diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-06-15 23:46:00 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-06-15 23:46:00 +0200 |
commit | a99752d30c73cd5040c9da3c05da3bbc2dc1b67e (patch) | |
tree | 4319210d4664aa3354404e67911ebe771b1e43f3 | |
parent | b3ddc93861a6a171eee7c855f83c7a1314f6eaf9 (diff) | |
download | gnunet-a99752d30c73cd5040c9da3c05da3bbc2dc1b67e.tar.gz gnunet-a99752d30c73cd5040c9da3c05da3bbc2dc1b67e.zip |
fix gnunet-gns performance issue for many egos
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | src/gns/gns_tld_api.c | 88 | ||||
-rw-r--r-- | src/identity/Makefile.am | 1 | ||||
-rw-r--r-- | src/identity/gnunet-service-identity.c | 71 | ||||
-rw-r--r-- | src/identity/identity.h | 3 | ||||
-rw-r--r-- | src/include/gnunet_identity_service.h | 34 | ||||
-rw-r--r-- | src/include/gnunet_protocols.h | 9 |
7 files changed, 143 insertions, 66 deletions
@@ -1,3 +1,6 @@ | |||
1 | Sat 15 Jun 2019 11:45:35 PM CEST | ||
2 | Improved gnunet-gns performance for many ego scenario. -CG | ||
3 | |||
1 | Fri 14 Jun 2019 07:17:40 PM CEST | 4 | Fri 14 Jun 2019 07:17:40 PM CEST |
2 | Add option to gnunet-identity to display private keys. -CG | 5 | Add option to gnunet-identity to display private keys. -CG |
3 | 6 | ||
diff --git a/src/gns/gns_tld_api.c b/src/gns/gns_tld_api.c index fa4c9c057..f36b31acf 100644 --- a/src/gns/gns_tld_api.c +++ b/src/gns/gns_tld_api.c | |||
@@ -72,7 +72,7 @@ struct GNUNET_GNS_LookupWithTldRequest | |||
72 | /** | 72 | /** |
73 | * Lookup an ego with the identity service. | 73 | * Lookup an ego with the identity service. |
74 | */ | 74 | */ |
75 | struct GNUNET_IDENTITY_Handle *id_co; | 75 | struct GNUNET_IDENTITY_EgoSuffixLookup *id_co; |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * Name of the longest matching ego found so far. | 78 | * Name of the longest matching ego found so far. |
@@ -191,68 +191,37 @@ lookup_with_public_key (struct GNUNET_GNS_LookupWithTldRequest *ltr, | |||
191 | */ | 191 | */ |
192 | static void | 192 | static void |
193 | identity_zone_cb (void *cls, | 193 | identity_zone_cb (void *cls, |
194 | struct GNUNET_IDENTITY_Ego *ego, | 194 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, |
195 | void **ctx, | 195 | const char *ego_name) |
196 | const char *name) | ||
197 | { | 196 | { |
198 | struct GNUNET_GNS_LookupWithTldRequest *ltr = cls; | 197 | struct GNUNET_GNS_LookupWithTldRequest *ltr = cls; |
199 | struct GNUNET_CRYPTO_EcdsaPublicKey pkey; | 198 | struct GNUNET_CRYPTO_EcdsaPublicKey pkey; |
200 | 199 | ||
201 | if (NULL == ego) | 200 | ltr->id_co = NULL; |
201 | if (NULL == priv) | ||
202 | { | 202 | { |
203 | if (NULL != ltr->longest_match) | 203 | /* no matching ego found */ |
204 | { | 204 | ltr->lookup_proc (ltr->lookup_proc_cls, GNUNET_NO, 0, NULL); |
205 | /* Final case: TLD matches one of our egos */ | ||
206 | // FIXME: eat all of the match (not just TLD!) | ||
207 | if (0 == strcmp (ltr->name, ltr->longest_match)) | ||
208 | { | ||
209 | /* name matches ego name perfectly, only "@" remains */ | ||
210 | strcpy (ltr->name, GNUNET_GNS_EMPTY_LABEL_AT); | ||
211 | } | ||
212 | else | ||
213 | { | ||
214 | GNUNET_assert (strlen (ltr->longest_match) < strlen (ltr->name)); | ||
215 | ltr->name[strlen (ltr->name) - strlen (ltr->longest_match) - 1] = '\0'; | ||
216 | } | ||
217 | |||
218 | /* if the name is of the form 'label' (and not 'label.SUBDOMAIN'), never go to the DHT */ | ||
219 | GNUNET_free (ltr->longest_match); | ||
220 | ltr->longest_match = NULL; | ||
221 | if (NULL == strchr (ltr->name, (unsigned char) '.')) | ||
222 | ltr->options = GNUNET_GNS_LO_NO_DHT; | ||
223 | else | ||
224 | ltr->options = GNUNET_GNS_LO_LOCAL_MASTER; | ||
225 | |||
226 | GNUNET_IDENTITY_ego_get_public_key (ltr->longest_match_ego, &pkey); | ||
227 | GNUNET_IDENTITY_disconnect (ltr->id_co); | ||
228 | ltr->id_co = NULL; | ||
229 | lookup_with_public_key (ltr, &pkey); | ||
230 | } | ||
231 | else | ||
232 | { | ||
233 | /* no matching ego found */ | ||
234 | GNUNET_IDENTITY_disconnect (ltr->id_co); | ||
235 | ltr->id_co = NULL; | ||
236 | ltr->lookup_proc (ltr->lookup_proc_cls, GNUNET_NO, 0, NULL); | ||
237 | GNUNET_GNS_lookup_with_tld_cancel (ltr); | ||
238 | } | ||
239 | return; | 205 | return; |
240 | } | 206 | } |
241 | else if (NULL != name) | 207 | /* Final case: TLD matches one of our egos */ |
208 | if (0 == strcmp (ltr->name, ego_name)) | ||
242 | { | 209 | { |
243 | if ((strlen (name) <= strlen (ltr->name)) && | 210 | /* name matches ego name perfectly, only "@" remains */ |
244 | (0 == strcmp (name, <r->name[strlen (ltr->name) - strlen (name)])) && | 211 | strcpy (ltr->name, GNUNET_GNS_EMPTY_LABEL_AT); |
245 | ((strlen (name) == strlen (ltr->name)) || | ||
246 | ('.' == ltr->name[strlen (ltr->name) - strlen (name) - 1])) && | ||
247 | ((NULL == ltr->longest_match) || | ||
248 | (strlen (name) > strlen (ltr->longest_match)))) | ||
249 | { | ||
250 | /* found better match, update! */ | ||
251 | GNUNET_free_non_null (ltr->longest_match); | ||
252 | ltr->longest_match = GNUNET_strdup (name); | ||
253 | ltr->longest_match_ego = ego; | ||
254 | } | ||
255 | } | 212 | } |
213 | else | ||
214 | { | ||
215 | GNUNET_assert (strlen (ego_name) < strlen (ltr->name)); | ||
216 | ltr->name[strlen (ltr->name) - strlen (ego_name) - 1] = '\0'; | ||
217 | } | ||
218 | /* if the name is of the form 'label' (and not 'label.SUBDOMAIN'), never go to the DHT */ | ||
219 | if (NULL == strchr (ltr->name, (unsigned char) '.')) | ||
220 | ltr->options = GNUNET_GNS_LO_NO_DHT; | ||
221 | else | ||
222 | ltr->options = GNUNET_GNS_LO_LOCAL_MASTER; | ||
223 | GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pkey); | ||
224 | lookup_with_public_key (ltr, &pkey); | ||
256 | } | 225 | } |
257 | 226 | ||
258 | 227 | ||
@@ -336,12 +305,11 @@ GNUNET_GNS_lookup_with_tld (struct GNUNET_GNS_Handle *handle, | |||
336 | } | 305 | } |
337 | GNUNET_free (dot_tld); | 306 | GNUNET_free (dot_tld); |
338 | } | 307 | } |
339 | /* FIXME: this call is still shitty slow to do the longest | ||
340 | suffix if we have thousands of egos. We should modify | ||
341 | the IDENTITY API to do the longest suffix matching | ||
342 | inside of the identity service and not do an O(n) IPC! */ | ||
343 | ltr->id_co = | 308 | ltr->id_co = |
344 | GNUNET_IDENTITY_connect (ltr->gns_handle->cfg, &identity_zone_cb, ltr); | 309 | GNUNET_IDENTITY_ego_lookup_by_suffix (ltr->gns_handle->cfg, |
310 | ltr->name, | ||
311 | &identity_zone_cb, | ||
312 | ltr); | ||
345 | if (NULL == ltr->id_co) | 313 | if (NULL == ltr->id_co) |
346 | { | 314 | { |
347 | GNUNET_free (ltr->name); | 315 | GNUNET_free (ltr->name); |
@@ -365,7 +333,7 @@ GNUNET_GNS_lookup_with_tld_cancel (struct GNUNET_GNS_LookupWithTldRequest *ltr) | |||
365 | 333 | ||
366 | if (NULL != ltr->id_co) | 334 | if (NULL != ltr->id_co) |
367 | { | 335 | { |
368 | GNUNET_IDENTITY_disconnect (ltr->id_co); | 336 | GNUNET_IDENTITY_ego_lookup_by_suffix_cancel (ltr->id_co); |
369 | ltr->id_co = NULL; | 337 | ltr->id_co = NULL; |
370 | } | 338 | } |
371 | if (NULL != ltr->lr) | 339 | if (NULL != ltr->lr) |
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am index 6e587dc86..476d981bb 100644 --- a/src/identity/Makefile.am +++ b/src/identity/Makefile.am | |||
@@ -43,6 +43,7 @@ libgnunet_plugin_rest_identity_la_LDFLAGS = \ | |||
43 | libgnunetidentity_la_SOURCES = \ | 43 | libgnunetidentity_la_SOURCES = \ |
44 | identity_api.c \ | 44 | identity_api.c \ |
45 | identity_api_lookup.c \ | 45 | identity_api_lookup.c \ |
46 | identity_api_suffix_lookup.c \ | ||
46 | identity.h | 47 | identity.h |
47 | libgnunetidentity_la_LIBADD = \ | 48 | libgnunetidentity_la_LIBADD = \ |
48 | $(top_builddir)/src/util/libgnunetutil.la \ | 49 | $(top_builddir)/src/util/libgnunetutil.la \ |
diff --git a/src/identity/gnunet-service-identity.c b/src/identity/gnunet-service-identity.c index a675a01f0..3e92a04cd 100644 --- a/src/identity/gnunet-service-identity.c +++ b/src/identity/gnunet-service-identity.c | |||
@@ -378,6 +378,73 @@ handle_lookup_message (void *cls, | |||
378 | 378 | ||
379 | 379 | ||
380 | /** | 380 | /** |
381 | * Handler for LOOKUP message from client, sends information | ||
382 | * about ONE identity to the client immediately. | ||
383 | * | ||
384 | * @param cls unused | ||
385 | * @param message the message received | ||
386 | * @return #GNUNET_SYSERR if message was ill-formed | ||
387 | */ | ||
388 | static int | ||
389 | check_lookup_by_suffix_message (void *cls, | ||
390 | const struct LookupMessage *message) | ||
391 | { | ||
392 | GNUNET_MQ_check_zero_termination (message); | ||
393 | return GNUNET_OK; | ||
394 | } | ||
395 | |||
396 | |||
397 | /** | ||
398 | * Handler for LOOKUP_BY_SUFFIX message from client, sends information | ||
399 | * about ONE identity to the client immediately. | ||
400 | * | ||
401 | * @param cls a `struct GNUNET_SERVICE_Client *` | ||
402 | * @param message the message received | ||
403 | */ | ||
404 | static void | ||
405 | handle_lookup_by_suffix_message (void *cls, | ||
406 | const struct LookupMessage *message) | ||
407 | { | ||
408 | struct GNUNET_SERVICE_Client *client = cls; | ||
409 | const char *name; | ||
410 | struct GNUNET_MQ_Envelope *env; | ||
411 | struct Ego *lprefix; | ||
412 | |||
413 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
414 | "Received LOOKUP_BY_SUFFIX message from client\n"); | ||
415 | name = (const char *) &message[1]; | ||
416 | lprefix = NULL; | ||
417 | for (struct Ego *ego = ego_head; NULL != ego; ego = ego->next) | ||
418 | { | ||
419 | |||
420 | if ((strlen (ego->identifier) <= strlen (name)) && | ||
421 | (0 == strcmp (ego->identifier, | ||
422 | &name[strlen (name) - strlen (ego->identifier)])) && | ||
423 | ((strlen (name) == strlen (ego->identifier)) || | ||
424 | ('.' == name[strlen (name) - | ||
425 | strlen (ego->identifier) - 1])) && | ||
426 | ((NULL == lprefix) || | ||
427 | (strlen (ego->identifier) > strlen (lprefix->identifier)))) | ||
428 | { | ||
429 | /* found better match, update! */ | ||
430 | lprefix = ego; | ||
431 | } | ||
432 | } | ||
433 | if (NULL != lprefix) | ||
434 | { | ||
435 | env = create_update_message (lprefix); | ||
436 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env); | ||
437 | GNUNET_SERVICE_client_continue (client); | ||
438 | return; | ||
439 | } | ||
440 | send_result_code (client, | ||
441 | 0, | ||
442 | "ego not found"); | ||
443 | GNUNET_SERVICE_client_continue (client); | ||
444 | } | ||
445 | |||
446 | |||
447 | /** | ||
381 | * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT message | 448 | * Checks a #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT message |
382 | * | 449 | * |
383 | * @param cls client sending the message | 450 | * @param cls client sending the message |
@@ -1118,6 +1185,10 @@ GNUNET_SERVICE_MAIN | |||
1118 | GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP, | 1185 | GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP, |
1119 | struct LookupMessage, | 1186 | struct LookupMessage, |
1120 | NULL), | 1187 | NULL), |
1188 | GNUNET_MQ_hd_var_size (lookup_by_suffix_message, | ||
1189 | GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP_BY_SUFFIX, | ||
1190 | struct LookupMessage, | ||
1191 | NULL), | ||
1121 | GNUNET_MQ_hd_var_size (get_default_message, | 1192 | GNUNET_MQ_hd_var_size (get_default_message, |
1122 | GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT, | 1193 | GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT, |
1123 | struct GetDefaultMessage, | 1194 | struct GetDefaultMessage, |
diff --git a/src/identity/identity.h b/src/identity/identity.h index 96550bdf2..6ef16e39d 100644 --- a/src/identity/identity.h +++ b/src/identity/identity.h | |||
@@ -62,7 +62,8 @@ struct ResultCodeMessage | |||
62 | struct LookupMessage | 62 | struct LookupMessage |
63 | { | 63 | { |
64 | /** | 64 | /** |
65 | * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP | 65 | * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP or |
66 | * #GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP_BY_SUFFIX | ||
66 | */ | 67 | */ |
67 | struct GNUNET_MessageHeader header; | 68 | struct GNUNET_MessageHeader header; |
68 | 69 | ||
diff --git a/src/include/gnunet_identity_service.h b/src/include/gnunet_identity_service.h index b2472da43..52ed1e908 100644 --- a/src/include/gnunet_identity_service.h +++ b/src/include/gnunet_identity_service.h | |||
@@ -328,6 +328,24 @@ GNUNET_IDENTITY_ego_lookup (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
328 | void | 328 | void |
329 | GNUNET_IDENTITY_ego_lookup_cancel (struct GNUNET_IDENTITY_EgoLookup *el); | 329 | GNUNET_IDENTITY_ego_lookup_cancel (struct GNUNET_IDENTITY_EgoLookup *el); |
330 | 330 | ||
331 | /** | ||
332 | * Function called with the result. | ||
333 | * | ||
334 | * @param cls closure | ||
335 | * @param ego NULL on error / ego not found | ||
336 | * @param ego_name NULL on error, name of the ego otherwise | ||
337 | */ | ||
338 | typedef void (*GNUNET_IDENTITY_EgoSuffixCallback) ( | ||
339 | void *cls, | ||
340 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, | ||
341 | const char *ego_name); | ||
342 | |||
343 | |||
344 | /** | ||
345 | * Handle for suffix lookup. | ||
346 | */ | ||
347 | struct GNUNET_IDENTITY_EgoSuffixLookup; | ||
348 | |||
331 | 349 | ||
332 | /** | 350 | /** |
333 | * Obtain the ego with the maximum suffix match between the | 351 | * Obtain the ego with the maximum suffix match between the |
@@ -335,20 +353,26 @@ GNUNET_IDENTITY_ego_lookup_cancel (struct GNUNET_IDENTITY_EgoLookup *el); | |||
335 | * a @a suffix "a.b.c" and egos with names "d.a.b.c", "b.c" and "c", | 353 | * a @a suffix "a.b.c" and egos with names "d.a.b.c", "b.c" and "c", |
336 | * we return the ego for "b.c". | 354 | * we return the ego for "b.c". |
337 | * | 355 | * |
338 | * @param id identity service to query | 356 | * @param cfg configuration to use |
339 | * @param suffix for which domain name suffix is an identity wanted | 357 | * @param suffix for which domain name suffix is an identity wanted |
340 | * @param cb function to call with the result (will only be called once) | 358 | * @param cb function to call with the result (will only be called once) |
341 | * @param cb_cls closure for @a cb | 359 | * @param cb_cls closure for @a cb |
342 | * @return handle to abort the operation | 360 | * @return handle to abort the operation |
343 | */ | 361 | */ |
344 | struct GNUNET_IDENTITY_EgoLookup * | 362 | struct GNUNET_IDENTITY_EgoSuffixLookup * |
345 | GNUNET_IDENTITY_ego_lookup_by_suffix (struct GNUNET_IDENTITY_Handle *id, | 363 | GNUNET_IDENTITY_ego_lookup_by_suffix (const struct GNUNET_CONFIGURATION_Handle *cfg, |
346 | const char *suffix, | 364 | const char *suffix, |
347 | GNUNET_IDENTITY_EgoCallback cb, | 365 | GNUNET_IDENTITY_EgoSuffixCallback cb, |
348 | void *cb_cls); | 366 | void *cb_cls); |
349 | 367 | ||
350 | 368 | ||
351 | 369 | /** | |
370 | * Abort ego suffix lookup attempt. | ||
371 | * | ||
372 | * @param el handle for lookup to abort | ||
373 | */ | ||
374 | void | ||
375 | GNUNET_IDENTITY_ego_lookup_by_suffix_cancel (struct GNUNET_IDENTITY_EgoSuffixLookup *el); | ||
352 | 376 | ||
353 | #if 0 /* keep Emacsens' auto-indent happy */ | 377 | #if 0 /* keep Emacsens' auto-indent happy */ |
354 | { | 378 | { |
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index d93e12bfb..45bfa4f1b 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h | |||
@@ -1948,6 +1948,15 @@ extern "C" { | |||
1948 | */ | 1948 | */ |
1949 | #define GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP 632 | 1949 | #define GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP 632 |
1950 | 1950 | ||
1951 | /** | ||
1952 | * First message send from identity client to service to lookup a | ||
1953 | * single ego matching the given suffix (longest match). The service | ||
1954 | * will respond with a #GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE message if | ||
1955 | * the ego exists, or a #GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE if | ||
1956 | * not. | ||
1957 | */ | ||
1958 | #define GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP_BY_SUFFIX 633 | ||
1959 | |||
1951 | 1960 | ||
1952 | /******************************************************************************* | 1961 | /******************************************************************************* |
1953 | * REVOCATION message types | 1962 | * REVOCATION message types |