diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-08-15 21:46:35 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-08-15 21:46:35 +0000 |
commit | 502af2167f7c218366666ca4944bd7cc54b5b19a (patch) | |
tree | a91fec5cc9769d260640bd91c6633cb9cf395524 /src/datacache | |
parent | 03af5a603b7cc53432249d5854cd412aa90dde0d (diff) | |
download | gnunet-502af2167f7c218366666ca4944bd7cc54b5b19a.tar.gz gnunet-502af2167f7c218366666ca4944bd7cc54b5b19a.zip |
indentation
Diffstat (limited to 'src/datacache')
-rw-r--r-- | src/datacache/datacache.c | 174 | ||||
-rw-r--r-- | src/datacache/perf_datacache.c | 119 | ||||
-rw-r--r-- | src/datacache/plugin_datacache_mysql.c | 769 | ||||
-rw-r--r-- | src/datacache/plugin_datacache_postgres.c | 416 | ||||
-rw-r--r-- | src/datacache/plugin_datacache_sqlite.c | 449 | ||||
-rw-r--r-- | src/datacache/plugin_datacache_template.c | 28 | ||||
-rw-r--r-- | src/datacache/test_datacache.c | 98 | ||||
-rw-r--r-- | src/datacache/test_datacache_quota.c | 84 |
8 files changed, 1005 insertions, 1132 deletions
diff --git a/src/datacache/datacache.c b/src/datacache/datacache.c index b937c63bb..a17eb9628 100644 --- a/src/datacache/datacache.c +++ b/src/datacache/datacache.c | |||
@@ -70,7 +70,7 @@ struct GNUNET_DATACACHE_Handle | |||
70 | * Name of the library (i.e. "gnunet_plugin_datacache_sqlite"). | 70 | * Name of the library (i.e. "gnunet_plugin_datacache_sqlite"). |
71 | */ | 71 | */ |
72 | char *lib_name; | 72 | char *lib_name; |
73 | 73 | ||
74 | /** | 74 | /** |
75 | * Name for the bloom filter file. | 75 | * Name for the bloom filter file. |
76 | */ | 76 | */ |
@@ -97,19 +97,16 @@ struct GNUNET_DATACACHE_Handle | |||
97 | * @param key key of the content that was deleted | 97 | * @param key key of the content that was deleted |
98 | * @param size number of bytes that were made available | 98 | * @param size number of bytes that were made available |
99 | */ | 99 | */ |
100 | static void | 100 | static void |
101 | env_delete_notify (void *cls, | 101 | env_delete_notify (void *cls, const GNUNET_HashCode * key, size_t size) |
102 | const GNUNET_HashCode *key, | ||
103 | size_t size) | ||
104 | { | 102 | { |
105 | struct GNUNET_DATACACHE_Handle * h = cls; | 103 | struct GNUNET_DATACACHE_Handle *h = cls; |
104 | |||
106 | GNUNET_assert (h->utilization >= size); | 105 | GNUNET_assert (h->utilization >= size); |
107 | h->utilization -= size; | 106 | h->utilization -= size; |
108 | GNUNET_CONTAINER_bloomfilter_remove (h->filter, key); | 107 | GNUNET_CONTAINER_bloomfilter_remove (h->filter, key); |
109 | GNUNET_STATISTICS_update (h->stats, | 108 | GNUNET_STATISTICS_update (h->stats, |
110 | gettext_noop ("# bytes stored"), | 109 | gettext_noop ("# bytes stored"), -size, GNUNET_NO); |
111 | -size, | ||
112 | GNUNET_NO); | ||
113 | } | 110 | } |
114 | 111 | ||
115 | 112 | ||
@@ -122,7 +119,7 @@ env_delete_notify (void *cls, | |||
122 | */ | 119 | */ |
123 | struct GNUNET_DATACACHE_Handle * | 120 | struct GNUNET_DATACACHE_Handle * |
124 | GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg, | 121 | GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg, |
125 | const char *section) | 122 | const char *section) |
126 | { | 123 | { |
127 | unsigned int bf_size; | 124 | unsigned int bf_size; |
128 | unsigned long long quota; | 125 | unsigned long long quota; |
@@ -131,45 +128,38 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
131 | char *name; | 128 | char *name; |
132 | 129 | ||
133 | if (GNUNET_OK != | 130 | if (GNUNET_OK != |
134 | GNUNET_CONFIGURATION_get_value_number (cfg, | 131 | GNUNET_CONFIGURATION_get_value_number (cfg, section, "QUOTA", "a)) |
135 | section, "QUOTA", "a)) | 132 | { |
136 | { | 133 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
137 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 134 | _("No `%s' specified for `%s' in configuration!\n"), |
138 | _("No `%s' specified for `%s' in configuration!\n"), | 135 | "QUOTA", section); |
139 | "QUOTA", | 136 | return NULL; |
140 | section); | 137 | } |
141 | return NULL; | ||
142 | } | ||
143 | if (GNUNET_OK != | 138 | if (GNUNET_OK != |
144 | GNUNET_CONFIGURATION_get_value_string (cfg, | 139 | GNUNET_CONFIGURATION_get_value_string (cfg, section, "DATABASE", &name)) |
145 | section, | 140 | { |
146 | "DATABASE", &name)) | 141 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
147 | { | 142 | _("No `%s' specified for `%s' in configuration!\n"), |
148 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 143 | "DATABASE", section); |
149 | _("No `%s' specified for `%s' in configuration!\n"), | 144 | return NULL; |
150 | "DATABASE", | 145 | } |
151 | section); | 146 | bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */ |
152 | return NULL; | 147 | |
153 | } | 148 | ret = GNUNET_malloc (sizeof (struct GNUNET_DATACACHE_Handle)); |
154 | bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */ | ||
155 | |||
156 | ret = GNUNET_malloc (sizeof(struct GNUNET_DATACACHE_Handle)); | ||
157 | ret->bloom_name = GNUNET_DISK_mktemp ("gnunet-datacachebloom"); | 149 | ret->bloom_name = GNUNET_DISK_mktemp ("gnunet-datacachebloom"); |
158 | if (NULL != ret->bloom_name) | 150 | if (NULL != ret->bloom_name) |
159 | { | 151 | { |
160 | ret->filter = GNUNET_CONTAINER_bloomfilter_load (ret->bloom_name, | 152 | ret->filter = GNUNET_CONTAINER_bloomfilter_load (ret->bloom_name, quota / 1024, /* 8 bit per entry in DB, expect 1k entries */ |
161 | quota / 1024, /* 8 bit per entry in DB, expect 1k entries */ | 153 | 5); |
162 | 5); | 154 | } |
163 | } | ||
164 | else | 155 | else |
165 | { | 156 | { |
166 | ret->filter = GNUNET_CONTAINER_bloomfilter_init (NULL, bf_size, 5); /* approx. 3% false positives at max use */ | 157 | ret->filter = GNUNET_CONTAINER_bloomfilter_init (NULL, bf_size, 5); /* approx. 3% false positives at max use */ |
167 | } | 158 | } |
168 | ret->stats = GNUNET_STATISTICS_create ("datacache", | 159 | ret->stats = GNUNET_STATISTICS_create ("datacache", cfg); |
169 | cfg); | ||
170 | ret->section = GNUNET_strdup (section); | 160 | ret->section = GNUNET_strdup (section); |
171 | ret->env.cfg = cfg; | 161 | ret->env.cfg = cfg; |
172 | ret->env.delete_notify = &env_delete_notify; | 162 | ret->env.delete_notify = &env_delete_notify; |
173 | ret->env.section = ret->section; | 163 | ret->env.section = ret->section; |
174 | ret->env.cls = ret; | 164 | ret->env.cls = ret; |
175 | ret->env.delete_notify = &env_delete_notify; | 165 | ret->env.delete_notify = &env_delete_notify; |
@@ -181,12 +171,12 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
181 | ret->lib_name = libname; | 171 | ret->lib_name = libname; |
182 | ret->api = GNUNET_PLUGIN_load (libname, &ret->env); | 172 | ret->api = GNUNET_PLUGIN_load (libname, &ret->env); |
183 | if (ret->api == NULL) | 173 | if (ret->api == NULL) |
184 | { | 174 | { |
185 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 175 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
186 | _("Failed to load datacache plugin for `%s'\n"), name); | 176 | _("Failed to load datacache plugin for `%s'\n"), name); |
187 | GNUNET_DATACACHE_destroy (ret); | 177 | GNUNET_DATACACHE_destroy (ret); |
188 | return NULL; | 178 | return NULL; |
189 | } | 179 | } |
190 | return ret; | 180 | return ret; |
191 | } | 181 | } |
192 | 182 | ||
@@ -196,7 +186,8 @@ GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
196 | * | 186 | * |
197 | * @param h handle to the datastore | 187 | * @param h handle to the datastore |
198 | */ | 188 | */ |
199 | void GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h) | 189 | void |
190 | GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h) | ||
200 | { | 191 | { |
201 | if (h->filter != NULL) | 192 | if (h->filter != NULL) |
202 | GNUNET_CONTAINER_bloomfilter_free (h->filter); | 193 | GNUNET_CONTAINER_bloomfilter_free (h->filter); |
@@ -206,15 +197,13 @@ void GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h) | |||
206 | GNUNET_free (h->short_name); | 197 | GNUNET_free (h->short_name); |
207 | GNUNET_free (h->section); | 198 | GNUNET_free (h->section); |
208 | if (h->bloom_name != NULL) | 199 | if (h->bloom_name != NULL) |
209 | { | 200 | { |
210 | if (0 != UNLINK (h->bloom_name)) | 201 | if (0 != UNLINK (h->bloom_name)) |
211 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | 202 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, |
212 | "unlink", | 203 | "unlink", h->bloom_name); |
213 | h->bloom_name); | 204 | GNUNET_free (h->bloom_name); |
214 | GNUNET_free (h->bloom_name); | 205 | } |
215 | } | 206 | GNUNET_STATISTICS_destroy (h->stats, GNUNET_NO); |
216 | GNUNET_STATISTICS_destroy (h->stats, | ||
217 | GNUNET_NO); | ||
218 | GNUNET_free (h); | 207 | GNUNET_free (h); |
219 | } | 208 | } |
220 | 209 | ||
@@ -230,31 +219,24 @@ void GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h) | |||
230 | * @param discard_time when to discard the value in any case | 219 | * @param discard_time when to discard the value in any case |
231 | * @return GNUNET_OK on success, GNUNET_SYSERR on error (full, etc.) | 220 | * @return GNUNET_OK on success, GNUNET_SYSERR on error (full, etc.) |
232 | */ | 221 | */ |
233 | int | 222 | int |
234 | GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h, | 223 | GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h, |
235 | const GNUNET_HashCode * key, | 224 | const GNUNET_HashCode * key, |
236 | size_t size, | 225 | size_t size, |
237 | const char *data, | 226 | const char *data, |
238 | enum GNUNET_BLOCK_Type type, | 227 | enum GNUNET_BLOCK_Type type, |
239 | struct GNUNET_TIME_Absolute discard_time) | 228 | struct GNUNET_TIME_Absolute discard_time) |
240 | { | 229 | { |
241 | uint32_t used; | 230 | uint32_t used; |
242 | 231 | ||
243 | used = h->api->put (h->api->cls, | 232 | used = h->api->put (h->api->cls, key, size, data, type, discard_time); |
244 | key, | ||
245 | size, | ||
246 | data, | ||
247 | type, | ||
248 | discard_time); | ||
249 | if (used == 0) | 233 | if (used == 0) |
250 | { | 234 | { |
251 | GNUNET_break (0); | 235 | GNUNET_break (0); |
252 | return GNUNET_SYSERR; | 236 | return GNUNET_SYSERR; |
253 | } | 237 | } |
254 | GNUNET_STATISTICS_update (h->stats, | 238 | GNUNET_STATISTICS_update (h->stats, |
255 | gettext_noop ("# bytes stored"), | 239 | gettext_noop ("# bytes stored"), size, GNUNET_NO); |
256 | size, | ||
257 | GNUNET_NO); | ||
258 | GNUNET_CONTAINER_bloomfilter_add (h->filter, key); | 240 | GNUNET_CONTAINER_bloomfilter_add (h->filter, key); |
259 | while (h->utilization + used > h->env.quota) | 241 | while (h->utilization + used > h->env.quota) |
260 | GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls)); | 242 | GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls)); |
@@ -274,31 +256,23 @@ GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h, | |||
274 | * @param iter_cls closure for iter | 256 | * @param iter_cls closure for iter |
275 | * @return the number of results found | 257 | * @return the number of results found |
276 | */ | 258 | */ |
277 | unsigned int | 259 | unsigned int |
278 | GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h, | 260 | GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h, |
279 | const GNUNET_HashCode * key, | 261 | const GNUNET_HashCode * key, |
280 | enum GNUNET_BLOCK_Type type, | 262 | enum GNUNET_BLOCK_Type type, |
281 | GNUNET_DATACACHE_Iterator iter, | 263 | GNUNET_DATACACHE_Iterator iter, void *iter_cls) |
282 | void *iter_cls) | ||
283 | { | 264 | { |
284 | GNUNET_STATISTICS_update (h->stats, | 265 | GNUNET_STATISTICS_update (h->stats, |
285 | gettext_noop ("# requests received"), | 266 | gettext_noop ("# requests received"), 1, GNUNET_NO); |
286 | 1, | 267 | if (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_test (h->filter, key)) |
287 | GNUNET_NO); | 268 | { |
288 | if (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_test (h->filter, | 269 | GNUNET_STATISTICS_update (h->stats, |
289 | key)) | 270 | gettext_noop |
290 | { | 271 | ("# requests filtered by bloom filter"), 1, |
291 | GNUNET_STATISTICS_update (h->stats, | 272 | GNUNET_NO); |
292 | gettext_noop ("# requests filtered by bloom filter"), | 273 | return 0; /* can not be present */ |
293 | 1, | 274 | } |
294 | GNUNET_NO); | 275 | return h->api->get (h->api->cls, key, type, iter, iter_cls); |
295 | return 0; /* can not be present */ | ||
296 | } | ||
297 | return h->api->get (h->api->cls, | ||
298 | key, | ||
299 | type, | ||
300 | iter, | ||
301 | iter_cls); | ||
302 | } | 276 | } |
303 | 277 | ||
304 | 278 | ||
diff --git a/src/datacache/perf_datacache.c b/src/datacache/perf_datacache.c index a3c59ff4f..3af76dbb6 100644 --- a/src/datacache/perf_datacache.c +++ b/src/datacache/perf_datacache.c | |||
@@ -45,14 +45,11 @@ static const char *plugin_name; | |||
45 | 45 | ||
46 | static int | 46 | static int |
47 | checkIt (void *cls, | 47 | checkIt (void *cls, |
48 | struct GNUNET_TIME_Absolute exp, | 48 | struct GNUNET_TIME_Absolute exp, |
49 | const GNUNET_HashCode * key, | 49 | const GNUNET_HashCode * key, |
50 | size_t size, | 50 | size_t size, const char *data, enum GNUNET_BLOCK_Type type) |
51 | const char *data, | ||
52 | enum GNUNET_BLOCK_Type type) | ||
53 | { | 51 | { |
54 | if ( (size == sizeof (GNUNET_HashCode)) && | 52 | if ((size == sizeof (GNUNET_HashCode)) && (0 == memcmp (data, cls, size))) |
55 | (0 == memcmp (data, cls, size)) ) | ||
56 | found++; | 53 | found++; |
57 | return GNUNET_OK; | 54 | return GNUNET_OK; |
58 | } | 55 | } |
@@ -61,8 +58,7 @@ checkIt (void *cls, | |||
61 | static void | 58 | static void |
62 | run (void *cls, | 59 | run (void *cls, |
63 | char *const *args, | 60 | char *const *args, |
64 | const char *cfgfile, | 61 | const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) |
65 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
66 | { | 62 | { |
67 | struct GNUNET_DATACACHE_Handle *h; | 63 | struct GNUNET_DATACACHE_Handle *h; |
68 | GNUNET_HashCode k; | 64 | GNUNET_HashCode k; |
@@ -71,66 +67,64 @@ run (void *cls, | |||
71 | struct GNUNET_TIME_Absolute start; | 67 | struct GNUNET_TIME_Absolute start; |
72 | unsigned int i; | 68 | unsigned int i; |
73 | char gstr[128]; | 69 | char gstr[128]; |
74 | 70 | ||
75 | ok = 0; | 71 | ok = 0; |
76 | h = GNUNET_DATACACHE_create (cfg, | 72 | h = GNUNET_DATACACHE_create (cfg, "perfcache"); |
77 | "perfcache"); | ||
78 | 73 | ||
79 | if (h == NULL) | 74 | if (h == NULL) |
80 | { | 75 | { |
81 | fprintf (stderr, | 76 | fprintf (stderr, |
82 | "Failed to initialize datacache. Database likely not setup, skipping test.\n"); | 77 | "Failed to initialize datacache. Database likely not setup, skipping test.\n"); |
83 | return; | 78 | return; |
84 | } | 79 | } |
85 | exp = GNUNET_TIME_absolute_get (); | 80 | exp = GNUNET_TIME_absolute_get (); |
86 | start = exp; | 81 | start = exp; |
87 | exp.abs_value += 5 * 60 * 1000; | 82 | exp.abs_value += 5 * 60 * 1000; |
88 | memset (&k, 0, sizeof (GNUNET_HashCode)); | 83 | memset (&k, 0, sizeof (GNUNET_HashCode)); |
89 | for (i = 0; i < ITERATIONS; i++) | 84 | for (i = 0; i < ITERATIONS; i++) |
90 | { | 85 | { |
91 | if (0 == i % (ITERATIONS / 80)) | 86 | if (0 == i % (ITERATIONS / 80)) |
92 | fprintf (stderr, "."); | 87 | fprintf (stderr, "."); |
93 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); | 88 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); |
94 | ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, | 89 | ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, |
95 | &k, | 90 | &k, |
96 | sizeof (GNUNET_HashCode), | 91 | sizeof (GNUNET_HashCode), |
97 | (const char *) &n, | 92 | (const char *) &n, |
98 | 1+i%16, | 93 | 1 + i % 16, exp)); |
99 | exp)); | 94 | k = n; |
100 | k = n; | 95 | } |
101 | } | ||
102 | fprintf (stderr, "\n"); | 96 | fprintf (stderr, "\n"); |
103 | fprintf (stdout, "Stored %u items in %llums\n", | 97 | fprintf (stdout, "Stored %u items in %llums\n", |
104 | ITERATIONS, | 98 | ITERATIONS, |
105 | (unsigned long long) GNUNET_TIME_absolute_get_duration(start).rel_value); | 99 | (unsigned long long) |
106 | GNUNET_snprintf (gstr, sizeof (gstr), | 100 | GNUNET_TIME_absolute_get_duration (start).rel_value); |
107 | "DATACACHE-%s", | 101 | GNUNET_snprintf (gstr, sizeof (gstr), "DATACACHE-%s", plugin_name); |
108 | plugin_name); | ||
109 | GAUGER (gstr, | 102 | GAUGER (gstr, |
110 | "Time to PUT item in datacache", | 103 | "Time to PUT item in datacache", |
111 | GNUNET_TIME_absolute_get_duration(start).rel_value / ITERATIONS, | 104 | GNUNET_TIME_absolute_get_duration (start).rel_value / ITERATIONS, |
112 | "ms/item"); | 105 | "ms/item"); |
113 | start = GNUNET_TIME_absolute_get (); | 106 | start = GNUNET_TIME_absolute_get (); |
114 | memset (&k, 0, sizeof (GNUNET_HashCode)); | 107 | memset (&k, 0, sizeof (GNUNET_HashCode)); |
115 | for (i = 0; i < ITERATIONS; i++) | 108 | for (i = 0; i < ITERATIONS; i++) |
116 | { | 109 | { |
117 | if (0 == i % (ITERATIONS / 80)) | 110 | if (0 == i % (ITERATIONS / 80)) |
118 | fprintf (stderr, "."); | 111 | fprintf (stderr, "."); |
119 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); | 112 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); |
120 | GNUNET_DATACACHE_get (h, &k, 1+i%16, | 113 | GNUNET_DATACACHE_get (h, &k, 1 + i % 16, &checkIt, &n); |
121 | &checkIt, &n); | 114 | k = n; |
122 | k = n; | 115 | } |
123 | } | ||
124 | fprintf (stderr, "\n"); | 116 | fprintf (stderr, "\n"); |
125 | fprintf (stdout, | 117 | fprintf (stdout, |
126 | "Found %u/%u items in %llums (%u were deleted during storage processing)\n", | 118 | "Found %u/%u items in %llums (%u were deleted during storage processing)\n", |
127 | found, ITERATIONS, | 119 | found, ITERATIONS, |
128 | (unsigned long long) GNUNET_TIME_absolute_get_duration(start).rel_value, | 120 | (unsigned long long) |
129 | ITERATIONS - found); | 121 | GNUNET_TIME_absolute_get_duration (start).rel_value, |
122 | ITERATIONS - found); | ||
130 | if (found > 0) | 123 | if (found > 0) |
131 | GAUGER (gstr, | 124 | GAUGER (gstr, |
132 | "Time to GET item from datacache", | 125 | "Time to GET item from datacache", |
133 | GNUNET_TIME_absolute_get_duration(start).rel_value / found, "ms/item"); | 126 | GNUNET_TIME_absolute_get_duration (start).rel_value / found, |
127 | "ms/item"); | ||
134 | GNUNET_DATACACHE_destroy (h); | 128 | GNUNET_DATACACHE_destroy (h); |
135 | ASSERT (ok == 0); | 129 | ASSERT (ok == 0); |
136 | return; | 130 | return; |
@@ -146,7 +140,8 @@ main (int argc, char *argv[]) | |||
146 | { | 140 | { |
147 | char *pos; | 141 | char *pos; |
148 | char cfg_name[128]; | 142 | char cfg_name[128]; |
149 | char *const xargv[] = { | 143 | |
144 | char *const xargv[] = { | ||
150 | "perf-datacache", | 145 | "perf-datacache", |
151 | "-c", | 146 | "-c", |
152 | cfg_name, | 147 | cfg_name, |
@@ -158,7 +153,7 @@ main (int argc, char *argv[]) | |||
158 | struct GNUNET_GETOPT_CommandLineOption options[] = { | 153 | struct GNUNET_GETOPT_CommandLineOption options[] = { |
159 | GNUNET_GETOPT_OPTION_END | 154 | GNUNET_GETOPT_OPTION_END |
160 | }; | 155 | }; |
161 | 156 | ||
162 | GNUNET_log_setup ("perf-datacache", | 157 | GNUNET_log_setup ("perf-datacache", |
163 | #if VERBOSE | 158 | #if VERBOSE |
164 | "DEBUG", | 159 | "DEBUG", |
@@ -168,22 +163,20 @@ main (int argc, char *argv[]) | |||
168 | NULL); | 163 | NULL); |
169 | /* determine name of plugin to use */ | 164 | /* determine name of plugin to use */ |
170 | plugin_name = argv[0]; | 165 | plugin_name = argv[0]; |
171 | while (NULL != (pos = strstr(plugin_name, "_"))) | 166 | while (NULL != (pos = strstr (plugin_name, "_"))) |
172 | plugin_name = pos+1; | 167 | plugin_name = pos + 1; |
173 | if (NULL != (pos = strstr(plugin_name, "."))) | 168 | if (NULL != (pos = strstr (plugin_name, "."))) |
174 | pos[0] = 0; | 169 | pos[0] = 0; |
175 | else | 170 | else |
176 | pos = (char *) plugin_name; | 171 | pos = (char *) plugin_name; |
177 | 172 | ||
178 | GNUNET_snprintf (cfg_name, | 173 | GNUNET_snprintf (cfg_name, |
179 | sizeof (cfg_name), | 174 | sizeof (cfg_name), |
180 | "perf_datacache_data_%s.conf", | 175 | "perf_datacache_data_%s.conf", plugin_name); |
181 | plugin_name); | ||
182 | if (pos != plugin_name) | 176 | if (pos != plugin_name) |
183 | pos[0] = '.'; | 177 | pos[0] = '.'; |
184 | GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, | 178 | GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, |
185 | xargv, "perf-datacache", "nohelp", | 179 | xargv, "perf-datacache", "nohelp", options, &run, NULL); |
186 | options, &run, NULL); | ||
187 | if (ok != 0) | 180 | if (ok != 0) |
188 | fprintf (stderr, "Missed some perfcases: %d\n", ok); | 181 | fprintf (stderr, "Missed some perfcases: %d\n", ok); |
189 | return ok; | 182 | return ok; |
diff --git a/src/datacache/plugin_datacache_mysql.c b/src/datacache/plugin_datacache_mysql.c index 8e477409e..f4530ccef 100644 --- a/src/datacache/plugin_datacache_mysql.c +++ b/src/datacache/plugin_datacache_mysql.c | |||
@@ -127,7 +127,7 @@ struct GNUNET_MysqlStatementHandle | |||
127 | /** | 127 | /** |
128 | * Context for all functions in this plugin. | 128 | * Context for all functions in this plugin. |
129 | */ | 129 | */ |
130 | struct Plugin | 130 | struct Plugin |
131 | { | 131 | { |
132 | /** | 132 | /** |
133 | * Our execution environment. | 133 | * Our execution environment. |
@@ -183,6 +183,7 @@ get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
183 | char *cnffile; | 183 | char *cnffile; |
184 | char *home_dir; | 184 | char *home_dir; |
185 | struct stat st; | 185 | struct stat st; |
186 | |||
186 | #ifndef WINDOWS | 187 | #ifndef WINDOWS |
187 | struct passwd *pw; | 188 | struct passwd *pw; |
188 | #endif | 189 | #endif |
@@ -191,44 +192,46 @@ get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
191 | #ifndef WINDOWS | 192 | #ifndef WINDOWS |
192 | pw = getpwuid (getuid ()); | 193 | pw = getpwuid (getuid ()); |
193 | if (!pw) | 194 | if (!pw) |
194 | { | 195 | { |
195 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | 196 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "getpwuid"); |
196 | "getpwuid"); | 197 | return NULL; |
197 | return NULL; | 198 | } |
198 | } | ||
199 | if (GNUNET_YES == | 199 | if (GNUNET_YES == |
200 | GNUNET_CONFIGURATION_have_value (cfg, | 200 | GNUNET_CONFIGURATION_have_value (cfg, "datacache-mysql", "CONFIG")) |
201 | "datacache-mysql", "CONFIG")) | 201 | { |
202 | { | 202 | GNUNET_assert (GNUNET_OK == |
203 | GNUNET_assert (GNUNET_OK == | 203 | GNUNET_CONFIGURATION_get_value_filename (cfg, |
204 | GNUNET_CONFIGURATION_get_value_filename (cfg, | 204 | "datacache-mysql", |
205 | "datacache-mysql", "CONFIG", &cnffile)); | 205 | "CONFIG", |
206 | configured = GNUNET_YES; | 206 | &cnffile)); |
207 | } | 207 | configured = GNUNET_YES; |
208 | } | ||
208 | else | 209 | else |
209 | { | 210 | { |
210 | home_dir = GNUNET_strdup (pw->pw_dir); | 211 | home_dir = GNUNET_strdup (pw->pw_dir); |
212 | GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); | ||
213 | GNUNET_free (home_dir); | ||
214 | configured = GNUNET_NO; | ||
215 | } | ||
211 | #else | 216 | #else |
212 | home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1); | 217 | home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1); |
213 | plibc_conv_to_win_path ("~/", home_dir); | 218 | plibc_conv_to_win_path ("~/", home_dir); |
219 | GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); | ||
220 | GNUNET_free (home_dir); | ||
221 | configured = GNUNET_NO; | ||
214 | #endif | 222 | #endif |
215 | GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); | ||
216 | GNUNET_free (home_dir); | ||
217 | configured = GNUNET_NO; | ||
218 | } | ||
219 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 223 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
220 | _("Trying to use file `%s' for MySQL configuration.\n"), | 224 | _("Trying to use file `%s' for MySQL configuration.\n"), cnffile); |
221 | cnffile); | ||
222 | if ((0 != STAT (cnffile, &st)) || | 225 | if ((0 != STAT (cnffile, &st)) || |
223 | (0 != ACCESS (cnffile, R_OK)) || (!S_ISREG (st.st_mode))) | 226 | (0 != ACCESS (cnffile, R_OK)) || (!S_ISREG (st.st_mode))) |
224 | { | 227 | { |
225 | if (configured == GNUNET_YES) | 228 | if (configured == GNUNET_YES) |
226 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 229 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
227 | _("Could not access file `%s': %s\n"), cnffile, | 230 | _("Could not access file `%s': %s\n"), cnffile, |
228 | STRERROR (errno)); | 231 | STRERROR (errno)); |
229 | GNUNET_free (cnffile); | 232 | GNUNET_free (cnffile); |
230 | return NULL; | 233 | return NULL; |
231 | } | 234 | } |
232 | return cnffile; | 235 | return cnffile; |
233 | } | 236 | } |
234 | 237 | ||
@@ -240,13 +243,10 @@ get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg) | |||
240 | * @param s prepared statement | 243 | * @param s prepared statement |
241 | */ | 244 | */ |
242 | static void | 245 | static void |
243 | prepared_statement_destroy (struct Plugin *plugin, | 246 | prepared_statement_destroy (struct Plugin *plugin, |
244 | struct GNUNET_MysqlStatementHandle | 247 | struct GNUNET_MysqlStatementHandle *s) |
245 | *s) | ||
246 | { | 248 | { |
247 | GNUNET_CONTAINER_DLL_remove (plugin->shead, | 249 | GNUNET_CONTAINER_DLL_remove (plugin->shead, plugin->stail, s); |
248 | plugin->stail, | ||
249 | s); | ||
250 | if (s->valid) | 250 | if (s->valid) |
251 | mysql_stmt_close (s->statement); | 251 | mysql_stmt_close (s->statement); |
252 | GNUNET_free (s->query); | 252 | GNUNET_free (s->query); |
@@ -262,13 +262,12 @@ static int | |||
262 | iclose (struct Plugin *plugin) | 262 | iclose (struct Plugin *plugin) |
263 | { | 263 | { |
264 | while (NULL != plugin->shead) | 264 | while (NULL != plugin->shead) |
265 | prepared_statement_destroy (plugin, | 265 | prepared_statement_destroy (plugin, plugin->shead); |
266 | plugin->shead); | ||
267 | if (plugin->dbf != NULL) | 266 | if (plugin->dbf != NULL) |
268 | { | 267 | { |
269 | mysql_close (plugin->dbf); | 268 | mysql_close (plugin->dbf); |
270 | plugin->dbf = NULL; | 269 | plugin->dbf = NULL; |
271 | } | 270 | } |
272 | return GNUNET_OK; | 271 | return GNUNET_OK; |
273 | } | 272 | } |
274 | 273 | ||
@@ -298,71 +297,75 @@ iopen (struct Plugin *ret) | |||
298 | mysql_options (ret->dbf, MYSQL_READ_DEFAULT_GROUP, "client"); | 297 | mysql_options (ret->dbf, MYSQL_READ_DEFAULT_GROUP, "client"); |
299 | reconnect = 0; | 298 | reconnect = 0; |
300 | mysql_options (ret->dbf, MYSQL_OPT_RECONNECT, &reconnect); | 299 | mysql_options (ret->dbf, MYSQL_OPT_RECONNECT, &reconnect); |
301 | mysql_options (ret->dbf, | 300 | mysql_options (ret->dbf, MYSQL_OPT_CONNECT_TIMEOUT, (const void *) &timeout); |
302 | MYSQL_OPT_CONNECT_TIMEOUT, (const void *) &timeout); | 301 | mysql_options (ret->dbf, MYSQL_SET_CHARSET_NAME, "UTF8"); |
303 | mysql_options(ret->dbf, MYSQL_SET_CHARSET_NAME, "UTF8"); | 302 | timeout = 60; /* in seconds */ |
304 | timeout = 60; /* in seconds */ | ||
305 | mysql_options (ret->dbf, MYSQL_OPT_READ_TIMEOUT, (const void *) &timeout); | 303 | mysql_options (ret->dbf, MYSQL_OPT_READ_TIMEOUT, (const void *) &timeout); |
306 | mysql_options (ret->dbf, MYSQL_OPT_WRITE_TIMEOUT, (const void *) &timeout); | 304 | mysql_options (ret->dbf, MYSQL_OPT_WRITE_TIMEOUT, (const void *) &timeout); |
307 | mysql_dbname = NULL; | 305 | mysql_dbname = NULL; |
308 | if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, | 306 | if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, |
309 | "datacache-mysql", "DATABASE")) | 307 | "datacache-mysql", |
310 | GNUNET_assert (GNUNET_OK == | 308 | "DATABASE")) |
311 | GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, | 309 | GNUNET_assert (GNUNET_OK == |
312 | "datacache-mysql", "DATABASE", | 310 | GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, |
313 | &mysql_dbname)); | 311 | "datacache-mysql", |
312 | "DATABASE", | ||
313 | &mysql_dbname)); | ||
314 | else | 314 | else |
315 | mysql_dbname = GNUNET_strdup ("gnunet"); | 315 | mysql_dbname = GNUNET_strdup ("gnunet"); |
316 | mysql_user = NULL; | 316 | mysql_user = NULL; |
317 | if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, | 317 | if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, |
318 | "datacache-mysql", "USER")) | 318 | "datacache-mysql", "USER")) |
319 | { | 319 | { |
320 | GNUNET_assert (GNUNET_OK == | 320 | GNUNET_assert (GNUNET_OK == |
321 | GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, | 321 | GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, |
322 | "datacache-mysql", "USER", | 322 | "datacache-mysql", |
323 | &mysql_user)); | 323 | "USER", &mysql_user)); |
324 | } | 324 | } |
325 | mysql_password = NULL; | 325 | mysql_password = NULL; |
326 | if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, | 326 | if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, |
327 | "datacache-mysql", "PASSWORD")) | 327 | "datacache-mysql", |
328 | { | 328 | "PASSWORD")) |
329 | GNUNET_assert (GNUNET_OK == | 329 | { |
330 | GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, | 330 | GNUNET_assert (GNUNET_OK == |
331 | "datacache-mysql", "PASSWORD", | 331 | GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, |
332 | &mysql_password)); | 332 | "datacache-mysql", |
333 | } | 333 | "PASSWORD", |
334 | &mysql_password)); | ||
335 | } | ||
334 | mysql_server = NULL; | 336 | mysql_server = NULL; |
335 | if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, | 337 | if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, |
336 | "datacache-mysql", "HOST")) | 338 | "datacache-mysql", "HOST")) |
337 | { | 339 | { |
338 | GNUNET_assert (GNUNET_OK == | 340 | GNUNET_assert (GNUNET_OK == |
339 | GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, | 341 | GNUNET_CONFIGURATION_get_value_string (ret->env->cfg, |
340 | "datacache-mysql", "HOST", | 342 | "datacache-mysql", |
341 | &mysql_server)); | 343 | "HOST", |
342 | } | 344 | &mysql_server)); |
345 | } | ||
343 | mysql_port = 0; | 346 | mysql_port = 0; |
344 | if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, | 347 | if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (ret->env->cfg, |
345 | "datacache-mysql", "PORT")) | 348 | "datacache-mysql", "PORT")) |
346 | { | 349 | { |
347 | GNUNET_assert (GNUNET_OK == | 350 | GNUNET_assert (GNUNET_OK == |
348 | GNUNET_CONFIGURATION_get_value_number (ret->env->cfg, "datacache-mysql", | 351 | GNUNET_CONFIGURATION_get_value_number (ret->env->cfg, |
349 | "PORT", &mysql_port)); | 352 | "datacache-mysql", |
350 | } | 353 | "PORT", &mysql_port)); |
354 | } | ||
351 | 355 | ||
352 | GNUNET_assert (mysql_dbname != NULL); | 356 | GNUNET_assert (mysql_dbname != NULL); |
353 | mysql_real_connect (ret->dbf, mysql_server, mysql_user, mysql_password, | 357 | mysql_real_connect (ret->dbf, mysql_server, mysql_user, mysql_password, |
354 | mysql_dbname, (unsigned int) mysql_port, NULL, | 358 | mysql_dbname, (unsigned int) mysql_port, NULL, |
355 | CLIENT_IGNORE_SIGPIPE); | 359 | CLIENT_IGNORE_SIGPIPE); |
356 | GNUNET_free_non_null (mysql_server); | 360 | GNUNET_free_non_null (mysql_server); |
357 | GNUNET_free_non_null (mysql_user); | 361 | GNUNET_free_non_null (mysql_user); |
358 | GNUNET_free_non_null (mysql_password); | 362 | GNUNET_free_non_null (mysql_password); |
359 | GNUNET_free (mysql_dbname); | 363 | GNUNET_free (mysql_dbname); |
360 | if (mysql_error (ret->dbf)[0]) | 364 | if (mysql_error (ret->dbf)[0]) |
361 | { | 365 | { |
362 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, | 366 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_real_connect", ret); |
363 | "mysql_real_connect", ret); | 367 | return GNUNET_SYSERR; |
364 | return GNUNET_SYSERR; | 368 | } |
365 | } | ||
366 | return GNUNET_OK; | 369 | return GNUNET_OK; |
367 | } | 370 | } |
368 | 371 | ||
@@ -373,19 +376,17 @@ iopen (struct Plugin *ret) | |||
373 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | 376 | * @return GNUNET_OK on success, GNUNET_SYSERR on error |
374 | */ | 377 | */ |
375 | static int | 378 | static int |
376 | run_statement (struct Plugin *plugin, | 379 | run_statement (struct Plugin *plugin, const char *statement) |
377 | const char *statement) | ||
378 | { | 380 | { |
379 | if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin))) | 381 | if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin))) |
380 | return GNUNET_SYSERR; | 382 | return GNUNET_SYSERR; |
381 | mysql_query (plugin->dbf, statement); | 383 | mysql_query (plugin->dbf, statement); |
382 | if (mysql_error (plugin->dbf)[0]) | 384 | if (mysql_error (plugin->dbf)[0]) |
383 | { | 385 | { |
384 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, | 386 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_query", plugin); |
385 | "mysql_query", plugin); | 387 | iclose (plugin); |
386 | iclose (plugin); | 388 | return GNUNET_SYSERR; |
387 | return GNUNET_SYSERR; | 389 | } |
388 | } | ||
389 | return GNUNET_OK; | 390 | return GNUNET_OK; |
390 | } | 391 | } |
391 | 392 | ||
@@ -395,16 +396,13 @@ run_statement (struct Plugin *plugin, | |||
395 | * @return NULL on error | 396 | * @return NULL on error |
396 | */ | 397 | */ |
397 | static struct GNUNET_MysqlStatementHandle * | 398 | static struct GNUNET_MysqlStatementHandle * |
398 | prepared_statement_create (struct Plugin *plugin, | 399 | prepared_statement_create (struct Plugin *plugin, const char *statement) |
399 | const char *statement) | ||
400 | { | 400 | { |
401 | struct GNUNET_MysqlStatementHandle *ret; | 401 | struct GNUNET_MysqlStatementHandle *ret; |
402 | 402 | ||
403 | ret = GNUNET_malloc (sizeof (struct GNUNET_MysqlStatementHandle)); | 403 | ret = GNUNET_malloc (sizeof (struct GNUNET_MysqlStatementHandle)); |
404 | ret->query = GNUNET_strdup (statement); | 404 | ret->query = GNUNET_strdup (statement); |
405 | GNUNET_CONTAINER_DLL_insert (plugin->shead, | 405 | GNUNET_CONTAINER_DLL_insert (plugin->shead, plugin->stail, ret); |
406 | plugin->stail, | ||
407 | ret); | ||
408 | return ret; | 406 | return ret; |
409 | } | 407 | } |
410 | 408 | ||
@@ -415,32 +413,27 @@ prepared_statement_create (struct Plugin *plugin, | |||
415 | * @return GNUNET_OK on success | 413 | * @return GNUNET_OK on success |
416 | */ | 414 | */ |
417 | static int | 415 | static int |
418 | prepare_statement (struct Plugin *plugin, | 416 | prepare_statement (struct Plugin *plugin, |
419 | struct GNUNET_MysqlStatementHandle *ret) | 417 | struct GNUNET_MysqlStatementHandle *ret) |
420 | { | 418 | { |
421 | if (GNUNET_YES == ret->valid) | 419 | if (GNUNET_YES == ret->valid) |
422 | return GNUNET_OK; | 420 | return GNUNET_OK; |
423 | if ((NULL == plugin->dbf) && | 421 | if ((NULL == plugin->dbf) && (GNUNET_OK != iopen (plugin))) |
424 | (GNUNET_OK != iopen (plugin))) | ||
425 | return GNUNET_SYSERR; | 422 | return GNUNET_SYSERR; |
426 | ret->statement = mysql_stmt_init (plugin->dbf); | 423 | ret->statement = mysql_stmt_init (plugin->dbf); |
427 | if (ret->statement == NULL) | 424 | if (ret->statement == NULL) |
428 | { | 425 | { |
429 | iclose (plugin); | 426 | iclose (plugin); |
430 | return GNUNET_SYSERR; | 427 | return GNUNET_SYSERR; |
431 | } | 428 | } |
432 | if (mysql_stmt_prepare (ret->statement, | 429 | if (mysql_stmt_prepare (ret->statement, ret->query, strlen (ret->query))) |
433 | ret->query, | 430 | { |
434 | strlen (ret->query))) | 431 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_stmt_prepare", plugin); |
435 | { | 432 | mysql_stmt_close (ret->statement); |
436 | LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, | 433 | ret->statement = NULL; |
437 | "mysql_stmt_prepare", | 434 | iclose (plugin); |
438 | plugin); | 435 | return GNUNET_SYSERR; |
439 | mysql_stmt_close (ret->statement); | 436 | } |
440 | ret->statement = NULL; | ||
441 | iclose (plugin); | ||
442 | return GNUNET_SYSERR; | ||
443 | } | ||
444 | ret->valid = GNUNET_YES; | 437 | ret->valid = GNUNET_YES; |
445 | return GNUNET_OK; | 438 | return GNUNET_OK; |
446 | 439 | ||
@@ -458,8 +451,7 @@ prepare_statement (struct Plugin *plugin, | |||
458 | */ | 451 | */ |
459 | static int | 452 | static int |
460 | init_params (struct Plugin *plugin, | 453 | init_params (struct Plugin *plugin, |
461 | struct GNUNET_MysqlStatementHandle *s, | 454 | struct GNUNET_MysqlStatementHandle *s, va_list ap) |
462 | va_list ap) | ||
463 | { | 455 | { |
464 | MYSQL_BIND qbind[MAX_PARAM]; | 456 | MYSQL_BIND qbind[MAX_PARAM]; |
465 | unsigned int pc; | 457 | unsigned int pc; |
@@ -468,68 +460,72 @@ init_params (struct Plugin *plugin, | |||
468 | 460 | ||
469 | pc = mysql_stmt_param_count (s->statement); | 461 | pc = mysql_stmt_param_count (s->statement); |
470 | if (pc > MAX_PARAM) | 462 | if (pc > MAX_PARAM) |
471 | { | 463 | { |
472 | /* increase internal constant! */ | 464 | /* increase internal constant! */ |
473 | GNUNET_break (0); | 465 | GNUNET_break (0); |
474 | return GNUNET_SYSERR; | 466 | return GNUNET_SYSERR; |
475 | } | 467 | } |
476 | memset (qbind, 0, sizeof (qbind)); | 468 | memset (qbind, 0, sizeof (qbind)); |
477 | off = 0; | 469 | off = 0; |
478 | ft = 0; | 470 | ft = 0; |
479 | while ( (pc > 0) && (-1 != (int) (ft = va_arg (ap, enum enum_field_types))) ) | 471 | while ((pc > 0) && (-1 != (int) (ft = va_arg (ap, enum enum_field_types)))) |
480 | { | 472 | { |
481 | qbind[off].buffer_type = ft; | 473 | qbind[off].buffer_type = ft; |
482 | switch (ft) | 474 | switch (ft) |
483 | { | ||
484 | case MYSQL_TYPE_FLOAT: | ||
485 | qbind[off].buffer = va_arg (ap, float *); | ||
486 | break; | ||
487 | case MYSQL_TYPE_LONGLONG: | ||
488 | qbind[off].buffer = va_arg (ap, unsigned long long *); | ||
489 | qbind[off].is_unsigned = va_arg (ap, int); | ||
490 | break; | ||
491 | case MYSQL_TYPE_LONG: | ||
492 | qbind[off].buffer = va_arg (ap, unsigned int *); | ||
493 | qbind[off].is_unsigned = va_arg (ap, int); | ||
494 | break; | ||
495 | case MYSQL_TYPE_VAR_STRING: | ||
496 | case MYSQL_TYPE_STRING: | ||
497 | case MYSQL_TYPE_BLOB: | ||
498 | qbind[off].buffer = va_arg (ap, void *); | ||
499 | qbind[off].buffer_length = va_arg (ap, unsigned long); | ||
500 | qbind[off].length = va_arg (ap, unsigned long *); | ||
501 | break; | ||
502 | default: | ||
503 | /* unsupported type */ | ||
504 | GNUNET_break (0); | ||
505 | return GNUNET_SYSERR; | ||
506 | } | ||
507 | pc--; | ||
508 | off++; | ||
509 | } | ||
510 | if (! ( (pc == 0) && (-1 != (int) ft) && (va_arg (ap, int) == -1)) ) | ||
511 | { | 475 | { |
476 | case MYSQL_TYPE_FLOAT: | ||
477 | qbind[off].buffer = va_arg (ap, float *); | ||
478 | |||
479 | break; | ||
480 | case MYSQL_TYPE_LONGLONG: | ||
481 | qbind[off].buffer = va_arg (ap, unsigned long long *); | ||
482 | qbind[off].is_unsigned = va_arg (ap, int); | ||
483 | |||
484 | break; | ||
485 | case MYSQL_TYPE_LONG: | ||
486 | qbind[off].buffer = va_arg (ap, unsigned int *); | ||
487 | qbind[off].is_unsigned = va_arg (ap, int); | ||
488 | |||
489 | break; | ||
490 | case MYSQL_TYPE_VAR_STRING: | ||
491 | case MYSQL_TYPE_STRING: | ||
492 | case MYSQL_TYPE_BLOB: | ||
493 | qbind[off].buffer = va_arg (ap, void *); | ||
494 | qbind[off].buffer_length = va_arg (ap, unsigned long); | ||
495 | qbind[off].length = va_arg (ap, unsigned long *); | ||
496 | |||
497 | break; | ||
498 | default: | ||
499 | /* unsupported type */ | ||
512 | GNUNET_break (0); | 500 | GNUNET_break (0); |
513 | return GNUNET_SYSERR; | 501 | return GNUNET_SYSERR; |
514 | } | 502 | } |
503 | pc--; | ||
504 | off++; | ||
505 | } | ||
506 | if (!((pc == 0) && (-1 != (int) ft) && (va_arg (ap, int) == -1))) | ||
507 | { | ||
508 | GNUNET_break (0); | ||
509 | return GNUNET_SYSERR; | ||
510 | } | ||
515 | if (mysql_stmt_bind_param (s->statement, qbind)) | 511 | if (mysql_stmt_bind_param (s->statement, qbind)) |
516 | { | 512 | { |
517 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 513 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
518 | _("`%s' failed at %s:%d with error: %s\n"), | 514 | _("`%s' failed at %s:%d with error: %s\n"), |
519 | "mysql_stmt_bind_param", | 515 | "mysql_stmt_bind_param", |
520 | __FILE__, __LINE__, mysql_stmt_error (s->statement)); | 516 | __FILE__, __LINE__, mysql_stmt_error (s->statement)); |
521 | iclose (plugin); | 517 | iclose (plugin); |
522 | return GNUNET_SYSERR; | 518 | return GNUNET_SYSERR; |
523 | } | 519 | } |
524 | if (mysql_stmt_execute (s->statement)) | 520 | if (mysql_stmt_execute (s->statement)) |
525 | { | 521 | { |
526 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 522 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
527 | _("`%s' failed at %s:%d with error: %s\n"), | 523 | _("`%s' failed at %s:%d with error: %s\n"), |
528 | "mysql_stmt_execute", | 524 | "mysql_stmt_execute", |
529 | __FILE__, __LINE__, mysql_stmt_error (s->statement)); | 525 | __FILE__, __LINE__, mysql_stmt_error (s->statement)); |
530 | iclose (plugin); | 526 | iclose (plugin); |
531 | return GNUNET_SYSERR; | 527 | return GNUNET_SYSERR; |
532 | } | 528 | } |
533 | return GNUNET_OK; | 529 | return GNUNET_OK; |
534 | } | 530 | } |
535 | 531 | ||
@@ -565,13 +561,12 @@ typedef int (*GNUNET_MysqlDataProcessor) (void *cls, | |||
565 | */ | 561 | */ |
566 | static int | 562 | static int |
567 | prepared_statement_run_select (struct Plugin *plugin, | 563 | prepared_statement_run_select (struct Plugin *plugin, |
568 | struct GNUNET_MysqlStatementHandle | 564 | struct GNUNET_MysqlStatementHandle |
569 | *s, | 565 | *s, |
570 | unsigned int result_size, | 566 | unsigned int result_size, |
571 | MYSQL_BIND * results, | 567 | MYSQL_BIND * results, |
572 | GNUNET_MysqlDataProcessor | 568 | GNUNET_MysqlDataProcessor |
573 | processor, void *processor_cls, | 569 | processor, void *processor_cls, ...) |
574 | ...) | ||
575 | { | 570 | { |
576 | va_list ap; | 571 | va_list ap; |
577 | int ret; | 572 | int ret; |
@@ -579,54 +574,54 @@ prepared_statement_run_select (struct Plugin *plugin, | |||
579 | int total; | 574 | int total; |
580 | 575 | ||
581 | if (GNUNET_OK != prepare_statement (plugin, s)) | 576 | if (GNUNET_OK != prepare_statement (plugin, s)) |
582 | { | 577 | { |
583 | GNUNET_break (0); | 578 | GNUNET_break (0); |
584 | return GNUNET_SYSERR; | 579 | return GNUNET_SYSERR; |
585 | } | 580 | } |
586 | va_start (ap, processor_cls); | 581 | va_start (ap, processor_cls); |
587 | if (GNUNET_OK != init_params (plugin, s, ap)) | 582 | if (GNUNET_OK != init_params (plugin, s, ap)) |
588 | { | 583 | { |
589 | GNUNET_break (0); | 584 | GNUNET_break (0); |
590 | va_end (ap); | 585 | va_end (ap); |
591 | return GNUNET_SYSERR; | 586 | return GNUNET_SYSERR; |
592 | } | 587 | } |
593 | va_end (ap); | 588 | va_end (ap); |
594 | rsize = mysql_stmt_field_count (s->statement); | 589 | rsize = mysql_stmt_field_count (s->statement); |
595 | if (rsize > result_size) | 590 | if (rsize > result_size) |
596 | { | 591 | { |
597 | GNUNET_break (0); | 592 | GNUNET_break (0); |
598 | return GNUNET_SYSERR; | 593 | return GNUNET_SYSERR; |
599 | } | 594 | } |
600 | if (mysql_stmt_bind_result (s->statement, results)) | 595 | if (mysql_stmt_bind_result (s->statement, results)) |
596 | { | ||
597 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
598 | _("`%s' failed at %s:%d with error: %s\n"), | ||
599 | "mysql_stmt_bind_result", | ||
600 | __FILE__, __LINE__, mysql_stmt_error (s->statement)); | ||
601 | iclose (plugin); | ||
602 | return GNUNET_SYSERR; | ||
603 | } | ||
604 | |||
605 | total = 0; | ||
606 | while (1) | ||
607 | { | ||
608 | ret = mysql_stmt_fetch (s->statement); | ||
609 | if (ret == MYSQL_NO_DATA) | ||
610 | break; | ||
611 | if (ret != 0) | ||
601 | { | 612 | { |
602 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 613 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
603 | _("`%s' failed at %s:%d with error: %s\n"), | 614 | _("`%s' failed at %s:%d with error: %s\n"), |
604 | "mysql_stmt_bind_result", | 615 | "mysql_stmt_fetch", |
605 | __FILE__, __LINE__, mysql_stmt_error (s->statement)); | 616 | __FILE__, __LINE__, mysql_stmt_error (s->statement)); |
606 | iclose (plugin); | 617 | iclose (plugin); |
607 | return GNUNET_SYSERR; | 618 | return GNUNET_SYSERR; |
608 | } | 619 | } |
609 | 620 | if (processor != NULL) | |
610 | total = 0; | 621 | if (GNUNET_OK != processor (processor_cls, rsize, results)) |
611 | while (1) | ||
612 | { | ||
613 | ret = mysql_stmt_fetch (s->statement); | ||
614 | if (ret == MYSQL_NO_DATA) | ||
615 | break; | 622 | break; |
616 | if (ret != 0) | 623 | total++; |
617 | { | 624 | } |
618 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
619 | _("`%s' failed at %s:%d with error: %s\n"), | ||
620 | "mysql_stmt_fetch", | ||
621 | __FILE__, __LINE__, mysql_stmt_error (s->statement)); | ||
622 | iclose (plugin); | ||
623 | return GNUNET_SYSERR; | ||
624 | } | ||
625 | if (processor != NULL) | ||
626 | if (GNUNET_OK != processor (processor_cls, rsize, results)) | ||
627 | break; | ||
628 | total++; | ||
629 | } | ||
630 | mysql_stmt_reset (s->statement); | 625 | mysql_stmt_reset (s->statement); |
631 | return total; | 626 | return total; |
632 | } | 627 | } |
@@ -648,8 +643,8 @@ prepared_statement_run_select (struct Plugin *plugin, | |||
648 | */ | 643 | */ |
649 | static int | 644 | static int |
650 | prepared_statement_run (struct Plugin *plugin, | 645 | prepared_statement_run (struct Plugin *plugin, |
651 | struct GNUNET_MysqlStatementHandle *s, | 646 | struct GNUNET_MysqlStatementHandle *s, |
652 | unsigned long long *insert_id, ...) | 647 | unsigned long long *insert_id, ...) |
653 | { | 648 | { |
654 | va_list ap; | 649 | va_list ap; |
655 | int affected; | 650 | int affected; |
@@ -658,10 +653,10 @@ prepared_statement_run (struct Plugin *plugin, | |||
658 | return GNUNET_SYSERR; | 653 | return GNUNET_SYSERR; |
659 | va_start (ap, insert_id); | 654 | va_start (ap, insert_id); |
660 | if (GNUNET_OK != init_params (plugin, s, ap)) | 655 | if (GNUNET_OK != init_params (plugin, s, ap)) |
661 | { | 656 | { |
662 | va_end (ap); | 657 | va_end (ap); |
663 | return GNUNET_SYSERR; | 658 | return GNUNET_SYSERR; |
664 | } | 659 | } |
665 | va_end (ap); | 660 | va_end (ap); |
666 | affected = mysql_stmt_affected_rows (s->statement); | 661 | affected = mysql_stmt_affected_rows (s->statement); |
667 | if (NULL != insert_id) | 662 | if (NULL != insert_id) |
@@ -718,13 +713,13 @@ itable (struct Plugin *plugin) | |||
718 | * @param discard_time when to discard the value in any case | 713 | * @param discard_time when to discard the value in any case |
719 | * @return 0 on error, number of bytes used otherwise | 714 | * @return 0 on error, number of bytes used otherwise |
720 | */ | 715 | */ |
721 | static size_t | 716 | static size_t |
722 | mysql_plugin_put (void *cls, | 717 | mysql_plugin_put (void *cls, |
723 | const GNUNET_HashCode * key, | 718 | const GNUNET_HashCode * key, |
724 | size_t size, | 719 | size_t size, |
725 | const char *data, | 720 | const char *data, |
726 | enum GNUNET_BLOCK_Type type, | 721 | enum GNUNET_BLOCK_Type type, |
727 | struct GNUNET_TIME_Absolute discard_time) | 722 | struct GNUNET_TIME_Absolute discard_time) |
728 | { | 723 | { |
729 | struct Plugin *plugin = cls; | 724 | struct Plugin *plugin = cls; |
730 | struct GNUNET_TIME_Absolute now; | 725 | struct GNUNET_TIME_Absolute now; |
@@ -751,25 +746,23 @@ mysql_plugin_put (void *cls, | |||
751 | v_discard_time = (unsigned long long) discard_time.abs_value; | 746 | v_discard_time = (unsigned long long) discard_time.abs_value; |
752 | if (GNUNET_OK == | 747 | if (GNUNET_OK == |
753 | prepared_statement_run (plugin, | 748 | prepared_statement_run (plugin, |
754 | plugin->update_value, | 749 | plugin->update_value, |
755 | NULL, | 750 | NULL, |
756 | MYSQL_TYPE_LONGLONG, | 751 | MYSQL_TYPE_LONGLONG, |
757 | &v_now, | 752 | &v_now, |
758 | GNUNET_YES, | 753 | GNUNET_YES, |
759 | MYSQL_TYPE_LONGLONG, | 754 | MYSQL_TYPE_LONGLONG, |
760 | &v_discard_time, | 755 | &v_discard_time, |
761 | GNUNET_YES, | 756 | GNUNET_YES, |
762 | MYSQL_TYPE_BLOB, | 757 | MYSQL_TYPE_BLOB, |
763 | key, | 758 | key, |
764 | sizeof (GNUNET_HashCode), | 759 | sizeof (GNUNET_HashCode), |
765 | &k_length, | 760 | &k_length, |
766 | MYSQL_TYPE_BLOB, | 761 | MYSQL_TYPE_BLOB, |
767 | &vhash, | 762 | &vhash, |
768 | sizeof (GNUNET_HashCode), | 763 | sizeof (GNUNET_HashCode), |
769 | &h_length, | 764 | &h_length, |
770 | MYSQL_TYPE_LONG, | 765 | MYSQL_TYPE_LONG, &v_type, GNUNET_YES, -1)) |
771 | &v_type, | ||
772 | GNUNET_YES, -1)) | ||
773 | return GNUNET_OK; | 766 | return GNUNET_OK; |
774 | 767 | ||
775 | /* now try INSERT */ | 768 | /* now try INSERT */ |
@@ -778,34 +771,33 @@ mysql_plugin_put (void *cls, | |||
778 | v_length = size; | 771 | v_length = size; |
779 | if (GNUNET_OK != | 772 | if (GNUNET_OK != |
780 | (ret = prepared_statement_run (plugin, | 773 | (ret = prepared_statement_run (plugin, |
781 | plugin->insert_value, | 774 | plugin->insert_value, |
782 | NULL, | 775 | NULL, |
783 | MYSQL_TYPE_LONG, | 776 | MYSQL_TYPE_LONG, |
784 | &type, | 777 | &type, |
785 | GNUNET_YES, | 778 | GNUNET_YES, |
786 | MYSQL_TYPE_LONGLONG, | 779 | MYSQL_TYPE_LONGLONG, |
787 | &v_now, | 780 | &v_now, |
788 | GNUNET_YES, | 781 | GNUNET_YES, |
789 | MYSQL_TYPE_LONGLONG, | 782 | MYSQL_TYPE_LONGLONG, |
790 | &v_discard_time, | 783 | &v_discard_time, |
791 | GNUNET_YES, | 784 | GNUNET_YES, |
792 | MYSQL_TYPE_BLOB, | 785 | MYSQL_TYPE_BLOB, |
793 | key, | 786 | key, |
794 | sizeof (GNUNET_HashCode), | 787 | sizeof (GNUNET_HashCode), |
795 | &k_length, | 788 | &k_length, |
796 | MYSQL_TYPE_BLOB, | 789 | MYSQL_TYPE_BLOB, |
797 | &vhash, | 790 | &vhash, |
798 | sizeof (GNUNET_HashCode), | 791 | sizeof (GNUNET_HashCode), |
799 | &h_length, | 792 | &h_length, |
800 | MYSQL_TYPE_BLOB, | 793 | MYSQL_TYPE_BLOB, |
801 | data, | 794 | data, |
802 | (unsigned long) size, | 795 | (unsigned long) size, &v_length, -1))) |
803 | &v_length, -1))) | 796 | { |
804 | { | 797 | if (ret == GNUNET_SYSERR) |
805 | if (ret == GNUNET_SYSERR) | 798 | itable (plugin); |
806 | itable (plugin); | 799 | return GNUNET_SYSERR; |
807 | return GNUNET_SYSERR; | 800 | } |
808 | } | ||
809 | return size + OVERHEAD; | 801 | return size + OVERHEAD; |
810 | } | 802 | } |
811 | 803 | ||
@@ -828,12 +820,11 @@ return_ok (void *cls, unsigned int num_values, MYSQL_BIND * values) | |||
828 | * @param iter_cls closure for iter | 820 | * @param iter_cls closure for iter |
829 | * @return the number of results found | 821 | * @return the number of results found |
830 | */ | 822 | */ |
831 | static unsigned int | 823 | static unsigned int |
832 | mysql_plugin_get (void *cls, | 824 | mysql_plugin_get (void *cls, |
833 | const GNUNET_HashCode * key, | 825 | const GNUNET_HashCode * key, |
834 | enum GNUNET_BLOCK_Type type, | 826 | enum GNUNET_BLOCK_Type type, |
835 | GNUNET_DATACACHE_Iterator iter, | 827 | GNUNET_DATACACHE_Iterator iter, void *iter_cls) |
836 | void *iter_cls) | ||
837 | { | 828 | { |
838 | struct Plugin *plugin = cls; | 829 | struct Plugin *plugin = cls; |
839 | MYSQL_BIND rbind[3]; | 830 | MYSQL_BIND rbind[3]; |
@@ -862,79 +853,72 @@ mysql_plugin_get (void *cls, | |||
862 | v_now = (unsigned long long) now.abs_value; | 853 | v_now = (unsigned long long) now.abs_value; |
863 | if ((GNUNET_OK != | 854 | if ((GNUNET_OK != |
864 | (ret = prepared_statement_run_select (plugin, | 855 | (ret = prepared_statement_run_select (plugin, |
865 | plugin->count_value, | 856 | plugin->count_value, |
866 | 1, | 857 | 1, |
867 | rbind, | 858 | rbind, |
868 | return_ok, | 859 | return_ok, |
869 | NULL, | 860 | NULL, |
870 | MYSQL_TYPE_BLOB, | 861 | MYSQL_TYPE_BLOB, |
871 | key, | 862 | key, |
872 | sizeof | 863 | sizeof |
873 | (GNUNET_HashCode), | 864 | (GNUNET_HashCode), |
874 | &h_length, | 865 | &h_length, |
875 | MYSQL_TYPE_LONG, | 866 | MYSQL_TYPE_LONG, |
876 | &v_type, GNUNET_YES, | 867 | &v_type, GNUNET_YES, |
877 | MYSQL_TYPE_LONGLONG, | 868 | MYSQL_TYPE_LONGLONG, |
878 | &v_now, GNUNET_YES, | 869 | &v_now, GNUNET_YES, |
879 | -1))) | 870 | -1))) || (-1 == total)) |
880 | || (-1 == total)) | 871 | { |
881 | { | 872 | if (ret == GNUNET_SYSERR) |
882 | if (ret == GNUNET_SYSERR) | 873 | itable (plugin); |
883 | itable (plugin); | 874 | return GNUNET_SYSERR; |
884 | return GNUNET_SYSERR; | 875 | } |
885 | } | ||
886 | if ((iter == NULL) || (total == 0)) | 876 | if ((iter == NULL) || (total == 0)) |
887 | return (int) total; | 877 | return (int) total; |
888 | 878 | ||
889 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total); | 879 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total); |
890 | cnt = 0; | 880 | cnt = 0; |
891 | while (cnt < total) | 881 | while (cnt < total) |
882 | { | ||
883 | memset (rbind, 0, sizeof (rbind)); | ||
884 | rbind[0].buffer_type = MYSQL_TYPE_BLOB; | ||
885 | rbind[0].buffer_length = sizeof (buffer); | ||
886 | rbind[0].length = &v_length; | ||
887 | rbind[0].buffer = buffer; | ||
888 | rbind[1].buffer_type = MYSQL_TYPE_LONGLONG; | ||
889 | rbind[1].is_unsigned = 1; | ||
890 | rbind[1].buffer = &v_expire; | ||
891 | off = (off + 1) % total; | ||
892 | if (GNUNET_OK != | ||
893 | (ret = prepared_statement_run_select (plugin, | ||
894 | plugin->select_value, | ||
895 | 2, | ||
896 | rbind, | ||
897 | return_ok, | ||
898 | NULL, | ||
899 | MYSQL_TYPE_BLOB, | ||
900 | key, | ||
901 | sizeof | ||
902 | (GNUNET_HashCode), | ||
903 | &h_length, | ||
904 | MYSQL_TYPE_LONG, | ||
905 | &v_type, | ||
906 | GNUNET_YES, | ||
907 | MYSQL_TYPE_LONGLONG, | ||
908 | &v_now, | ||
909 | GNUNET_YES, | ||
910 | MYSQL_TYPE_LONG, | ||
911 | &off, GNUNET_YES, -1))) | ||
892 | { | 912 | { |
893 | memset (rbind, 0, sizeof (rbind)); | 913 | if (ret == GNUNET_SYSERR) |
894 | rbind[0].buffer_type = MYSQL_TYPE_BLOB; | 914 | itable (plugin); |
895 | rbind[0].buffer_length = sizeof (buffer); | 915 | return GNUNET_SYSERR; |
896 | rbind[0].length = &v_length; | ||
897 | rbind[0].buffer = buffer; | ||
898 | rbind[1].buffer_type = MYSQL_TYPE_LONGLONG; | ||
899 | rbind[1].is_unsigned = 1; | ||
900 | rbind[1].buffer = &v_expire; | ||
901 | off = (off + 1) % total; | ||
902 | if (GNUNET_OK != | ||
903 | (ret = prepared_statement_run_select (plugin, | ||
904 | plugin->select_value, | ||
905 | 2, | ||
906 | rbind, | ||
907 | return_ok, | ||
908 | NULL, | ||
909 | MYSQL_TYPE_BLOB, | ||
910 | key, | ||
911 | sizeof | ||
912 | (GNUNET_HashCode), | ||
913 | &h_length, | ||
914 | MYSQL_TYPE_LONG, | ||
915 | &v_type, | ||
916 | GNUNET_YES, | ||
917 | MYSQL_TYPE_LONGLONG, | ||
918 | &v_now, | ||
919 | GNUNET_YES, | ||
920 | MYSQL_TYPE_LONG, | ||
921 | &off, | ||
922 | GNUNET_YES, | ||
923 | -1))) | ||
924 | { | ||
925 | if (ret == GNUNET_SYSERR) | ||
926 | itable (plugin); | ||
927 | return GNUNET_SYSERR; | ||
928 | } | ||
929 | cnt++; | ||
930 | expire.abs_value = v_expire; | ||
931 | if (GNUNET_OK != iter (iter_cls, | ||
932 | expire, | ||
933 | key, | ||
934 | v_length, buffer, | ||
935 | type)) | ||
936 | break; | ||
937 | } | 916 | } |
917 | cnt++; | ||
918 | expire.abs_value = v_expire; | ||
919 | if (GNUNET_OK != iter (iter_cls, expire, key, v_length, buffer, type)) | ||
920 | break; | ||
921 | } | ||
938 | return cnt; | 922 | return cnt; |
939 | } | 923 | } |
940 | 924 | ||
@@ -945,8 +929,8 @@ mysql_plugin_get (void *cls, | |||
945 | * | 929 | * |
946 | * @param cls closure (our "struct Plugin") | 930 | * @param cls closure (our "struct Plugin") |
947 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | 931 | * @return GNUNET_OK on success, GNUNET_SYSERR on error |
948 | */ | 932 | */ |
949 | static int | 933 | static int |
950 | mysql_plugin_del (void *cls) | 934 | mysql_plugin_del (void *cls) |
951 | { | 935 | { |
952 | struct Plugin *plugin = cls; | 936 | struct Plugin *plugin = cls; |
@@ -982,40 +966,37 @@ mysql_plugin_del (void *cls) | |||
982 | rbind[3].buffer = buffer; | 966 | rbind[3].buffer = buffer; |
983 | if ((GNUNET_OK != | 967 | if ((GNUNET_OK != |
984 | (ret = prepared_statement_run_select (plugin, | 968 | (ret = prepared_statement_run_select (plugin, |
985 | plugin->select_old_value, | 969 | plugin->select_old_value, |
986 | 4, | 970 | 4, |
987 | rbind, | 971 | rbind, |
988 | return_ok, | 972 | return_ok, |
989 | NULL, | 973 | NULL, |
990 | -1))) || | 974 | -1))) || |
991 | (GNUNET_OK != | 975 | (GNUNET_OK != |
992 | (ret = prepared_statement_run (plugin, | 976 | (ret = prepared_statement_run (plugin, |
993 | plugin->delete_value, | 977 | plugin->delete_value, |
994 | NULL, | 978 | NULL, |
995 | MYSQL_TYPE_BLOB, | 979 | MYSQL_TYPE_BLOB, |
996 | &v_key, | 980 | &v_key, |
997 | sizeof (GNUNET_HashCode), | 981 | sizeof (GNUNET_HashCode), |
998 | &k_length, | 982 | &k_length, |
999 | MYSQL_TYPE_BLOB, | 983 | MYSQL_TYPE_BLOB, |
1000 | &vhash, | 984 | &vhash, |
1001 | sizeof (GNUNET_HashCode), | 985 | sizeof (GNUNET_HashCode), |
1002 | &h_length, | 986 | &h_length, |
1003 | MYSQL_TYPE_LONG, | 987 | MYSQL_TYPE_LONG, |
1004 | &v_type, | 988 | &v_type, |
1005 | GNUNET_YES, | 989 | GNUNET_YES, |
1006 | MYSQL_TYPE_BLOB, | 990 | MYSQL_TYPE_BLOB, |
1007 | buffer, | 991 | buffer, |
1008 | (unsigned long) | 992 | (unsigned long) |
1009 | sizeof (buffer), | 993 | sizeof (buffer), &v_length, -1)))) |
1010 | &v_length, -1)))) | 994 | { |
1011 | { | 995 | if (ret == GNUNET_SYSERR) |
1012 | if (ret == GNUNET_SYSERR) | 996 | itable (plugin); |
1013 | itable (plugin); | 997 | return GNUNET_SYSERR; |
1014 | return GNUNET_SYSERR; | 998 | } |
1015 | } | 999 | plugin->env->delete_notify (plugin->env->cls, &v_key, v_length + OVERHEAD); |
1016 | plugin->env->delete_notify (plugin->env->cls, | ||
1017 | &v_key, | ||
1018 | v_length + OVERHEAD); | ||
1019 | 1000 | ||
1020 | return GNUNET_OK; | 1001 | return GNUNET_OK; |
1021 | } | 1002 | } |
@@ -1037,21 +1018,19 @@ libgnunet_plugin_datacache_mysql_init (void *cls) | |||
1037 | plugin = GNUNET_malloc (sizeof (struct Plugin)); | 1018 | plugin = GNUNET_malloc (sizeof (struct Plugin)); |
1038 | plugin->env = env; | 1019 | plugin->env = env; |
1039 | plugin->cnffile = get_my_cnf_path (env->cfg); | 1020 | plugin->cnffile = get_my_cnf_path (env->cfg); |
1040 | if (GNUNET_OK != | 1021 | if (GNUNET_OK != iopen (plugin)) |
1041 | iopen (plugin)) | 1022 | { |
1042 | { | 1023 | GNUNET_free_non_null (plugin->cnffile); |
1043 | GNUNET_free_non_null (plugin->cnffile); | 1024 | GNUNET_free (plugin); |
1044 | GNUNET_free (plugin); | 1025 | return NULL; |
1045 | return NULL; | 1026 | } |
1046 | } | 1027 | if (GNUNET_OK != itable (plugin)) |
1047 | if (GNUNET_OK != | 1028 | { |
1048 | itable (plugin)) | 1029 | iclose (plugin); |
1049 | { | 1030 | GNUNET_free_non_null (plugin->cnffile); |
1050 | iclose (plugin); | 1031 | GNUNET_free (plugin); |
1051 | GNUNET_free_non_null (plugin->cnffile); | 1032 | return NULL; |
1052 | GNUNET_free (plugin); | 1033 | } |
1053 | return NULL; | ||
1054 | } | ||
1055 | api = GNUNET_malloc (sizeof (struct GNUNET_DATACACHE_PluginFunctions)); | 1034 | api = GNUNET_malloc (sizeof (struct GNUNET_DATACACHE_PluginFunctions)); |
1056 | api->cls = plugin; | 1035 | api->cls = plugin; |
1057 | api->get = &mysql_plugin_get; | 1036 | api->get = &mysql_plugin_get; |
diff --git a/src/datacache/plugin_datacache_postgres.c b/src/datacache/plugin_datacache_postgres.c index e391469fd..fdc377b8f 100644 --- a/src/datacache/plugin_datacache_postgres.c +++ b/src/datacache/plugin_datacache_postgres.c | |||
@@ -38,7 +38,7 @@ | |||
38 | /** | 38 | /** |
39 | * Context for all functions in this plugin. | 39 | * Context for all functions in this plugin. |
40 | */ | 40 | */ |
41 | struct Plugin | 41 | struct Plugin |
42 | { | 42 | { |
43 | /** | 43 | /** |
44 | * Our execution environment. | 44 | * Our execution environment. |
@@ -62,27 +62,28 @@ struct Plugin | |||
62 | */ | 62 | */ |
63 | static int | 63 | static int |
64 | check_result (struct Plugin *plugin, | 64 | check_result (struct Plugin *plugin, |
65 | PGresult * ret, | 65 | PGresult * ret, |
66 | int expected_status, | 66 | int expected_status, |
67 | const char *command, const char *args, int line) | 67 | const char *command, const char *args, int line) |
68 | { | 68 | { |
69 | if (ret == NULL) | 69 | if (ret == NULL) |
70 | { | 70 | { |
71 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 71 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
72 | "datastore-postgres", | 72 | "datastore-postgres", |
73 | "Postgres failed to allocate result for `%s:%s' at %d\n", | 73 | "Postgres failed to allocate result for `%s:%s' at %d\n", |
74 | command, args, line); | 74 | command, args, line); |
75 | return GNUNET_SYSERR; | 75 | return GNUNET_SYSERR; |
76 | } | 76 | } |
77 | if (PQresultStatus (ret) != expected_status) | 77 | if (PQresultStatus (ret) != expected_status) |
78 | { | 78 | { |
79 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 79 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
80 | "datastore-postgres", | 80 | "datastore-postgres", |
81 | _("`%s:%s' failed at %s:%d with error: %s"), | 81 | _("`%s:%s' failed at %s:%d with error: %s"), |
82 | command, args, __FILE__, line, PQerrorMessage (plugin->dbh)); | 82 | command, args, __FILE__, line, |
83 | PQclear (ret); | 83 | PQerrorMessage (plugin->dbh)); |
84 | return GNUNET_SYSERR; | 84 | PQclear (ret); |
85 | } | 85 | return GNUNET_SYSERR; |
86 | } | ||
86 | return GNUNET_OK; | 87 | return GNUNET_OK; |
87 | } | 88 | } |
88 | 89 | ||
@@ -91,14 +92,13 @@ check_result (struct Plugin *plugin, | |||
91 | * Run simple SQL statement (without results). | 92 | * Run simple SQL statement (without results). |
92 | */ | 93 | */ |
93 | static int | 94 | static int |
94 | pq_exec (struct Plugin *plugin, | 95 | pq_exec (struct Plugin *plugin, const char *sql, int line) |
95 | const char *sql, int line) | ||
96 | { | 96 | { |
97 | PGresult *ret; | 97 | PGresult *ret; |
98 | |||
98 | ret = PQexec (plugin->dbh, sql); | 99 | ret = PQexec (plugin->dbh, sql); |
99 | if (GNUNET_OK != check_result (plugin, | 100 | if (GNUNET_OK != check_result (plugin, |
100 | ret, | 101 | ret, PGRES_COMMAND_OK, "PQexec", sql, line)) |
101 | PGRES_COMMAND_OK, "PQexec", sql, line)) | ||
102 | return GNUNET_SYSERR; | 102 | return GNUNET_SYSERR; |
103 | PQclear (ret); | 103 | PQclear (ret); |
104 | return GNUNET_OK; | 104 | return GNUNET_OK; |
@@ -110,13 +110,13 @@ pq_exec (struct Plugin *plugin, | |||
110 | */ | 110 | */ |
111 | static int | 111 | static int |
112 | pq_prepare (struct Plugin *plugin, | 112 | pq_prepare (struct Plugin *plugin, |
113 | const char *name, const char *sql, int nparms, int line) | 113 | const char *name, const char *sql, int nparms, int line) |
114 | { | 114 | { |
115 | PGresult *ret; | 115 | PGresult *ret; |
116 | |||
116 | ret = PQprepare (plugin->dbh, name, sql, nparms, NULL); | 117 | ret = PQprepare (plugin->dbh, name, sql, nparms, NULL); |
117 | if (GNUNET_OK != | 118 | if (GNUNET_OK != |
118 | check_result (plugin, | 119 | check_result (plugin, ret, PGRES_COMMAND_OK, "PQprepare", sql, line)) |
119 | ret, PGRES_COMMAND_OK, "PQprepare", sql, line)) | ||
120 | return GNUNET_SYSERR; | 120 | return GNUNET_SYSERR; |
121 | PQclear (ret); | 121 | PQclear (ret); |
122 | return GNUNET_OK; | 122 | return GNUNET_OK; |
@@ -134,128 +134,121 @@ init_connection (struct Plugin *plugin) | |||
134 | PGresult *ret; | 134 | PGresult *ret; |
135 | 135 | ||
136 | /* Open database and precompile statements */ | 136 | /* Open database and precompile statements */ |
137 | if (GNUNET_OK != | 137 | if (GNUNET_OK != |
138 | GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, | 138 | GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, |
139 | "datacache-postgres", | 139 | "datacache-postgres", |
140 | "CONFIG", | 140 | "CONFIG", &conninfo)) |
141 | &conninfo)) | ||
142 | conninfo = NULL; | 141 | conninfo = NULL; |
143 | plugin->dbh = PQconnectdb (conninfo == NULL ? "" : conninfo); | 142 | plugin->dbh = PQconnectdb (conninfo == NULL ? "" : conninfo); |
144 | GNUNET_free_non_null (conninfo); | 143 | GNUNET_free_non_null (conninfo); |
145 | if (NULL == plugin->dbh) | 144 | if (NULL == plugin->dbh) |
146 | { | 145 | { |
147 | /* FIXME: warn about out-of-memory? */ | 146 | /* FIXME: warn about out-of-memory? */ |
148 | return GNUNET_SYSERR; | 147 | return GNUNET_SYSERR; |
149 | } | 148 | } |
150 | if (PQstatus (plugin->dbh) != CONNECTION_OK) | 149 | if (PQstatus (plugin->dbh) != CONNECTION_OK) |
151 | { | 150 | { |
152 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | 151 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, |
153 | "datacache-postgres", | 152 | "datacache-postgres", |
154 | _("Unable to initialize Postgres: %s"), | 153 | _("Unable to initialize Postgres: %s"), |
155 | PQerrorMessage (plugin->dbh)); | 154 | PQerrorMessage (plugin->dbh)); |
156 | PQfinish (plugin->dbh); | 155 | PQfinish (plugin->dbh); |
157 | plugin->dbh = NULL; | 156 | plugin->dbh = NULL; |
158 | return GNUNET_SYSERR; | 157 | return GNUNET_SYSERR; |
159 | } | 158 | } |
160 | ret = PQexec (plugin->dbh, | 159 | ret = PQexec (plugin->dbh, |
161 | "CREATE TEMPORARY TABLE gn090dc (" | 160 | "CREATE TEMPORARY TABLE gn090dc (" |
162 | " type INTEGER NOT NULL DEFAULT 0," | 161 | " type INTEGER NOT NULL DEFAULT 0," |
163 | " discard_time BIGINT NOT NULL DEFAULT 0," | 162 | " discard_time BIGINT NOT NULL DEFAULT 0," |
164 | " key BYTEA NOT NULL DEFAULT ''," | 163 | " key BYTEA NOT NULL DEFAULT ''," |
165 | " value BYTEA NOT NULL DEFAULT '')" "WITH OIDS"); | 164 | " value BYTEA NOT NULL DEFAULT '')" "WITH OIDS"); |
166 | if ( (ret == NULL) || | 165 | if ((ret == NULL) || ((PQresultStatus (ret) != PGRES_COMMAND_OK) && (0 != strcmp ("42P07", /* duplicate table */ |
167 | ( (PQresultStatus (ret) != PGRES_COMMAND_OK) && | 166 | PQresultErrorField |
168 | (0 != strcmp ("42P07", /* duplicate table */ | 167 | (ret, |
169 | PQresultErrorField | 168 | PG_DIAG_SQLSTATE))))) |
170 | (ret, | 169 | { |
171 | PG_DIAG_SQLSTATE))))) | 170 | (void) check_result (plugin, |
171 | ret, PGRES_COMMAND_OK, "CREATE TABLE", "gn090dc", | ||
172 | __LINE__); | ||
173 | PQfinish (plugin->dbh); | ||
174 | plugin->dbh = NULL; | ||
175 | return GNUNET_SYSERR; | ||
176 | } | ||
177 | if (PQresultStatus (ret) == PGRES_COMMAND_OK) | ||
178 | { | ||
179 | if ((GNUNET_OK != | ||
180 | pq_exec (plugin, "CREATE INDEX idx_key ON gn090dc (key)", __LINE__)) || | ||
181 | (GNUNET_OK != | ||
182 | pq_exec (plugin, "CREATE INDEX idx_dt ON gn090dc (discard_time)", | ||
183 | __LINE__))) | ||
172 | { | 184 | { |
173 | (void) check_result (plugin, | 185 | PQclear (ret); |
174 | ret, PGRES_COMMAND_OK, "CREATE TABLE", "gn090dc", __LINE__); | ||
175 | PQfinish (plugin->dbh); | 186 | PQfinish (plugin->dbh); |
176 | plugin->dbh = NULL; | 187 | plugin->dbh = NULL; |
177 | return GNUNET_SYSERR; | 188 | return GNUNET_SYSERR; |
178 | } | 189 | } |
179 | if (PQresultStatus (ret) == PGRES_COMMAND_OK) | 190 | } |
180 | { | ||
181 | if ((GNUNET_OK != | ||
182 | pq_exec (plugin, "CREATE INDEX idx_key ON gn090dc (key)", __LINE__)) || | ||
183 | (GNUNET_OK != | ||
184 | pq_exec (plugin, "CREATE INDEX idx_dt ON gn090dc (discard_time)", | ||
185 | __LINE__)) ) | ||
186 | { | ||
187 | PQclear (ret); | ||
188 | PQfinish (plugin->dbh); | ||
189 | plugin->dbh = NULL; | ||
190 | return GNUNET_SYSERR; | ||
191 | } | ||
192 | } | ||
193 | PQclear (ret); | 191 | PQclear (ret); |
194 | #if 1 | 192 | #if 1 |
195 | ret = PQexec (plugin->dbh, | 193 | ret = PQexec (plugin->dbh, |
196 | "ALTER TABLE gn090dc ALTER value SET STORAGE EXTERNAL"); | 194 | "ALTER TABLE gn090dc ALTER value SET STORAGE EXTERNAL"); |
197 | if (GNUNET_OK != | 195 | if (GNUNET_OK != |
198 | check_result (plugin, | 196 | check_result (plugin, |
199 | ret, PGRES_COMMAND_OK, | 197 | ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090dc", __LINE__)) |
200 | "ALTER TABLE", "gn090dc", __LINE__)) | 198 | { |
201 | { | 199 | PQfinish (plugin->dbh); |
202 | PQfinish (plugin->dbh); | 200 | plugin->dbh = NULL; |
203 | plugin->dbh = NULL; | 201 | return GNUNET_SYSERR; |
204 | return GNUNET_SYSERR; | 202 | } |
205 | } | ||
206 | PQclear (ret); | 203 | PQclear (ret); |
207 | ret = PQexec (plugin->dbh, | 204 | ret = PQexec (plugin->dbh, "ALTER TABLE gn090dc ALTER key SET STORAGE PLAIN"); |
208 | "ALTER TABLE gn090dc ALTER key SET STORAGE PLAIN"); | ||
209 | if (GNUNET_OK != | 205 | if (GNUNET_OK != |
210 | check_result (plugin, | 206 | check_result (plugin, |
211 | ret, PGRES_COMMAND_OK, | 207 | ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090dc", __LINE__)) |
212 | "ALTER TABLE", "gn090dc", __LINE__)) | 208 | { |
213 | { | 209 | PQfinish (plugin->dbh); |
214 | PQfinish (plugin->dbh); | 210 | plugin->dbh = NULL; |
215 | plugin->dbh = NULL; | 211 | return GNUNET_SYSERR; |
216 | return GNUNET_SYSERR; | 212 | } |
217 | } | ||
218 | PQclear (ret); | 213 | PQclear (ret); |
219 | #endif | 214 | #endif |
220 | if ((GNUNET_OK != | 215 | if ((GNUNET_OK != |
221 | pq_prepare (plugin, | 216 | pq_prepare (plugin, |
222 | "getkt", | 217 | "getkt", |
223 | "SELECT discard_time,type,value FROM gn090dc " | 218 | "SELECT discard_time,type,value FROM gn090dc " |
224 | "WHERE key=$1 AND type=$2 ", | 219 | "WHERE key=$1 AND type=$2 ", |
225 | 2, | 220 | 2, |
226 | __LINE__)) || | 221 | __LINE__)) || |
227 | (GNUNET_OK != | 222 | (GNUNET_OK != |
228 | pq_prepare (plugin, | 223 | pq_prepare (plugin, |
229 | "getk", | 224 | "getk", |
230 | "SELECT discard_time,type,value FROM gn090dc " | 225 | "SELECT discard_time,type,value FROM gn090dc " |
231 | "WHERE key=$1", | 226 | "WHERE key=$1", |
232 | 1, | 227 | 1, |
233 | __LINE__)) || | 228 | __LINE__)) || |
234 | (GNUNET_OK != | 229 | (GNUNET_OK != |
235 | pq_prepare (plugin, | 230 | pq_prepare (plugin, |
236 | "getm", | 231 | "getm", |
237 | "SELECT length(value),oid,key FROM gn090dc " | 232 | "SELECT length(value),oid,key FROM gn090dc " |
238 | "ORDER BY discard_time ASC LIMIT 1", | 233 | "ORDER BY discard_time ASC LIMIT 1", |
239 | 0, | 234 | 0, |
240 | __LINE__)) || | 235 | __LINE__)) || |
241 | (GNUNET_OK != | 236 | (GNUNET_OK != |
242 | pq_prepare (plugin, | 237 | pq_prepare (plugin, |
243 | "delrow", | 238 | "delrow", |
244 | "DELETE FROM gn090dc WHERE oid=$1", | 239 | "DELETE FROM gn090dc WHERE oid=$1", |
245 | 1, | 240 | 1, |
246 | __LINE__)) || | 241 | __LINE__)) || |
247 | (GNUNET_OK != | 242 | (GNUNET_OK != |
248 | pq_prepare (plugin, | 243 | pq_prepare (plugin, |
249 | "put", | 244 | "put", |
250 | "INSERT INTO gn090dc (type, discard_time, key, value) " | 245 | "INSERT INTO gn090dc (type, discard_time, key, value) " |
251 | "VALUES ($1, $2, $3, $4)", | 246 | "VALUES ($1, $2, $3, $4)", 4, __LINE__))) |
252 | 4, | 247 | { |
253 | __LINE__)) ) | 248 | PQfinish (plugin->dbh); |
254 | { | 249 | plugin->dbh = NULL; |
255 | PQfinish (plugin->dbh); | 250 | return GNUNET_SYSERR; |
256 | plugin->dbh = NULL; | 251 | } |
257 | return GNUNET_SYSERR; | ||
258 | } | ||
259 | return GNUNET_OK; | 252 | return GNUNET_OK; |
260 | } | 253 | } |
261 | 254 | ||
@@ -267,8 +260,7 @@ init_connection (struct Plugin *plugin) | |||
267 | * @return GNUNET_OK on success | 260 | * @return GNUNET_OK on success |
268 | */ | 261 | */ |
269 | static int | 262 | static int |
270 | delete_by_rowid (struct Plugin *plugin, | 263 | delete_by_rowid (struct Plugin *plugin, uint32_t rowid) |
271 | uint32_t rowid) | ||
272 | { | 264 | { |
273 | uint32_t brow = htonl (rowid); | 265 | uint32_t brow = htonl (rowid); |
274 | const char *paramValues[] = { (const char *) &brow }; | 266 | const char *paramValues[] = { (const char *) &brow }; |
@@ -281,11 +273,11 @@ delete_by_rowid (struct Plugin *plugin, | |||
281 | 1, paramValues, paramLengths, paramFormats, 1); | 273 | 1, paramValues, paramLengths, paramFormats, 1); |
282 | if (GNUNET_OK != | 274 | if (GNUNET_OK != |
283 | check_result (plugin, | 275 | check_result (plugin, |
284 | ret, PGRES_COMMAND_OK, "PQexecPrepared", "delrow", | 276 | ret, PGRES_COMMAND_OK, "PQexecPrepared", "delrow", |
285 | __LINE__)) | 277 | __LINE__)) |
286 | { | 278 | { |
287 | return GNUNET_SYSERR; | 279 | return GNUNET_SYSERR; |
288 | } | 280 | } |
289 | PQclear (ret); | 281 | PQclear (ret); |
290 | return GNUNET_OK; | 282 | return GNUNET_OK; |
291 | } | 283 | } |
@@ -302,18 +294,19 @@ delete_by_rowid (struct Plugin *plugin, | |||
302 | * @param discard_time when to discard the value in any case | 294 | * @param discard_time when to discard the value in any case |
303 | * @return 0 on error, number of bytes used otherwise | 295 | * @return 0 on error, number of bytes used otherwise |
304 | */ | 296 | */ |
305 | static size_t | 297 | static size_t |
306 | postgres_plugin_put (void *cls, | 298 | postgres_plugin_put (void *cls, |
307 | const GNUNET_HashCode * key, | 299 | const GNUNET_HashCode * key, |
308 | size_t size, | 300 | size_t size, |
309 | const char *data, | 301 | const char *data, |
310 | enum GNUNET_BLOCK_Type type, | 302 | enum GNUNET_BLOCK_Type type, |
311 | struct GNUNET_TIME_Absolute discard_time) | 303 | struct GNUNET_TIME_Absolute discard_time) |
312 | { | 304 | { |
313 | struct Plugin *plugin = cls; | 305 | struct Plugin *plugin = cls; |
314 | PGresult *ret; | 306 | PGresult *ret; |
315 | uint32_t btype = htonl (type); | 307 | uint32_t btype = htonl (type); |
316 | uint64_t bexpi = GNUNET_TIME_absolute_hton (discard_time).abs_value__; | 308 | uint64_t bexpi = GNUNET_TIME_absolute_hton (discard_time).abs_value__; |
309 | |||
317 | const char *paramValues[] = { | 310 | const char *paramValues[] = { |
318 | (const char *) &btype, | 311 | (const char *) &btype, |
319 | (const char *) &bexpi, | 312 | (const char *) &bexpi, |
@@ -350,15 +343,15 @@ postgres_plugin_put (void *cls, | |||
350 | * @param iter_cls closure for iter | 343 | * @param iter_cls closure for iter |
351 | * @return the number of results found | 344 | * @return the number of results found |
352 | */ | 345 | */ |
353 | static unsigned int | 346 | static unsigned int |
354 | postgres_plugin_get (void *cls, | 347 | postgres_plugin_get (void *cls, |
355 | const GNUNET_HashCode * key, | 348 | const GNUNET_HashCode * key, |
356 | enum GNUNET_BLOCK_Type type, | 349 | enum GNUNET_BLOCK_Type type, |
357 | GNUNET_DATACACHE_Iterator iter, | 350 | GNUNET_DATACACHE_Iterator iter, void *iter_cls) |
358 | void *iter_cls) | ||
359 | { | 351 | { |
360 | struct Plugin *plugin = cls; | 352 | struct Plugin *plugin = cls; |
361 | uint32_t btype = htonl (type); | 353 | uint32_t btype = htonl (type); |
354 | |||
362 | const char *paramValues[] = { | 355 | const char *paramValues[] = { |
363 | (const char *) key, | 356 | (const char *) key, |
364 | (const char *) &btype, | 357 | (const char *) &btype, |
@@ -376,80 +369,73 @@ postgres_plugin_get (void *cls, | |||
376 | 369 | ||
377 | cnt = 0; | 370 | cnt = 0; |
378 | res = PQexecPrepared (plugin->dbh, | 371 | res = PQexecPrepared (plugin->dbh, |
379 | (type == 0) ? "getk" : "getkt", | 372 | (type == 0) ? "getk" : "getkt", |
380 | (type == 0) ? 1 : 2, | 373 | (type == 0) ? 1 : 2, |
381 | paramValues, | 374 | paramValues, paramLengths, paramFormats, 1); |
382 | paramLengths, | ||
383 | paramFormats, | ||
384 | 1); | ||
385 | if (GNUNET_OK != check_result (plugin, | 375 | if (GNUNET_OK != check_result (plugin, |
386 | res, | 376 | res, |
387 | PGRES_TUPLES_OK, | 377 | PGRES_TUPLES_OK, |
388 | "PQexecPrepared", | 378 | "PQexecPrepared", |
389 | (type == 0) ? "getk" : "getkt", | 379 | (type == 0) ? "getk" : "getkt", __LINE__)) |
390 | __LINE__)) | 380 | { |
391 | { | ||
392 | #if DEBUG_POSTGRES | 381 | #if DEBUG_POSTGRES |
393 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 382 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
394 | "datacache-postgres", | 383 | "datacache-postgres", |
395 | "Ending iteration (postgres error)\n"); | 384 | "Ending iteration (postgres error)\n"); |
396 | #endif | 385 | #endif |
397 | return 0; | 386 | return 0; |
398 | } | 387 | } |
399 | 388 | ||
400 | if (0 == (cnt = PQntuples (res))) | 389 | if (0 == (cnt = PQntuples (res))) |
401 | { | 390 | { |
402 | /* no result */ | 391 | /* no result */ |
403 | #if DEBUG_POSTGRES | 392 | #if DEBUG_POSTGRES |
404 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 393 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
405 | "datacache-postgres", | 394 | "datacache-postgres", |
406 | "Ending iteration (no more results)\n"); | 395 | "Ending iteration (no more results)\n"); |
407 | #endif | 396 | #endif |
408 | PQclear (res); | 397 | PQclear (res); |
409 | return 0; | 398 | return 0; |
410 | } | 399 | } |
411 | if (iter == NULL) | 400 | if (iter == NULL) |
412 | { | 401 | { |
413 | PQclear (res); | 402 | PQclear (res); |
414 | return cnt; | 403 | return cnt; |
415 | } | 404 | } |
416 | if ( (3 != PQnfields (res)) || | 405 | if ((3 != PQnfields (res)) || |
417 | (sizeof (uint64_t) != PQfsize (res, 0)) || | 406 | (sizeof (uint64_t) != PQfsize (res, 0)) || |
418 | (sizeof (uint32_t) != PQfsize (res, 1))) | 407 | (sizeof (uint32_t) != PQfsize (res, 1))) |
419 | { | 408 | { |
420 | GNUNET_break (0); | 409 | GNUNET_break (0); |
421 | PQclear (res); | 410 | PQclear (res); |
422 | return 0; | 411 | return 0; |
423 | } | 412 | } |
424 | for (i=0;i<cnt;i++) | 413 | for (i = 0; i < cnt; i++) |
425 | { | 414 | { |
426 | expiration_time.abs_value = GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, i, 0)); | 415 | expiration_time.abs_value = |
427 | type = ntohl (*(uint32_t *) PQgetvalue (res, i, 1)); | 416 | GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, i, 0)); |
428 | size = PQgetlength (res, i, 2); | 417 | type = ntohl (*(uint32_t *) PQgetvalue (res, i, 1)); |
418 | size = PQgetlength (res, i, 2); | ||
429 | #if DEBUG_POSTGRES | 419 | #if DEBUG_POSTGRES |
430 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 420 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
431 | "datacache-postgres", | 421 | "datacache-postgres", |
432 | "Found result of size %u bytes and type %u in database\n", | 422 | "Found result of size %u bytes and type %u in database\n", |
433 | (unsigned int) size, | 423 | (unsigned int) size, (unsigned int) type); |
434 | (unsigned int) type); | ||
435 | #endif | 424 | #endif |
436 | if (GNUNET_SYSERR == | 425 | if (GNUNET_SYSERR == |
437 | iter (iter_cls, | 426 | iter (iter_cls, |
438 | expiration_time, | 427 | expiration_time, |
439 | key, | 428 | key, size, PQgetvalue (res, i, 2), (enum GNUNET_BLOCK_Type) type)) |
440 | size, | 429 | { |
441 | PQgetvalue (res, i, 2), | ||
442 | (enum GNUNET_BLOCK_Type) type)) | ||
443 | { | ||
444 | #if DEBUG_POSTGRES | 430 | #if DEBUG_POSTGRES |
445 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 431 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
446 | "datacache-postgres", | 432 | "datacache-postgres", |
447 | "Ending iteration (client error)\n"); | 433 | "Ending iteration (client error)\n"); |
448 | #endif | 434 | #endif |
449 | PQclear (res); | 435 | PQclear (res); |
450 | return cnt; | 436 | return cnt; |
451 | } | 437 | } |
452 | } | 438 | } |
453 | PQclear (res); | 439 | PQclear (res); |
454 | return cnt; | 440 | return cnt; |
455 | } | 441 | } |
@@ -461,8 +447,8 @@ postgres_plugin_get (void *cls, | |||
461 | * | 447 | * |
462 | * @param cls closure (our "struct Plugin") | 448 | * @param cls closure (our "struct Plugin") |
463 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | 449 | * @return GNUNET_OK on success, GNUNET_SYSERR on error |
464 | */ | 450 | */ |
465 | static int | 451 | static int |
466 | postgres_plugin_del (void *cls) | 452 | postgres_plugin_del (void *cls) |
467 | { | 453 | { |
468 | struct Plugin *plugin = cls; | 454 | struct Plugin *plugin = cls; |
@@ -471,55 +457,46 @@ postgres_plugin_del (void *cls) | |||
471 | GNUNET_HashCode key; | 457 | GNUNET_HashCode key; |
472 | PGresult *res; | 458 | PGresult *res; |
473 | 459 | ||
474 | res = PQexecPrepared (plugin->dbh, | 460 | res = PQexecPrepared (plugin->dbh, "getm", 0, NULL, NULL, NULL, 1); |
475 | "getm", | ||
476 | 0, NULL, NULL, NULL, | ||
477 | 1); | ||
478 | if (GNUNET_OK != check_result (plugin, | 461 | if (GNUNET_OK != check_result (plugin, |
479 | res, | 462 | res, |
480 | PGRES_TUPLES_OK, | 463 | PGRES_TUPLES_OK, |
481 | "PQexecPrepared", | 464 | "PQexecPrepared", "getm", __LINE__)) |
482 | "getm", | 465 | { |
483 | __LINE__)) | ||
484 | { | ||
485 | #if DEBUG_POSTGRES | 466 | #if DEBUG_POSTGRES |
486 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 467 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
487 | "datacache-postgres", | 468 | "datacache-postgres", |
488 | "Ending iteration (postgres error)\n"); | 469 | "Ending iteration (postgres error)\n"); |
489 | #endif | 470 | #endif |
490 | return 0; | 471 | return 0; |
491 | } | 472 | } |
492 | if (0 == PQntuples (res)) | 473 | if (0 == PQntuples (res)) |
493 | { | 474 | { |
494 | /* no result */ | 475 | /* no result */ |
495 | #if DEBUG_POSTGRES | 476 | #if DEBUG_POSTGRES |
496 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 477 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
497 | "datacache-postgres", | 478 | "datacache-postgres", |
498 | "Ending iteration (no more results)\n"); | 479 | "Ending iteration (no more results)\n"); |
499 | #endif | 480 | #endif |
500 | PQclear (res); | 481 | PQclear (res); |
501 | return GNUNET_SYSERR; | 482 | return GNUNET_SYSERR; |
502 | } | 483 | } |
503 | if ( (3 != PQnfields (res)) || | 484 | if ((3 != PQnfields (res)) || |
504 | (sizeof (size) != PQfsize (res, 0)) || | 485 | (sizeof (size) != PQfsize (res, 0)) || |
505 | (sizeof (oid) != PQfsize (res, 1)) || | 486 | (sizeof (oid) != PQfsize (res, 1)) || |
506 | (sizeof (GNUNET_HashCode) != PQgetlength (res, 0, 2)) ) | 487 | (sizeof (GNUNET_HashCode) != PQgetlength (res, 0, 2))) |
507 | { | 488 | { |
508 | GNUNET_break (0); | 489 | GNUNET_break (0); |
509 | PQclear (res); | 490 | PQclear (res); |
510 | return 0; | 491 | return 0; |
511 | } | 492 | } |
512 | size = ntohl (*(uint32_t *) PQgetvalue (res, 0, 0)); | 493 | size = ntohl (*(uint32_t *) PQgetvalue (res, 0, 0)); |
513 | oid = ntohl (*(uint32_t *) PQgetvalue (res, 0, 1)); | 494 | oid = ntohl (*(uint32_t *) PQgetvalue (res, 0, 1)); |
514 | memcpy (&key, | 495 | memcpy (&key, PQgetvalue (res, 0, 2), sizeof (GNUNET_HashCode)); |
515 | PQgetvalue (res, 0, 2), | ||
516 | sizeof (GNUNET_HashCode)); | ||
517 | PQclear (res); | 496 | PQclear (res); |
518 | if (GNUNET_OK != delete_by_rowid (plugin, oid)) | 497 | if (GNUNET_OK != delete_by_rowid (plugin, oid)) |
519 | return GNUNET_SYSERR; | 498 | return GNUNET_SYSERR; |
520 | plugin->env->delete_notify (plugin->env->cls, | 499 | plugin->env->delete_notify (plugin->env->cls, &key, size + OVERHEAD); |
521 | &key, | ||
522 | size + OVERHEAD); | ||
523 | return GNUNET_OK; | 500 | return GNUNET_OK; |
524 | } | 501 | } |
525 | 502 | ||
@@ -540,12 +517,11 @@ libgnunet_plugin_datacache_postgres_init (void *cls) | |||
540 | plugin = GNUNET_malloc (sizeof (struct Plugin)); | 517 | plugin = GNUNET_malloc (sizeof (struct Plugin)); |
541 | plugin->env = env; | 518 | plugin->env = env; |
542 | 519 | ||
543 | if (GNUNET_OK != | 520 | if (GNUNET_OK != init_connection (plugin)) |
544 | init_connection (plugin)) | 521 | { |
545 | { | 522 | GNUNET_free (plugin); |
546 | GNUNET_free (plugin); | 523 | return NULL; |
547 | return NULL; | 524 | } |
548 | } | ||
549 | 525 | ||
550 | api = GNUNET_malloc (sizeof (struct GNUNET_DATACACHE_PluginFunctions)); | 526 | api = GNUNET_malloc (sizeof (struct GNUNET_DATACACHE_PluginFunctions)); |
551 | api->cls = plugin; | 527 | api->cls = plugin; |
@@ -553,8 +529,7 @@ libgnunet_plugin_datacache_postgres_init (void *cls) | |||
553 | api->put = &postgres_plugin_put; | 529 | api->put = &postgres_plugin_put; |
554 | api->del = &postgres_plugin_del; | 530 | api->del = &postgres_plugin_del; |
555 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, | 531 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, |
556 | "datacache-postgres", | 532 | "datacache-postgres", _("Postgres datacache running\n")); |
557 | _("Postgres datacache running\n")); | ||
558 | return api; | 533 | return api; |
559 | } | 534 | } |
560 | 535 | ||
@@ -580,4 +555,3 @@ libgnunet_plugin_datacache_postgres_done (void *cls) | |||
580 | 555 | ||
581 | 556 | ||
582 | /* end of plugin_datacache_postgres.c */ | 557 | /* end of plugin_datacache_postgres.c */ |
583 | |||
diff --git a/src/datacache/plugin_datacache_sqlite.c b/src/datacache/plugin_datacache_sqlite.c index fd451e2b4..5f534227f 100644 --- a/src/datacache/plugin_datacache_sqlite.c +++ b/src/datacache/plugin_datacache_sqlite.c | |||
@@ -39,7 +39,7 @@ | |||
39 | /** | 39 | /** |
40 | * Context for all functions in this plugin. | 40 | * Context for all functions in this plugin. |
41 | */ | 41 | */ |
42 | struct Plugin | 42 | struct Plugin |
43 | { | 43 | { |
44 | /** | 44 | /** |
45 | * Our execution environment. | 45 | * Our execution environment. |
@@ -53,7 +53,7 @@ struct Plugin | |||
53 | 53 | ||
54 | /** | 54 | /** |
55 | * Filename used for the DB. | 55 | * Filename used for the DB. |
56 | */ | 56 | */ |
57 | char *fn; | 57 | char *fn; |
58 | }; | 58 | }; |
59 | 59 | ||
@@ -77,9 +77,9 @@ sq_prepare (sqlite3 * dbh, const char *zSql, /* SQL statement, UTF-8 encoded | |||
77 | sqlite3_stmt ** ppStmt) | 77 | sqlite3_stmt ** ppStmt) |
78 | { /* OUT: Statement handle */ | 78 | { /* OUT: Statement handle */ |
79 | char *dummy; | 79 | char *dummy; |
80 | |||
80 | return sqlite3_prepare (dbh, | 81 | return sqlite3_prepare (dbh, |
81 | zSql, | 82 | zSql, strlen (zSql), ppStmt, (const char **) &dummy); |
82 | strlen (zSql), ppStmt, (const char **) &dummy); | ||
83 | } | 83 | } |
84 | 84 | ||
85 | 85 | ||
@@ -94,13 +94,13 @@ sq_prepare (sqlite3 * dbh, const char *zSql, /* SQL statement, UTF-8 encoded | |||
94 | * @param discard_time when to discard the value in any case | 94 | * @param discard_time when to discard the value in any case |
95 | * @return 0 on error, number of bytes used otherwise | 95 | * @return 0 on error, number of bytes used otherwise |
96 | */ | 96 | */ |
97 | static size_t | 97 | static size_t |
98 | sqlite_plugin_put (void *cls, | 98 | sqlite_plugin_put (void *cls, |
99 | const GNUNET_HashCode * key, | 99 | const GNUNET_HashCode * key, |
100 | size_t size, | 100 | size_t size, |
101 | const char *data, | 101 | const char *data, |
102 | enum GNUNET_BLOCK_Type type, | 102 | enum GNUNET_BLOCK_Type type, |
103 | struct GNUNET_TIME_Absolute discard_time) | 103 | struct GNUNET_TIME_Absolute discard_time) |
104 | { | 104 | { |
105 | struct Plugin *plugin = cls; | 105 | struct Plugin *plugin = cls; |
106 | sqlite3_stmt *stmt; | 106 | sqlite3_stmt *stmt; |
@@ -108,50 +108,50 @@ sqlite_plugin_put (void *cls, | |||
108 | 108 | ||
109 | #if DEBUG_DATACACHE_SQLITE | 109 | #if DEBUG_DATACACHE_SQLITE |
110 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 110 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
111 | "Processing `%s' of %u bytes with key `%4s' and expiration %llums\n", | 111 | "Processing `%s' of %u bytes with key `%4s' and expiration %llums\n", |
112 | "PUT", | 112 | "PUT", |
113 | (unsigned int) size, | 113 | (unsigned int) size, |
114 | GNUNET_h2s (key), | 114 | GNUNET_h2s (key), |
115 | (unsigned long long) GNUNET_TIME_absolute_get_remaining (discard_time).rel_value); | 115 | (unsigned long long) |
116 | GNUNET_TIME_absolute_get_remaining (discard_time).rel_value); | ||
116 | #endif | 117 | #endif |
117 | dval = (int64_t) discard_time.abs_value; | 118 | dval = (int64_t) discard_time.abs_value; |
118 | if (dval < 0) | 119 | if (dval < 0) |
119 | dval = INT64_MAX; | 120 | dval = INT64_MAX; |
120 | if (sq_prepare (plugin->dbh, | 121 | if (sq_prepare (plugin->dbh, |
121 | "INSERT INTO ds090 " | 122 | "INSERT INTO ds090 " |
122 | "(type, expire, key, value) " | 123 | "(type, expire, key, value) " |
123 | "VALUES (?, ?, ?, ?)", &stmt) != SQLITE_OK) | 124 | "VALUES (?, ?, ?, ?)", &stmt) != SQLITE_OK) |
124 | { | 125 | { |
125 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 126 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
126 | _("`%s' failed at %s:%d with error: %s\n"), | 127 | _("`%s' failed at %s:%d with error: %s\n"), |
127 | "sq_prepare", __FILE__, __LINE__, | 128 | "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (plugin->dbh)); |
128 | sqlite3_errmsg (plugin->dbh)); | 129 | return 0; |
129 | return 0; | 130 | } |
130 | } | 131 | if ((SQLITE_OK != sqlite3_bind_int (stmt, 1, type)) || |
131 | if ( (SQLITE_OK != sqlite3_bind_int (stmt, 1, type)) || | 132 | (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, dval)) || |
132 | (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, dval)) || | 133 | (SQLITE_OK != sqlite3_bind_blob (stmt, 3, key, sizeof (GNUNET_HashCode), |
133 | (SQLITE_OK != sqlite3_bind_blob (stmt, 3, key, sizeof (GNUNET_HashCode), | 134 | SQLITE_TRANSIENT)) || |
134 | SQLITE_TRANSIENT)) || | 135 | (SQLITE_OK != sqlite3_bind_blob (stmt, 4, data, size, SQLITE_TRANSIENT))) |
135 | (SQLITE_OK != sqlite3_bind_blob (stmt, 4, data, size, SQLITE_TRANSIENT))) | 136 | { |
136 | { | 137 | LOG_SQLITE (plugin->dbh, |
137 | LOG_SQLITE (plugin->dbh, | 138 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
138 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 139 | "sqlite3_bind_xxx"); |
139 | "sqlite3_bind_xxx"); | 140 | sqlite3_finalize (stmt); |
140 | sqlite3_finalize (stmt); | 141 | return 0; |
141 | return 0; | 142 | } |
142 | } | ||
143 | if (SQLITE_DONE != sqlite3_step (stmt)) | 143 | if (SQLITE_DONE != sqlite3_step (stmt)) |
144 | { | 144 | { |
145 | LOG_SQLITE (plugin->dbh, | 145 | LOG_SQLITE (plugin->dbh, |
146 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 146 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
147 | "sqlite3_step"); | 147 | "sqlite3_step"); |
148 | sqlite3_finalize (stmt); | 148 | sqlite3_finalize (stmt); |
149 | return 0; | 149 | return 0; |
150 | } | 150 | } |
151 | if (SQLITE_OK != sqlite3_finalize (stmt)) | 151 | if (SQLITE_OK != sqlite3_finalize (stmt)) |
152 | LOG_SQLITE (plugin->dbh, | 152 | LOG_SQLITE (plugin->dbh, |
153 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 153 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
154 | "sqlite3_finalize"); | 154 | "sqlite3_finalize"); |
155 | return size + OVERHEAD; | 155 | return size + OVERHEAD; |
156 | } | 156 | } |
157 | 157 | ||
@@ -167,12 +167,11 @@ sqlite_plugin_put (void *cls, | |||
167 | * @param iter_cls closure for iter | 167 | * @param iter_cls closure for iter |
168 | * @return the number of results found | 168 | * @return the number of results found |
169 | */ | 169 | */ |
170 | static unsigned int | 170 | static unsigned int |
171 | sqlite_plugin_get (void *cls, | 171 | sqlite_plugin_get (void *cls, |
172 | const GNUNET_HashCode * key, | 172 | const GNUNET_HashCode * key, |
173 | enum GNUNET_BLOCK_Type type, | 173 | enum GNUNET_BLOCK_Type type, |
174 | GNUNET_DATACACHE_Iterator iter, | 174 | GNUNET_DATACACHE_Iterator iter, void *iter_cls) |
175 | void *iter_cls) | ||
176 | { | 175 | { |
177 | struct Plugin *plugin = cls; | 176 | struct Plugin *plugin = cls; |
178 | sqlite3_stmt *stmt; | 177 | sqlite3_stmt *stmt; |
@@ -189,102 +188,92 @@ sqlite_plugin_get (void *cls, | |||
189 | now = GNUNET_TIME_absolute_get (); | 188 | now = GNUNET_TIME_absolute_get (); |
190 | #if DEBUG_DATACACHE_SQLITE | 189 | #if DEBUG_DATACACHE_SQLITE |
191 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 190 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
192 | "Processing `%s' for key `%4s'\n", | 191 | "Processing `%s' for key `%4s'\n", "GET", GNUNET_h2s (key)); |
193 | "GET", | ||
194 | GNUNET_h2s (key)); | ||
195 | #endif | 192 | #endif |
196 | if (sq_prepare (plugin->dbh, | 193 | if (sq_prepare (plugin->dbh, |
197 | "SELECT count(*) FROM ds090 WHERE key=? AND type=? AND expire >= ?", | 194 | "SELECT count(*) FROM ds090 WHERE key=? AND type=? AND expire >= ?", |
198 | &stmt) != SQLITE_OK) | 195 | &stmt) != SQLITE_OK) |
199 | { | 196 | { |
200 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 197 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
201 | _("`%s' failed at %s:%d with error: %s\n"), | 198 | _("`%s' failed at %s:%d with error: %s\n"), |
202 | "sq_prepare", __FILE__, __LINE__, | 199 | "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (plugin->dbh)); |
203 | sqlite3_errmsg (plugin->dbh)); | 200 | return 0; |
204 | return 0; | 201 | } |
205 | } | ||
206 | ntime = (int64_t) now.abs_value; | 202 | ntime = (int64_t) now.abs_value; |
207 | GNUNET_assert (ntime >= 0); | 203 | GNUNET_assert (ntime >= 0); |
208 | if ( (SQLITE_OK != | 204 | if ((SQLITE_OK != |
209 | sqlite3_bind_blob (stmt, 1, key, sizeof (GNUNET_HashCode), | 205 | sqlite3_bind_blob (stmt, 1, key, sizeof (GNUNET_HashCode), |
210 | SQLITE_TRANSIENT)) || | 206 | SQLITE_TRANSIENT)) || |
211 | (SQLITE_OK != | 207 | (SQLITE_OK != |
212 | sqlite3_bind_int (stmt, 2, type)) || | 208 | sqlite3_bind_int (stmt, 2, type)) || |
213 | (SQLITE_OK != | 209 | (SQLITE_OK != sqlite3_bind_int64 (stmt, 3, now.abs_value))) |
214 | sqlite3_bind_int64 (stmt, 3, now.abs_value)) ) | 210 | { |
215 | { | 211 | LOG_SQLITE (plugin->dbh, |
216 | LOG_SQLITE (plugin->dbh, | 212 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
217 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 213 | "sqlite3_bind_xxx"); |
218 | "sqlite3_bind_xxx"); | 214 | sqlite3_finalize (stmt); |
219 | sqlite3_finalize (stmt); | 215 | return 0; |
220 | return 0; | 216 | } |
221 | } | ||
222 | 217 | ||
223 | if (SQLITE_ROW != sqlite3_step (stmt)) | 218 | if (SQLITE_ROW != sqlite3_step (stmt)) |
224 | { | 219 | { |
225 | LOG_SQLITE (plugin->dbh, | 220 | LOG_SQLITE (plugin->dbh, |
226 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 221 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
227 | "sqlite_step"); | 222 | "sqlite_step"); |
228 | sqlite3_finalize (stmt); | 223 | sqlite3_finalize (stmt); |
229 | return 0; | 224 | return 0; |
230 | } | 225 | } |
231 | total = sqlite3_column_int (stmt, 0); | 226 | total = sqlite3_column_int (stmt, 0); |
232 | sqlite3_finalize (stmt); | 227 | sqlite3_finalize (stmt); |
233 | if ( (total == 0) || (iter == NULL) ) | 228 | if ((total == 0) || (iter == NULL)) |
234 | return total; | 229 | return total; |
235 | 230 | ||
236 | cnt = 0; | 231 | cnt = 0; |
237 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total); | 232 | off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total); |
238 | while (cnt < total) | 233 | while (cnt < total) |
234 | { | ||
235 | off = (off + 1) % total; | ||
236 | GNUNET_snprintf (scratch, | ||
237 | sizeof (scratch), | ||
238 | "SELECT value,expire FROM ds090 WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET %u", | ||
239 | off); | ||
240 | if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK) | ||
241 | { | ||
242 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
243 | _("`%s' failed at %s:%d with error: %s\n"), | ||
244 | "sq_prepare", __FILE__, __LINE__, | ||
245 | sqlite3_errmsg (plugin->dbh)); | ||
246 | return cnt; | ||
247 | } | ||
248 | if ((SQLITE_OK != | ||
249 | sqlite3_bind_blob (stmt, 1, key, sizeof (GNUNET_HashCode), | ||
250 | SQLITE_TRANSIENT)) || | ||
251 | (SQLITE_OK != | ||
252 | sqlite3_bind_int (stmt, 2, type)) || | ||
253 | (SQLITE_OK != sqlite3_bind_int64 (stmt, 3, now.abs_value))) | ||
254 | { | ||
255 | LOG_SQLITE (plugin->dbh, | ||
256 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
257 | "sqlite3_bind_xxx"); | ||
258 | sqlite3_finalize (stmt); | ||
259 | return cnt; | ||
260 | } | ||
261 | if (sqlite3_step (stmt) != SQLITE_ROW) | ||
262 | break; | ||
263 | size = sqlite3_column_bytes (stmt, 0); | ||
264 | dat = sqlite3_column_blob (stmt, 0); | ||
265 | exp.abs_value = sqlite3_column_int64 (stmt, 1); | ||
266 | ntime = (int64_t) exp.abs_value; | ||
267 | if (ntime == INT64_MAX) | ||
268 | exp = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
269 | cnt++; | ||
270 | if (GNUNET_OK != iter (iter_cls, exp, key, size, dat, type)) | ||
239 | { | 271 | { |
240 | off = (off + 1) % total; | ||
241 | GNUNET_snprintf (scratch, | ||
242 | sizeof(scratch), | ||
243 | "SELECT value,expire FROM ds090 WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET %u", | ||
244 | off); | ||
245 | if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK) | ||
246 | { | ||
247 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
248 | _("`%s' failed at %s:%d with error: %s\n"), | ||
249 | "sq_prepare", __FILE__, __LINE__, | ||
250 | sqlite3_errmsg (plugin->dbh)); | ||
251 | return cnt; | ||
252 | } | ||
253 | if ( (SQLITE_OK != | ||
254 | sqlite3_bind_blob (stmt, 1, key, sizeof (GNUNET_HashCode), | ||
255 | SQLITE_TRANSIENT)) || | ||
256 | (SQLITE_OK != | ||
257 | sqlite3_bind_int (stmt, 2, type)) || | ||
258 | (SQLITE_OK != | ||
259 | sqlite3_bind_int64 (stmt, 3, now.abs_value)) ) | ||
260 | { | ||
261 | LOG_SQLITE (plugin->dbh, | ||
262 | GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
263 | "sqlite3_bind_xxx"); | ||
264 | sqlite3_finalize (stmt); | ||
265 | return cnt; | ||
266 | } | ||
267 | if (sqlite3_step (stmt) != SQLITE_ROW) | ||
268 | break; | ||
269 | size = sqlite3_column_bytes (stmt, 0); | ||
270 | dat = sqlite3_column_blob (stmt, 0); | ||
271 | exp.abs_value = sqlite3_column_int64 (stmt, 1); | ||
272 | ntime = (int64_t) exp.abs_value; | ||
273 | if (ntime == INT64_MAX) | ||
274 | exp = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
275 | cnt++; | ||
276 | if (GNUNET_OK != iter (iter_cls, | ||
277 | exp, | ||
278 | key, | ||
279 | size, | ||
280 | dat, | ||
281 | type)) | ||
282 | { | ||
283 | sqlite3_finalize (stmt); | ||
284 | break; | ||
285 | } | ||
286 | sqlite3_finalize (stmt); | 272 | sqlite3_finalize (stmt); |
273 | break; | ||
287 | } | 274 | } |
275 | sqlite3_finalize (stmt); | ||
276 | } | ||
288 | return cnt; | 277 | return cnt; |
289 | } | 278 | } |
290 | 279 | ||
@@ -295,8 +284,8 @@ sqlite_plugin_get (void *cls, | |||
295 | * | 284 | * |
296 | * @param cls closure (our "struct Plugin") | 285 | * @param cls closure (our "struct Plugin") |
297 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | 286 | * @return GNUNET_OK on success, GNUNET_SYSERR on error |
298 | */ | 287 | */ |
299 | static int | 288 | static int |
300 | sqlite_plugin_del (void *cls) | 289 | sqlite_plugin_del (void *cls) |
301 | { | 290 | { |
302 | struct Plugin *plugin = cls; | 291 | struct Plugin *plugin = cls; |
@@ -308,32 +297,30 @@ sqlite_plugin_del (void *cls) | |||
308 | GNUNET_HashCode hc; | 297 | GNUNET_HashCode hc; |
309 | 298 | ||
310 | #if DEBUG_DATACACHE_SQLITE | 299 | #if DEBUG_DATACACHE_SQLITE |
311 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 300 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s'\n", "DEL"); |
312 | "Processing `%s'\n", | ||
313 | "DEL"); | ||
314 | #endif | 301 | #endif |
315 | stmt = NULL; | 302 | stmt = NULL; |
316 | dstmt = NULL; | 303 | dstmt = NULL; |
317 | if (sq_prepare (plugin->dbh, | 304 | if (sq_prepare (plugin->dbh, |
318 | "SELECT type, key, value FROM ds090 ORDER BY expire ASC LIMIT 1", | 305 | "SELECT type, key, value FROM ds090 ORDER BY expire ASC LIMIT 1", |
319 | &stmt) != SQLITE_OK) | 306 | &stmt) != SQLITE_OK) |
320 | { | 307 | { |
321 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 308 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
322 | _("`%s' failed at %s:%d with error: %s\n"), | 309 | _("`%s' failed at %s:%d with error: %s\n"), |
323 | "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (plugin->dbh)); | 310 | "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (plugin->dbh)); |
324 | if (stmt != NULL) | 311 | if (stmt != NULL) |
325 | (void) sqlite3_finalize (stmt); | ||
326 | return GNUNET_SYSERR; | ||
327 | } | ||
328 | if (SQLITE_ROW != sqlite3_step (stmt)) | ||
329 | { | ||
330 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
331 | _("`%s' failed at %s:%d with error: %s\n"), | ||
332 | "sqlite3_step", __FILE__, __LINE__, | ||
333 | sqlite3_errmsg (plugin->dbh)); | ||
334 | (void) sqlite3_finalize (stmt); | 312 | (void) sqlite3_finalize (stmt); |
335 | return GNUNET_SYSERR; | 313 | return GNUNET_SYSERR; |
336 | } | 314 | } |
315 | if (SQLITE_ROW != sqlite3_step (stmt)) | ||
316 | { | ||
317 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
318 | _("`%s' failed at %s:%d with error: %s\n"), | ||
319 | "sqlite3_step", __FILE__, __LINE__, | ||
320 | sqlite3_errmsg (plugin->dbh)); | ||
321 | (void) sqlite3_finalize (stmt); | ||
322 | return GNUNET_SYSERR; | ||
323 | } | ||
337 | dtype = sqlite3_column_int (stmt, 0); | 324 | dtype = sqlite3_column_int (stmt, 0); |
338 | GNUNET_break (sqlite3_column_bytes (stmt, 1) == sizeof (GNUNET_HashCode)); | 325 | GNUNET_break (sqlite3_column_bytes (stmt, 1) == sizeof (GNUNET_HashCode)); |
339 | dsize = sqlite3_column_bytes (stmt, 2); | 326 | dsize = sqlite3_column_bytes (stmt, 2); |
@@ -342,58 +329,54 @@ sqlite_plugin_del (void *cls) | |||
342 | memcpy (&hc, sqlite3_column_blob (stmt, 1), sizeof (GNUNET_HashCode)); | 329 | memcpy (&hc, sqlite3_column_blob (stmt, 1), sizeof (GNUNET_HashCode)); |
343 | if (SQLITE_OK != sqlite3_finalize (stmt)) | 330 | if (SQLITE_OK != sqlite3_finalize (stmt)) |
344 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 331 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
345 | _("`%s' failed at %s:%d with error: %s\n"), | 332 | _("`%s' failed at %s:%d with error: %s\n"), |
346 | "sqlite3_step", __FILE__, __LINE__, | 333 | "sqlite3_step", __FILE__, __LINE__, |
347 | sqlite3_errmsg (plugin->dbh)); | 334 | sqlite3_errmsg (plugin->dbh)); |
348 | if (sq_prepare (plugin->dbh, | 335 | if (sq_prepare (plugin->dbh, |
349 | "DELETE FROM ds090 " | 336 | "DELETE FROM ds090 " |
350 | "WHERE key=? AND value=? AND type=?", | 337 | "WHERE key=? AND value=? AND type=?", &dstmt) != SQLITE_OK) |
351 | &dstmt) != SQLITE_OK) | 338 | { |
352 | { | 339 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
353 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 340 | _("`%s' failed at %s:%d with error: %s\n"), |
354 | _("`%s' failed at %s:%d with error: %s\n"), | 341 | "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (plugin->dbh)); |
355 | "sq_prepare", __FILE__, __LINE__, sqlite3_errmsg (plugin->dbh)); | 342 | if (stmt != NULL) |
356 | if (stmt != NULL) | 343 | (void) sqlite3_finalize (stmt); |
357 | (void) sqlite3_finalize (stmt); | 344 | return GNUNET_SYSERR; |
358 | return GNUNET_SYSERR; | 345 | } |
359 | } | 346 | if ((SQLITE_OK != |
360 | if ( (SQLITE_OK != | 347 | sqlite3_bind_blob (dstmt, |
361 | sqlite3_bind_blob (dstmt, | 348 | 1, &hc, |
362 | 1, &hc, | 349 | sizeof (GNUNET_HashCode), |
363 | sizeof (GNUNET_HashCode), | 350 | SQLITE_TRANSIENT)) || |
364 | SQLITE_TRANSIENT)) || | 351 | (SQLITE_OK != |
365 | (SQLITE_OK != | 352 | sqlite3_bind_blob (dstmt, |
366 | sqlite3_bind_blob (dstmt, | 353 | 2, blob, |
367 | 2, blob, | 354 | dsize, |
368 | dsize, | 355 | SQLITE_TRANSIENT)) || |
369 | SQLITE_TRANSIENT)) || | 356 | (SQLITE_OK != sqlite3_bind_int (dstmt, 3, dtype))) |
370 | (SQLITE_OK != | 357 | { |
371 | sqlite3_bind_int (dstmt, 3, dtype)) ) | 358 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
372 | { | 359 | _("`%s' failed at %s:%d with error: %s\n"), |
373 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 360 | "sqlite3_bind", __FILE__, __LINE__, |
374 | _("`%s' failed at %s:%d with error: %s\n"), | 361 | sqlite3_errmsg (plugin->dbh)); |
375 | "sqlite3_bind", __FILE__, __LINE__, | 362 | (void) sqlite3_finalize (dstmt); |
376 | sqlite3_errmsg (plugin->dbh)); | 363 | return GNUNET_SYSERR; |
377 | (void) sqlite3_finalize (dstmt); | 364 | } |
378 | return GNUNET_SYSERR; | ||
379 | } | ||
380 | if (sqlite3_step (dstmt) != SQLITE_DONE) | 365 | if (sqlite3_step (dstmt) != SQLITE_DONE) |
381 | { | 366 | { |
382 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 367 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
383 | _("`%s' failed at %s:%d with error: %s\n"), | 368 | _("`%s' failed at %s:%d with error: %s\n"), |
384 | "sqlite3_step", __FILE__, __LINE__, | 369 | "sqlite3_step", __FILE__, __LINE__, |
385 | sqlite3_errmsg (plugin->dbh)); | 370 | sqlite3_errmsg (plugin->dbh)); |
386 | (void) sqlite3_finalize (dstmt); | 371 | (void) sqlite3_finalize (dstmt); |
387 | return GNUNET_SYSERR; | 372 | return GNUNET_SYSERR; |
388 | } | 373 | } |
389 | plugin->env->delete_notify (plugin->env->cls, | 374 | plugin->env->delete_notify (plugin->env->cls, &hc, dsize + OVERHEAD); |
390 | &hc, | ||
391 | dsize + OVERHEAD); | ||
392 | if (SQLITE_OK != sqlite3_finalize (dstmt)) | 375 | if (SQLITE_OK != sqlite3_finalize (dstmt)) |
393 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | 376 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, |
394 | _("`%s' failed at %s:%d with error: %s\n"), | 377 | _("`%s' failed at %s:%d with error: %s\n"), |
395 | "sqlite3_finalize", __FILE__, __LINE__, | 378 | "sqlite3_finalize", __FILE__, __LINE__, |
396 | sqlite3_errmsg (plugin->dbh)); | 379 | sqlite3_errmsg (plugin->dbh)); |
397 | return GNUNET_OK; | 380 | return GNUNET_OK; |
398 | } | 381 | } |
399 | 382 | ||
@@ -417,10 +400,10 @@ libgnunet_plugin_datacache_sqlite_init (void *cls) | |||
417 | 400 | ||
418 | fn = GNUNET_DISK_mktemp ("gnunet-datacache"); | 401 | fn = GNUNET_DISK_mktemp ("gnunet-datacache"); |
419 | if (fn == NULL) | 402 | if (fn == NULL) |
420 | { | 403 | { |
421 | GNUNET_break (0); | 404 | GNUNET_break (0); |
422 | return NULL; | 405 | return NULL; |
423 | } | 406 | } |
424 | #ifdef ENABLE_NLS | 407 | #ifdef ENABLE_NLS |
425 | fn_utf8 = GNUNET_STRINGS_to_utf8 (fn, strlen (fn), nl_langinfo (CODESET)); | 408 | fn_utf8 = GNUNET_STRINGS_to_utf8 (fn, strlen (fn), nl_langinfo (CODESET)); |
426 | #else | 409 | #else |
@@ -428,11 +411,11 @@ libgnunet_plugin_datacache_sqlite_init (void *cls) | |||
428 | fn_utf8 = GNUNET_STRINGS_to_utf8 (fn, strlen (fn), "UTF-8"); | 411 | fn_utf8 = GNUNET_STRINGS_to_utf8 (fn, strlen (fn), "UTF-8"); |
429 | #endif | 412 | #endif |
430 | if (SQLITE_OK != sqlite3_open (fn_utf8, &dbh)) | 413 | if (SQLITE_OK != sqlite3_open (fn_utf8, &dbh)) |
431 | { | 414 | { |
432 | GNUNET_free (fn); | 415 | GNUNET_free (fn); |
433 | GNUNET_free (fn_utf8); | 416 | GNUNET_free (fn_utf8); |
434 | return NULL; | 417 | return NULL; |
435 | } | 418 | } |
436 | GNUNET_free (fn); | 419 | GNUNET_free (fn); |
437 | 420 | ||
438 | SQLITE3_EXEC (dbh, "PRAGMA temp_store=MEMORY"); | 421 | SQLITE3_EXEC (dbh, "PRAGMA temp_store=MEMORY"); |
@@ -461,6 +444,7 @@ libgnunet_plugin_datacache_sqlite_init (void *cls) | |||
461 | "sqlite", _("Sqlite datacache running\n")); | 444 | "sqlite", _("Sqlite datacache running\n")); |
462 | return api; | 445 | return api; |
463 | } | 446 | } |
447 | |||
464 | // explain SELECT type FROM gn090 WHERE NOT EXISTS (SELECT 1 from gn090 WHERE expire < 42 LIMIT 1) OR expire < 42 ORDER BY repl DESC, Random() LIMIT 1; | 448 | // explain SELECT type FROM gn090 WHERE NOT EXISTS (SELECT 1 from gn090 WHERE expire < 42 LIMIT 1) OR expire < 42 ORDER BY repl DESC, Random() LIMIT 1; |
465 | 449 | ||
466 | 450 | ||
@@ -476,53 +460,49 @@ libgnunet_plugin_datacache_sqlite_done (void *cls) | |||
476 | struct GNUNET_DATACACHE_PluginFunctions *api = cls; | 460 | struct GNUNET_DATACACHE_PluginFunctions *api = cls; |
477 | struct Plugin *plugin = api->cls; | 461 | struct Plugin *plugin = api->cls; |
478 | int result; | 462 | int result; |
463 | |||
479 | #if SQLITE_VERSION_NUMBER >= 3007000 | 464 | #if SQLITE_VERSION_NUMBER >= 3007000 |
480 | sqlite3_stmt *stmt; | 465 | sqlite3_stmt *stmt; |
481 | #endif | 466 | #endif |
482 | 467 | ||
483 | #if !WINDOWS || defined(__CYGWIN__) | 468 | #if !WINDOWS || defined(__CYGWIN__) |
484 | if (0 != UNLINK (plugin->fn)) | 469 | if (0 != UNLINK (plugin->fn)) |
485 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | 470 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", plugin->fn); |
486 | "unlink", | ||
487 | plugin->fn); | ||
488 | GNUNET_free (plugin->fn); | 471 | GNUNET_free (plugin->fn); |
489 | #endif | 472 | #endif |
490 | result = sqlite3_close (plugin->dbh); | 473 | result = sqlite3_close (plugin->dbh); |
491 | #if SQLITE_VERSION_NUMBER >= 3007000 | 474 | #if SQLITE_VERSION_NUMBER >= 3007000 |
492 | if (result == SQLITE_BUSY) | 475 | if (result == SQLITE_BUSY) |
476 | { | ||
477 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
478 | "sqlite", | ||
479 | _ | ||
480 | ("Tried to close sqlite without finalizing all prepared statements.\n")); | ||
481 | stmt = sqlite3_next_stmt (plugin->dbh, NULL); | ||
482 | while (stmt != NULL) | ||
493 | { | 483 | { |
494 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
495 | "sqlite", | ||
496 | _("Tried to close sqlite without finalizing all prepared statements.\n")); | ||
497 | stmt = sqlite3_next_stmt(plugin->dbh, NULL); | ||
498 | while (stmt != NULL) | ||
499 | { | ||
500 | #if DEBUG_SQLITE | 484 | #if DEBUG_SQLITE |
501 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 485 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
502 | "sqlite", "Closing statement %p\n", stmt); | 486 | "sqlite", "Closing statement %p\n", stmt); |
503 | #endif | 487 | #endif |
504 | result = sqlite3_finalize(stmt); | 488 | result = sqlite3_finalize (stmt); |
505 | #if DEBUG_SQLITE | 489 | #if DEBUG_SQLITE |
506 | if (result != SQLITE_OK) | 490 | if (result != SQLITE_OK) |
507 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 491 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
508 | "sqlite", | 492 | "sqlite", |
509 | "Failed to close statement %p: %d\n", stmt, result); | 493 | "Failed to close statement %p: %d\n", stmt, result); |
510 | #endif | 494 | #endif |
511 | stmt = sqlite3_next_stmt(plugin->dbh, NULL); | 495 | stmt = sqlite3_next_stmt (plugin->dbh, NULL); |
512 | } | ||
513 | result = sqlite3_close(plugin->dbh); | ||
514 | } | 496 | } |
497 | result = sqlite3_close (plugin->dbh); | ||
498 | } | ||
515 | #endif | 499 | #endif |
516 | if (SQLITE_OK != result) | 500 | if (SQLITE_OK != result) |
517 | LOG_SQLITE (plugin->dbh, | 501 | LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close"); |
518 | GNUNET_ERROR_TYPE_ERROR, | ||
519 | "sqlite3_close"); | ||
520 | 502 | ||
521 | #if WINDOWS && !defined(__CYGWIN__) | 503 | #if WINDOWS && !defined(__CYGWIN__) |
522 | if (0 != UNLINK (plugin->fn)) | 504 | if (0 != UNLINK (plugin->fn)) |
523 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | 505 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", plugin->fn); |
524 | "unlink", | ||
525 | plugin->fn); | ||
526 | GNUNET_free (plugin->fn); | 506 | GNUNET_free (plugin->fn); |
527 | #endif | 507 | #endif |
528 | GNUNET_free (plugin); | 508 | GNUNET_free (plugin); |
@@ -533,4 +513,3 @@ libgnunet_plugin_datacache_sqlite_done (void *cls) | |||
533 | 513 | ||
534 | 514 | ||
535 | /* end of plugin_datacache_sqlite.c */ | 515 | /* end of plugin_datacache_sqlite.c */ |
536 | |||
diff --git a/src/datacache/plugin_datacache_template.c b/src/datacache/plugin_datacache_template.c index 60862dac2..865f431d7 100644 --- a/src/datacache/plugin_datacache_template.c +++ b/src/datacache/plugin_datacache_template.c | |||
@@ -31,7 +31,7 @@ | |||
31 | /** | 31 | /** |
32 | * Context for all functions in this plugin. | 32 | * Context for all functions in this plugin. |
33 | */ | 33 | */ |
34 | struct Plugin | 34 | struct Plugin |
35 | { | 35 | { |
36 | /** | 36 | /** |
37 | * Our execution environment. | 37 | * Our execution environment. |
@@ -51,13 +51,13 @@ struct Plugin | |||
51 | * @param discard_time when to discard the value in any case | 51 | * @param discard_time when to discard the value in any case |
52 | * @return 0 on error, number of bytes used otherwise | 52 | * @return 0 on error, number of bytes used otherwise |
53 | */ | 53 | */ |
54 | static size_t | 54 | static size_t |
55 | template_plugin_put (void *cls, | 55 | template_plugin_put (void *cls, |
56 | const GNUNET_HashCode * key, | 56 | const GNUNET_HashCode * key, |
57 | size_t size, | 57 | size_t size, |
58 | const char *data, | 58 | const char *data, |
59 | enum GNUNET_BLOCK_Type type, | 59 | enum GNUNET_BLOCK_Type type, |
60 | struct GNUNET_TIME_Absolute discard_time) | 60 | struct GNUNET_TIME_Absolute discard_time) |
61 | { | 61 | { |
62 | GNUNET_break (0); | 62 | GNUNET_break (0); |
63 | return 0; | 63 | return 0; |
@@ -75,12 +75,11 @@ template_plugin_put (void *cls, | |||
75 | * @param iter_cls closure for iter | 75 | * @param iter_cls closure for iter |
76 | * @return the number of results found | 76 | * @return the number of results found |
77 | */ | 77 | */ |
78 | static unsigned int | 78 | static unsigned int |
79 | template_plugin_get (void *cls, | 79 | template_plugin_get (void *cls, |
80 | const GNUNET_HashCode * key, | 80 | const GNUNET_HashCode * key, |
81 | enum GNUNET_BLOCK_Type type, | 81 | enum GNUNET_BLOCK_Type type, |
82 | GNUNET_DATACACHE_Iterator iter, | 82 | GNUNET_DATACACHE_Iterator iter, void *iter_cls) |
83 | void *iter_cls) | ||
84 | { | 83 | { |
85 | GNUNET_break (0); | 84 | GNUNET_break (0); |
86 | return 0; | 85 | return 0; |
@@ -93,8 +92,8 @@ template_plugin_get (void *cls, | |||
93 | * | 92 | * |
94 | * @param cls closure (our "struct Plugin") | 93 | * @param cls closure (our "struct Plugin") |
95 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | 94 | * @return GNUNET_OK on success, GNUNET_SYSERR on error |
96 | */ | 95 | */ |
97 | static int | 96 | static int |
98 | template_plugin_del (void *cls) | 97 | template_plugin_del (void *cls) |
99 | { | 98 | { |
100 | GNUNET_break (0); | 99 | GNUNET_break (0); |
@@ -148,4 +147,3 @@ libgnunet_plugin_datacache_template_done (void *cls) | |||
148 | 147 | ||
149 | 148 | ||
150 | /* end of plugin_datacache_template.c */ | 149 | /* end of plugin_datacache_template.c */ |
151 | |||
diff --git a/src/datacache/test_datacache.c b/src/datacache/test_datacache.c index 7d55ef8b7..c04facc15 100644 --- a/src/datacache/test_datacache.c +++ b/src/datacache/test_datacache.c | |||
@@ -40,22 +40,20 @@ static const char *plugin_name; | |||
40 | 40 | ||
41 | static int | 41 | static int |
42 | checkIt (void *cls, | 42 | checkIt (void *cls, |
43 | struct GNUNET_TIME_Absolute exp, | 43 | struct GNUNET_TIME_Absolute exp, |
44 | const GNUNET_HashCode * key, | 44 | const GNUNET_HashCode * key, |
45 | size_t size, | 45 | size_t size, const char *data, enum GNUNET_BLOCK_Type type) |
46 | const char *data, | ||
47 | enum GNUNET_BLOCK_Type type) | ||
48 | { | 46 | { |
49 | if (size != sizeof (GNUNET_HashCode)) | 47 | if (size != sizeof (GNUNET_HashCode)) |
50 | { | 48 | { |
51 | printf ("ERROR: Invalid size\n"); | 49 | printf ("ERROR: Invalid size\n"); |
52 | ok = 2; | 50 | ok = 2; |
53 | } | 51 | } |
54 | if (0 != memcmp (data, cls, size)) | 52 | if (0 != memcmp (data, cls, size)) |
55 | { | 53 | { |
56 | printf ("ERROR: Invalid data\n"); | 54 | printf ("ERROR: Invalid data\n"); |
57 | ok = 3; | 55 | ok = 3; |
58 | } | 56 | } |
59 | return GNUNET_OK; | 57 | return GNUNET_OK; |
60 | } | 58 | } |
61 | 59 | ||
@@ -63,8 +61,7 @@ checkIt (void *cls, | |||
63 | static void | 61 | static void |
64 | run (void *cls, | 62 | run (void *cls, |
65 | char *const *args, | 63 | char *const *args, |
66 | const char *cfgfile, | 64 | const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) |
67 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
68 | { | 65 | { |
69 | struct GNUNET_DATACACHE_Handle *h; | 66 | struct GNUNET_DATACACHE_Handle *h; |
70 | GNUNET_HashCode k; | 67 | GNUNET_HashCode k; |
@@ -73,39 +70,35 @@ run (void *cls, | |||
73 | unsigned int i; | 70 | unsigned int i; |
74 | 71 | ||
75 | ok = 0; | 72 | ok = 0; |
76 | h = GNUNET_DATACACHE_create (cfg, | 73 | h = GNUNET_DATACACHE_create (cfg, "testcache"); |
77 | "testcache"); | ||
78 | if (h == NULL) | 74 | if (h == NULL) |
79 | { | 75 | { |
80 | fprintf (stderr, | 76 | fprintf (stderr, |
81 | "Failed to initialize datacache. Database likely not setup, skipping test.\n"); | 77 | "Failed to initialize datacache. Database likely not setup, skipping test.\n"); |
82 | return; | 78 | return; |
83 | } | 79 | } |
84 | exp = GNUNET_TIME_absolute_get (); | 80 | exp = GNUNET_TIME_absolute_get (); |
85 | exp.abs_value += 5 * 60 * 1000; | 81 | exp.abs_value += 5 * 60 * 1000; |
86 | memset (&k, 0, sizeof (GNUNET_HashCode)); | 82 | memset (&k, 0, sizeof (GNUNET_HashCode)); |
87 | for (i = 0; i < 100; i++) | 83 | for (i = 0; i < 100; i++) |
88 | { | 84 | { |
89 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); | 85 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); |
90 | ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, | 86 | ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, |
91 | &k, | 87 | &k, |
92 | sizeof (GNUNET_HashCode), | 88 | sizeof (GNUNET_HashCode), |
93 | (const char *) &n, | 89 | (const char *) &n, |
94 | 1+i%16, | 90 | 1 + i % 16, exp)); |
95 | exp)); | 91 | k = n; |
96 | k = n; | 92 | } |
97 | } | ||
98 | memset (&k, 0, sizeof (GNUNET_HashCode)); | 93 | memset (&k, 0, sizeof (GNUNET_HashCode)); |
99 | for (i = 0; i < 100; i++) | 94 | for (i = 0; i < 100; i++) |
100 | { | 95 | { |
101 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); | 96 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); |
102 | ASSERT (1 == | 97 | ASSERT (1 == GNUNET_DATACACHE_get (h, &k, 1 + i % 16, &checkIt, &n)); |
103 | GNUNET_DATACACHE_get (h, &k, 1+i%16, | 98 | k = n; |
104 | &checkIt, &n)); | 99 | } |
105 | k = n; | 100 | |
106 | } | 101 | memset (&k, 42, sizeof (GNUNET_HashCode)); |
107 | |||
108 | memset(&k, 42, sizeof(GNUNET_HashCode)); | ||
109 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); | 102 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); |
110 | ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, | 103 | ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, |
111 | &k, | 104 | &k, |
@@ -113,9 +106,7 @@ run (void *cls, | |||
113 | (const char *) &n, | 106 | (const char *) &n, |
114 | 792, | 107 | 792, |
115 | GNUNET_TIME_UNIT_FOREVER_ABS)); | 108 | GNUNET_TIME_UNIT_FOREVER_ABS)); |
116 | ASSERT (0 != | 109 | ASSERT (0 != GNUNET_DATACACHE_get (h, &k, 792, &checkIt, &n)); |
117 | GNUNET_DATACACHE_get (h, &k, 792, | ||
118 | &checkIt, &n)); | ||
119 | 110 | ||
120 | GNUNET_DATACACHE_destroy (h); | 111 | GNUNET_DATACACHE_destroy (h); |
121 | ASSERT (ok == 0); | 112 | ASSERT (ok == 0); |
@@ -132,7 +123,8 @@ main (int argc, char *argv[]) | |||
132 | { | 123 | { |
133 | char *pos; | 124 | char *pos; |
134 | char cfg_name[128]; | 125 | char cfg_name[128]; |
135 | char *const xargv[] = { | 126 | |
127 | char *const xargv[] = { | ||
136 | "test-datacache", | 128 | "test-datacache", |
137 | "-c", | 129 | "-c", |
138 | cfg_name, | 130 | cfg_name, |
@@ -154,22 +146,20 @@ main (int argc, char *argv[]) | |||
154 | NULL); | 146 | NULL); |
155 | /* determine name of plugin to use */ | 147 | /* determine name of plugin to use */ |
156 | plugin_name = argv[0]; | 148 | plugin_name = argv[0]; |
157 | while (NULL != (pos = strstr(plugin_name, "_"))) | 149 | while (NULL != (pos = strstr (plugin_name, "_"))) |
158 | plugin_name = pos+1; | 150 | plugin_name = pos + 1; |
159 | if (NULL != (pos = strstr(plugin_name, "."))) | 151 | if (NULL != (pos = strstr (plugin_name, "."))) |
160 | pos[0] = 0; | 152 | pos[0] = 0; |
161 | else | 153 | else |
162 | pos = (char *) plugin_name; | 154 | pos = (char *) plugin_name; |
163 | 155 | ||
164 | GNUNET_snprintf (cfg_name, | 156 | GNUNET_snprintf (cfg_name, |
165 | sizeof (cfg_name), | 157 | sizeof (cfg_name), |
166 | "test_datacache_data_%s.conf", | 158 | "test_datacache_data_%s.conf", plugin_name); |
167 | plugin_name); | ||
168 | if (pos != plugin_name) | 159 | if (pos != plugin_name) |
169 | pos[0] = '.'; | 160 | pos[0] = '.'; |
170 | GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, | 161 | GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, |
171 | xargv, "test-datacache", "nohelp", | 162 | xargv, "test-datacache", "nohelp", options, &run, NULL); |
172 | options, &run, NULL); | ||
173 | if (ok != 0) | 163 | if (ok != 0) |
174 | fprintf (stderr, "Missed some testcases: %d\n", ok); | 164 | fprintf (stderr, "Missed some testcases: %d\n", ok); |
175 | return ok; | 165 | return ok; |
diff --git a/src/datacache/test_datacache_quota.c b/src/datacache/test_datacache_quota.c index d956ac36f..f943844a4 100644 --- a/src/datacache/test_datacache_quota.c +++ b/src/datacache/test_datacache_quota.c | |||
@@ -46,8 +46,7 @@ static const char *plugin_name; | |||
46 | static void | 46 | static void |
47 | run (void *cls, | 47 | run (void *cls, |
48 | char *const *args, | 48 | char *const *args, |
49 | const char *cfgfile, | 49 | const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) |
50 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
51 | { | 50 | { |
52 | struct GNUNET_DATACACHE_Handle *h; | 51 | struct GNUNET_DATACACHE_Handle *h; |
53 | GNUNET_HashCode k; | 52 | GNUNET_HashCode k; |
@@ -58,56 +57,43 @@ run (void *cls, | |||
58 | struct GNUNET_TIME_Absolute exp; | 57 | struct GNUNET_TIME_Absolute exp; |
59 | 58 | ||
60 | ok = 0; | 59 | ok = 0; |
61 | h = GNUNET_DATACACHE_create (cfg, | 60 | h = GNUNET_DATACACHE_create (cfg, "testcache"); |
62 | "testcache"); | ||
63 | 61 | ||
64 | if (h == NULL) | 62 | if (h == NULL) |
65 | { | 63 | { |
66 | fprintf (stderr, | 64 | fprintf (stderr, |
67 | "Failed to initialize datacache. Database likely not setup, skipping test.\n"); | 65 | "Failed to initialize datacache. Database likely not setup, skipping test.\n"); |
68 | return; | 66 | return; |
69 | } | 67 | } |
70 | exp = GNUNET_TIME_absolute_get (); | 68 | exp = GNUNET_TIME_absolute_get (); |
71 | exp.abs_value += 20 * 60 * 1000; | 69 | exp.abs_value += 20 * 60 * 1000; |
72 | memset (buf, 1, sizeof (buf)); | 70 | memset (buf, 1, sizeof (buf)); |
73 | memset (&k, 0, sizeof (GNUNET_HashCode)); | 71 | memset (&k, 0, sizeof (GNUNET_HashCode)); |
74 | for (i = 0; i < 10; i++) | 72 | for (i = 0; i < 10; i++) |
73 | { | ||
74 | fprintf (stderr, "."); | ||
75 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); | ||
76 | for (j = i; j < sizeof (buf); j += 10) | ||
75 | { | 77 | { |
76 | fprintf (stderr, "."); | 78 | exp.abs_value++; |
77 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); | 79 | buf[j] = i; |
78 | for (j = i; j < sizeof (buf); j += 10) | 80 | ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, &k, j, buf, 1 + i, exp)); |
79 | { | 81 | ASSERT (0 < GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL)); |
80 | exp.abs_value++; | ||
81 | buf[j] = i; | ||
82 | ASSERT (GNUNET_OK == | ||
83 | GNUNET_DATACACHE_put (h, | ||
84 | &k, | ||
85 | j, | ||
86 | buf, | ||
87 | 1+i, | ||
88 | exp)); | ||
89 | ASSERT (0 < GNUNET_DATACACHE_get (h, | ||
90 | &k, 1+i, | ||
91 | NULL, NULL)); | ||
92 | } | ||
93 | k = n; | ||
94 | } | 82 | } |
83 | k = n; | ||
84 | } | ||
95 | fprintf (stderr, "\n"); | 85 | fprintf (stderr, "\n"); |
96 | memset (&k, 0, sizeof (GNUNET_HashCode)); | 86 | memset (&k, 0, sizeof (GNUNET_HashCode)); |
97 | for (i = 0; i < 10; i++) | 87 | for (i = 0; i < 10; i++) |
98 | { | 88 | { |
99 | fprintf (stderr, "."); | 89 | fprintf (stderr, "."); |
100 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); | 90 | GNUNET_CRYPTO_hash (&k, sizeof (GNUNET_HashCode), &n); |
101 | if (i < 2) | 91 | if (i < 2) |
102 | ASSERT (0 == GNUNET_DATACACHE_get (h, | 92 | ASSERT (0 == GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL)); |
103 | &k, 1+i, | 93 | if (i == 9) |
104 | NULL, NULL)); | 94 | ASSERT (0 < GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL)); |
105 | if (i == 9) | 95 | k = n; |
106 | ASSERT (0 < GNUNET_DATACACHE_get (h, | 96 | } |
107 | &k, 1+i, | ||
108 | NULL, NULL)); | ||
109 | k = n; | ||
110 | } | ||
111 | fprintf (stderr, "\n"); | 97 | fprintf (stderr, "\n"); |
112 | GNUNET_DATACACHE_destroy (h); | 98 | GNUNET_DATACACHE_destroy (h); |
113 | return; | 99 | return; |
@@ -123,7 +109,8 @@ main (int argc, char *argv[]) | |||
123 | { | 109 | { |
124 | char *pos; | 110 | char *pos; |
125 | char cfg_name[128]; | 111 | char cfg_name[128]; |
126 | char *const xargv[] = { | 112 | |
113 | char *const xargv[] = { | ||
127 | "test-datacache-quota", | 114 | "test-datacache-quota", |
128 | "-c", | 115 | "-c", |
129 | cfg_name, | 116 | cfg_name, |
@@ -135,7 +122,7 @@ main (int argc, char *argv[]) | |||
135 | struct GNUNET_GETOPT_CommandLineOption options[] = { | 122 | struct GNUNET_GETOPT_CommandLineOption options[] = { |
136 | GNUNET_GETOPT_OPTION_END | 123 | GNUNET_GETOPT_OPTION_END |
137 | }; | 124 | }; |
138 | 125 | ||
139 | GNUNET_log_setup ("test-datacache-quota", | 126 | GNUNET_log_setup ("test-datacache-quota", |
140 | #if VERBOSE | 127 | #if VERBOSE |
141 | "DEBUG", | 128 | "DEBUG", |
@@ -146,17 +133,16 @@ main (int argc, char *argv[]) | |||
146 | 133 | ||
147 | /* determine name of plugin to use */ | 134 | /* determine name of plugin to use */ |
148 | plugin_name = argv[0]; | 135 | plugin_name = argv[0]; |
149 | while (NULL != (pos = strstr(plugin_name, "_"))) | 136 | while (NULL != (pos = strstr (plugin_name, "_"))) |
150 | plugin_name = pos+1; | 137 | plugin_name = pos + 1; |
151 | if (NULL != (pos = strstr(plugin_name, "."))) | 138 | if (NULL != (pos = strstr (plugin_name, "."))) |
152 | pos[0] = 0; | 139 | pos[0] = 0; |
153 | else | 140 | else |
154 | pos = (char *) plugin_name; | 141 | pos = (char *) plugin_name; |
155 | 142 | ||
156 | GNUNET_snprintf (cfg_name, | 143 | GNUNET_snprintf (cfg_name, |
157 | sizeof (cfg_name), | 144 | sizeof (cfg_name), |
158 | "test_datacache_data_%s.conf", | 145 | "test_datacache_data_%s.conf", plugin_name); |
159 | plugin_name); | ||
160 | if (pos != plugin_name) | 146 | if (pos != plugin_name) |
161 | pos[0] = '.'; | 147 | pos[0] = '.'; |
162 | GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, | 148 | GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, |