diff options
Diffstat (limited to 'src/namestore/gnunet-zoneimport.c')
-rw-r--r-- | src/namestore/gnunet-zoneimport.c | 279 |
1 files changed, 131 insertions, 148 deletions
diff --git a/src/namestore/gnunet-zoneimport.c b/src/namestore/gnunet-zoneimport.c index 4d595e554..0148f42a7 100644 --- a/src/namestore/gnunet-zoneimport.c +++ b/src/namestore/gnunet-zoneimport.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <gnunet_dnsstub_lib.h> | 30 | #include <gnunet_dnsstub_lib.h> |
31 | #include <gnunet_dnsparser_lib.h> | 31 | #include <gnunet_dnsparser_lib.h> |
32 | #include <gnunet_gnsrecord_lib.h> | 32 | #include <gnunet_gnsrecord_lib.h> |
33 | #include <gnunet_namestore_plugin.h> | 33 | #include <gnunet_namestore_service.h> |
34 | #include <gnunet_identity_service.h> | 34 | #include <gnunet_identity_service.h> |
35 | 35 | ||
36 | 36 | ||
@@ -164,6 +164,11 @@ struct Request | |||
164 | char *label; | 164 | char *label; |
165 | 165 | ||
166 | /** | 166 | /** |
167 | * Namestore operation pending for this record. | ||
168 | */ | ||
169 | struct GNUNET_NAMESTORE_QueueEntry *qe; | ||
170 | |||
171 | /** | ||
167 | * Zone responsible for this request. | 172 | * Zone responsible for this request. |
168 | */ | 173 | */ |
169 | const struct Zone *zone; | 174 | const struct Zone *zone; |
@@ -210,9 +215,9 @@ struct Request | |||
210 | static struct GNUNET_IDENTITY_Handle *id; | 215 | static struct GNUNET_IDENTITY_Handle *id; |
211 | 216 | ||
212 | /** | 217 | /** |
213 | * Namestore plugin. | 218 | * Namestore handle. |
214 | */ | 219 | */ |
215 | static struct GNUNET_NAMESTORE_PluginFunctions *ns; | 220 | static struct GNUNET_NAMESTORE_Handle *ns; |
216 | 221 | ||
217 | /** | 222 | /** |
218 | * Context for DNS resolution. | 223 | * Context for DNS resolution. |
@@ -271,11 +276,6 @@ static struct GNUNET_SCHEDULER_Task *t; | |||
271 | static char *dns_server; | 276 | static char *dns_server; |
272 | 277 | ||
273 | /** | 278 | /** |
274 | * Name of the database plugin (for loading/unloading). | ||
275 | */ | ||
276 | static char *db_lib_name; | ||
277 | |||
278 | /** | ||
279 | * Head of list of zones we are managing. | 279 | * Head of list of zones we are managing. |
280 | */ | 280 | */ |
281 | static struct Zone *zone_head; | 281 | static struct Zone *zone_head; |
@@ -285,16 +285,6 @@ static struct Zone *zone_head; | |||
285 | */ | 285 | */ |
286 | static struct Zone *zone_tail; | 286 | static struct Zone *zone_tail; |
287 | 287 | ||
288 | /** | ||
289 | * Set to #GNUNET_YES if we are currently in a DB transaction. | ||
290 | */ | ||
291 | static int in_transaction; | ||
292 | |||
293 | /** | ||
294 | * Flag set if we should use transactions to batch DB operations. | ||
295 | */ | ||
296 | static int use_transactions; | ||
297 | |||
298 | 288 | ||
299 | /** | 289 | /** |
300 | * Callback for #for_all_records | 290 | * Callback for #for_all_records |
@@ -790,6 +780,41 @@ process_record (void *cls, | |||
790 | 780 | ||
791 | 781 | ||
792 | /** | 782 | /** |
783 | * Continuation called to notify client about result of the | ||
784 | * operation. | ||
785 | * | ||
786 | * @param cls closure with our `struct Request` | ||
787 | * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) | ||
788 | * #GNUNET_NO if content was already there or not found | ||
789 | * #GNUNET_YES (or other positive value) on success | ||
790 | * @param emsg NULL on success, otherwise an error message | ||
791 | */ | ||
792 | static void | ||
793 | store_completed_cb (void *cls, | ||
794 | int32_t success, | ||
795 | const char *emsg) | ||
796 | { | ||
797 | struct Request *req = cls; | ||
798 | |||
799 | req->qe = NULL; | ||
800 | pending--; | ||
801 | if (GNUNET_SYSERR == success) | ||
802 | { | ||
803 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
804 | "Failed to store zone data for `%s': %s\n", | ||
805 | req->hostname, | ||
806 | emsg); | ||
807 | } | ||
808 | else | ||
809 | { | ||
810 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
811 | "Stored records under `%s'\n", | ||
812 | req->label); | ||
813 | } | ||
814 | } | ||
815 | |||
816 | |||
817 | /** | ||
793 | * Function called with the result of a DNS resolution. | 818 | * Function called with the result of a DNS resolution. |
794 | * | 819 | * |
795 | * @param cls closure with the `struct Request` | 820 | * @param cls closure with the `struct Request` |
@@ -835,7 +860,6 @@ process_result (void *cls, | |||
835 | GNUNET_CONTAINER_DLL_remove (req_head, | 860 | GNUNET_CONTAINER_DLL_remove (req_head, |
836 | req_tail, | 861 | req_tail, |
837 | req); | 862 | req); |
838 | pending--; | ||
839 | GNUNET_DNSSTUB_resolve_cancel (req->rs); | 863 | GNUNET_DNSSTUB_resolve_cancel (req->rs); |
840 | req->rs = NULL; | 864 | req->rs = NULL; |
841 | p = GNUNET_DNSPARSER_parse ((const char *) dns, | 865 | p = GNUNET_DNSPARSER_parse ((const char *) dns, |
@@ -849,9 +873,11 @@ process_result (void *cls, | |||
849 | { | 873 | { |
850 | failures++; | 874 | failures++; |
851 | insert_sorted (req); | 875 | insert_sorted (req); |
876 | pending--; | ||
852 | return; | 877 | return; |
853 | } | 878 | } |
854 | insert_sorted (req); | 879 | insert_sorted (req); |
880 | pending--; | ||
855 | return; | 881 | return; |
856 | } | 882 | } |
857 | /* Free old/legacy records */ | 883 | /* Free old/legacy records */ |
@@ -899,34 +925,13 @@ process_result (void *cls, | |||
899 | /* convert linked list into array */ | 925 | /* convert linked list into array */ |
900 | for (rec = req->rec_head; NULL != rec; rec =rec->next) | 926 | for (rec = req->rec_head; NULL != rec; rec =rec->next) |
901 | rd[off++] = rec->grd; | 927 | rd[off++] = rec->grd; |
902 | if ( (! in_transaction) && | 928 | req->qe = GNUNET_NAMESTORE_records_store (ns, |
903 | (GNUNET_YES == use_transactions) ) | 929 | &req->zone->key, |
904 | { | 930 | req->label, |
905 | /* not all plugins support transactions, but if one does, | 931 | rd_count, |
906 | remember we need to eventually commit... */ | 932 | rd, |
907 | if (GNUNET_OK == | 933 | &store_completed_cb, |
908 | ns->begin_transaction (ns->cls)) | 934 | req); |
909 | in_transaction = GNUNET_YES; | ||
910 | } | ||
911 | if (GNUNET_OK != | ||
912 | ns->store_records (ns->cls, | ||
913 | &req->zone->key, | ||
914 | req->label, | ||
915 | rd_count, | ||
916 | rd)) | ||
917 | { | ||
918 | if (0 != rd_count) | ||
919 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
920 | "Failed to store zone data for `%s'\n", | ||
921 | req->hostname); | ||
922 | } | ||
923 | else | ||
924 | { | ||
925 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
926 | "Stored %u records under `%s'\n", | ||
927 | (unsigned int) rd_count, | ||
928 | req->label); | ||
929 | } | ||
930 | } | 935 | } |
931 | insert_sorted (req); | 936 | insert_sorted (req); |
932 | } | 937 | } |
@@ -947,6 +952,8 @@ submit_req (struct Request *req) | |||
947 | static struct GNUNET_TIME_Absolute last_request; | 952 | static struct GNUNET_TIME_Absolute last_request; |
948 | struct GNUNET_TIME_Absolute now; | 953 | struct GNUNET_TIME_Absolute now; |
949 | 954 | ||
955 | if (NULL != req->qe) | ||
956 | return GNUNET_NO; /* namestore op still pending */ | ||
950 | if (NULL != req->rs) | 957 | if (NULL != req->rs) |
951 | { | 958 | { |
952 | GNUNET_break (0); | 959 | GNUNET_break (0); |
@@ -979,25 +986,6 @@ submit_req (struct Request *req) | |||
979 | 986 | ||
980 | 987 | ||
981 | /** | 988 | /** |
982 | * If we are currently in a transaction, commit it. | ||
983 | */ | ||
984 | static void | ||
985 | finish_transaction () | ||
986 | { | ||
987 | if (! in_transaction) | ||
988 | return; | ||
989 | if (GNUNET_OK != | ||
990 | ns->commit_transaction (ns->cls)) | ||
991 | { | ||
992 | GNUNET_break (0); | ||
993 | GNUNET_SCHEDULER_shutdown (); | ||
994 | return; | ||
995 | } | ||
996 | in_transaction = GNUNET_NO; | ||
997 | } | ||
998 | |||
999 | |||
1000 | /** | ||
1001 | * Process as many requests as possible from the queue. | 989 | * Process as many requests as possible from the queue. |
1002 | * | 990 | * |
1003 | * @param cls NULL | 991 | * @param cls NULL |
@@ -1006,7 +994,6 @@ static void | |||
1006 | process_queue (void *cls) | 994 | process_queue (void *cls) |
1007 | { | 995 | { |
1008 | struct Request *req; | 996 | struct Request *req; |
1009 | static unsigned int cnt; | ||
1010 | 997 | ||
1011 | (void) cls; | 998 | (void) cls; |
1012 | t = NULL; | 999 | t = NULL; |
@@ -1033,7 +1020,6 @@ process_queue (void *cls) | |||
1033 | "Waiting until %s for next record (`%s') to expire\n", | 1020 | "Waiting until %s for next record (`%s') to expire\n", |
1034 | GNUNET_STRINGS_absolute_time_to_string (req->expires), | 1021 | GNUNET_STRINGS_absolute_time_to_string (req->expires), |
1035 | req->hostname); | 1022 | req->hostname); |
1036 | finish_transaction (); | ||
1037 | if (NULL != t) | 1023 | if (NULL != t) |
1038 | GNUNET_SCHEDULER_cancel (t); | 1024 | GNUNET_SCHEDULER_cancel (t); |
1039 | t = GNUNET_SCHEDULER_add_at (req->expires, | 1025 | t = GNUNET_SCHEDULER_add_at (req->expires, |
@@ -1042,8 +1028,6 @@ process_queue (void *cls) | |||
1042 | } | 1028 | } |
1043 | else | 1029 | else |
1044 | { | 1030 | { |
1045 | if (0 == cnt++ % TRANSACTION_SYNC_FREQ) | ||
1046 | finish_transaction (); | ||
1047 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1031 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1048 | "Throttling for 1ms\n"); | 1032 | "Throttling for 1ms\n"); |
1049 | if (NULL != t) | 1033 | if (NULL != t) |
@@ -1077,14 +1061,10 @@ do_shutdown (void *cls) | |||
1077 | GNUNET_SCHEDULER_cancel (t); | 1061 | GNUNET_SCHEDULER_cancel (t); |
1078 | t = NULL; | 1062 | t = NULL; |
1079 | } | 1063 | } |
1080 | finish_transaction (); | ||
1081 | if (NULL != ns) | 1064 | if (NULL != ns) |
1082 | { | 1065 | { |
1083 | GNUNET_break (NULL == | 1066 | GNUNET_NAMESTORE_disconnect (ns); |
1084 | GNUNET_PLUGIN_unload (db_lib_name, | 1067 | ns = NULL; |
1085 | ns)); | ||
1086 | GNUNET_free (db_lib_name); | ||
1087 | db_lib_name = NULL; | ||
1088 | } | 1068 | } |
1089 | if (NULL != ctx) | 1069 | if (NULL != ctx) |
1090 | { | 1070 | { |
@@ -1120,26 +1100,46 @@ do_shutdown (void *cls) | |||
1120 | 1100 | ||
1121 | 1101 | ||
1122 | /** | 1102 | /** |
1123 | * Function called for each matching record. | 1103 | * Function called if #GNUNET_NAMESTORE_records_lookup() failed. |
1104 | * Continues resolution based on assumption namestore has no data. | ||
1124 | * | 1105 | * |
1125 | * @param cls `struct Request *` | 1106 | * @param cls a `struct Request` |
1126 | * @param zone_key private key of the zone | ||
1127 | * @param label name that is being mapped (at most 255 characters long) | ||
1128 | * @param rd_count number of entries in @a rd array | ||
1129 | * @param rd array of records with data to store | ||
1130 | */ | 1107 | */ |
1131 | static void | 1108 | static void |
1132 | import_records (void *cls, | 1109 | ns_lookup_error_cb (void *cls) |
1133 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key, | ||
1134 | const char *label, | ||
1135 | unsigned int rd_count, | ||
1136 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1137 | { | 1110 | { |
1138 | struct Request *req = cls; | 1111 | struct Request *req = cls; |
1139 | 1112 | ||
1140 | GNUNET_break (0 == memcmp (private_key, | 1113 | req->qe = NULL; |
1114 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1115 | "Failed to load data from namestore for `%s'\n", | ||
1116 | req->label); | ||
1117 | insert_sorted (req); | ||
1118 | } | ||
1119 | |||
1120 | |||
1121 | /** | ||
1122 | * Process a record that was stored in the namestore. | ||
1123 | * | ||
1124 | * @param cls a `struct Request *` | ||
1125 | * @param zone private key of the zone | ||
1126 | * @param label label of the records | ||
1127 | * @param rd_count number of entries in @a rd array, 0 if label was deleted | ||
1128 | * @param rd array of records with data to store | ||
1129 | */ | ||
1130 | static void | ||
1131 | ns_lookup_result_cb (void *cls, | ||
1132 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
1133 | const char *label, | ||
1134 | unsigned int rd_count, | ||
1135 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1136 | { | ||
1137 | struct Request *req = cls; | ||
1138 | |||
1139 | req->qe = NULL; | ||
1140 | GNUNET_break (0 == memcmp (zone, | ||
1141 | &req->zone->key, | 1141 | &req->zone->key, |
1142 | sizeof (*private_key))); | 1142 | sizeof (*zone))); |
1143 | GNUNET_break (0 == strcasecmp (label, | 1143 | GNUNET_break (0 == strcasecmp (label, |
1144 | req->label)); | 1144 | req->label)); |
1145 | for (unsigned int i=0;i<rd_count;i++) | 1145 | for (unsigned int i=0;i<rd_count;i++) |
@@ -1153,6 +1153,40 @@ import_records (void *cls, | |||
1153 | rd->data, | 1153 | rd->data, |
1154 | rd->data_size); | 1154 | rd->data_size); |
1155 | } | 1155 | } |
1156 | if (0 == rd_count) | ||
1157 | { | ||
1158 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1159 | "Empty record set in namestore for `%s'\n", | ||
1160 | req->label); | ||
1161 | } | ||
1162 | else | ||
1163 | { | ||
1164 | unsigned int pos = 0; | ||
1165 | |||
1166 | req->expires = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
1167 | for (struct Record *rec = req->rec_head; | ||
1168 | NULL != rec; | ||
1169 | rec = rec->next) | ||
1170 | { | ||
1171 | struct GNUNET_TIME_Absolute at; | ||
1172 | |||
1173 | at.abs_value_us = rec->grd.expiration_time; | ||
1174 | req->expires = GNUNET_TIME_absolute_min (req->expires, | ||
1175 | at); | ||
1176 | pos++; | ||
1177 | } | ||
1178 | if (0 == pos) | ||
1179 | req->expires = GNUNET_TIME_UNIT_ZERO_ABS; | ||
1180 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1181 | "Hot-start with %u existing records for `%s'\n", | ||
1182 | pos, | ||
1183 | req->label); | ||
1184 | } | ||
1185 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1186 | "Adding `%s' to worklist to start at %s\n", | ||
1187 | req->hostname, | ||
1188 | GNUNET_STRINGS_absolute_time_to_string (req->expires)); | ||
1189 | insert_sorted (req); | ||
1156 | } | 1190 | } |
1157 | 1191 | ||
1158 | 1192 | ||
@@ -1236,45 +1270,13 @@ queue (const char *hostname) | |||
1236 | req->id = p.id; | 1270 | req->id = p.id; |
1237 | req->label = GNUNET_strndup (hostname, | 1271 | req->label = GNUNET_strndup (hostname, |
1238 | dot - hostname); | 1272 | dot - hostname); |
1239 | if (GNUNET_OK != | 1273 | req->qe = GNUNET_NAMESTORE_records_lookup (ns, |
1240 | ns->lookup_records (ns->cls, | 1274 | &req->zone->key, |
1241 | &req->zone->key, | 1275 | req->label, |
1242 | req->label, | 1276 | &ns_lookup_error_cb, |
1243 | &import_records, | 1277 | req, |
1244 | req)) | 1278 | &ns_lookup_result_cb, |
1245 | { | 1279 | req); |
1246 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1247 | "Failed to load data from namestore for `%s'\n", | ||
1248 | req->label); | ||
1249 | } | ||
1250 | else | ||
1251 | { | ||
1252 | unsigned int rd_count = 0; | ||
1253 | |||
1254 | req->expires = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
1255 | for (struct Record *rec = req->rec_head; | ||
1256 | NULL != rec; | ||
1257 | rec = rec->next) | ||
1258 | { | ||
1259 | struct GNUNET_TIME_Absolute at; | ||
1260 | |||
1261 | at.abs_value_us = rec->grd.expiration_time; | ||
1262 | req->expires = GNUNET_TIME_absolute_min (req->expires, | ||
1263 | at); | ||
1264 | rd_count++; | ||
1265 | } | ||
1266 | if (0 == rd_count) | ||
1267 | req->expires = GNUNET_TIME_UNIT_ZERO_ABS; | ||
1268 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1269 | "Hot-start with %u existing records for `%s'\n", | ||
1270 | rd_count, | ||
1271 | req->label); | ||
1272 | } | ||
1273 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1274 | "Adding `%s' to worklist to start at %s\n", | ||
1275 | req->hostname, | ||
1276 | GNUNET_STRINGS_absolute_time_to_string (req->expires)); | ||
1277 | insert_sorted (req); | ||
1278 | } | 1280 | } |
1279 | 1281 | ||
1280 | 1282 | ||
@@ -1390,8 +1392,6 @@ run (void *cls, | |||
1390 | const char *cfgfile, | 1392 | const char *cfgfile, |
1391 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 1393 | const struct GNUNET_CONFIGURATION_Handle *cfg) |
1392 | { | 1394 | { |
1393 | char *database; | ||
1394 | |||
1395 | (void) cls; | 1395 | (void) cls; |
1396 | (void) args; | 1396 | (void) args; |
1397 | (void) cfgfile; | 1397 | (void) cfgfile; |
@@ -1403,22 +1403,9 @@ run (void *cls, | |||
1403 | "Failed to initialize GNUnet DNS STUB\n"); | 1403 | "Failed to initialize GNUnet DNS STUB\n"); |
1404 | return; | 1404 | return; |
1405 | } | 1405 | } |
1406 | if (GNUNET_OK != | ||
1407 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
1408 | "namestore", | ||
1409 | "database", | ||
1410 | &database)) | ||
1411 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1412 | "No database backend configured\n"); | ||
1413 | |||
1414 | GNUNET_asprintf (&db_lib_name, | ||
1415 | "libgnunet_plugin_namestore_%s", | ||
1416 | database); | ||
1417 | ns = GNUNET_PLUGIN_load (db_lib_name, | ||
1418 | (void *) cfg); | ||
1419 | GNUNET_free (database); | ||
1420 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, | 1406 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, |
1421 | NULL); | 1407 | NULL); |
1408 | ns = GNUNET_NAMESTORE_connect (cfg); | ||
1422 | if (NULL == ns) | 1409 | if (NULL == ns) |
1423 | { | 1410 | { |
1424 | GNUNET_SCHEDULER_shutdown (); | 1411 | GNUNET_SCHEDULER_shutdown (); |
@@ -1448,10 +1435,6 @@ main (int argc, | |||
1448 | "IP", | 1435 | "IP", |
1449 | "which DNS server should be used", | 1436 | "which DNS server should be used", |
1450 | &dns_server)), | 1437 | &dns_server)), |
1451 | GNUNET_GETOPT_option_flag ('e', | ||
1452 | "enable-transactions", | ||
1453 | "enable use of transactions to reduce disk IO", | ||
1454 | &use_transactions), | ||
1455 | GNUNET_GETOPT_OPTION_END | 1438 | GNUNET_GETOPT_OPTION_END |
1456 | }; | 1439 | }; |
1457 | 1440 | ||