diff options
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | src/datastore/gnunet-service-datastore.c | 190 |
2 files changed, 151 insertions, 42 deletions
@@ -6,9 +6,6 @@ | |||
6 | * UTIL: | 6 | * UTIL: |
7 | - only connect() sockets that are ready (select()) [Nils] | 7 | - only connect() sockets that are ready (select()) [Nils] |
8 | [On W32, we need to select after calling socket before doing connect etc.] | 8 | [On W32, we need to select after calling socket before doing connect etc.] |
9 | * DATASTORE [CG]: | ||
10 | - check for duplicates on insertion (currently, same content is frequently | ||
11 | stored again [seen with KBLOCKS and SBLOCKS]!) | ||
12 | * GNUNET-GTK: [CG] | 9 | * GNUNET-GTK: [CG] |
13 | - directory support: | 10 | - directory support: |
14 | + download start: recursive/directory (!) & from-URI only | 11 | + download start: recursive/directory (!) & from-URI only |
diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c index faae1ae99..073c74dd9 100644 --- a/src/datastore/gnunet-service-datastore.c +++ b/src/datastore/gnunet-service-datastore.c | |||
@@ -870,6 +870,142 @@ check_data (const struct GNUNET_MessageHeader *message) | |||
870 | 870 | ||
871 | 871 | ||
872 | /** | 872 | /** |
873 | * Context for a put request used to see if the content is | ||
874 | * already present. | ||
875 | */ | ||
876 | struct PutContext | ||
877 | { | ||
878 | /** | ||
879 | * Client to notify on completion. | ||
880 | */ | ||
881 | struct GNUNET_SERVER_Client *client; | ||
882 | |||
883 | /** | ||
884 | * Did we find the data already in the database? | ||
885 | */ | ||
886 | int is_present; | ||
887 | |||
888 | /* followed by the 'struct DataMessage' */ | ||
889 | }; | ||
890 | |||
891 | |||
892 | /** | ||
893 | * Actually put the data message. | ||
894 | */ | ||
895 | static void | ||
896 | execute_put (struct GNUNET_SERVER_Client *client, | ||
897 | const struct DataMessage *dm) | ||
898 | { | ||
899 | uint32_t size; | ||
900 | char *msg; | ||
901 | int ret; | ||
902 | |||
903 | size = ntohl(dm->size); | ||
904 | msg = NULL; | ||
905 | ret = plugin->api->put (plugin->api->cls, | ||
906 | &dm->key, | ||
907 | size, | ||
908 | &dm[1], | ||
909 | ntohl(dm->type), | ||
910 | ntohl(dm->priority), | ||
911 | ntohl(dm->anonymity), | ||
912 | GNUNET_TIME_absolute_ntoh(dm->expiration), | ||
913 | &msg); | ||
914 | if (GNUNET_OK == ret) | ||
915 | { | ||
916 | GNUNET_STATISTICS_update (stats, | ||
917 | gettext_noop ("# bytes stored"), | ||
918 | size, | ||
919 | GNUNET_YES); | ||
920 | GNUNET_CONTAINER_bloomfilter_add (filter, | ||
921 | &dm->key); | ||
922 | #if DEBUG_DATASTORE | ||
923 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
924 | "Successfully stored %u bytes of type %u under key `%s'\n", | ||
925 | size, | ||
926 | ntohl(dm->type), | ||
927 | GNUNET_h2s (&dm->key)); | ||
928 | #endif | ||
929 | } | ||
930 | transmit_status (client, | ||
931 | (GNUNET_SYSERR == ret) ? GNUNET_SYSERR : GNUNET_OK, | ||
932 | msg); | ||
933 | GNUNET_free_non_null (msg); | ||
934 | if (quota - reserved - cache_size < plugin->api->get_size (plugin->api->cls)) | ||
935 | { | ||
936 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
937 | _("Need %llu bytes more space (%llu allowed, using %llu)\n"), | ||
938 | (unsigned long long) size + GNUNET_DATASTORE_ENTRY_OVERHEAD, | ||
939 | (unsigned long long) (quota - reserved - cache_size), | ||
940 | (unsigned long long) plugin->api->get_size (plugin->api->cls)); | ||
941 | manage_space (size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | ||
942 | } | ||
943 | } | ||
944 | |||
945 | |||
946 | |||
947 | /** | ||
948 | * Function that will check if the given datastore entry | ||
949 | * matches the put and if none match executes the put. | ||
950 | * | ||
951 | * @param cls closure, pointer to the client (of type 'struct PutContext'). | ||
952 | * @param next_cls closure to use to ask for the next item | ||
953 | * @param key key for the content | ||
954 | * @param size number of bytes in data | ||
955 | * @param data content stored | ||
956 | * @param type type of the content | ||
957 | * @param priority priority of the content | ||
958 | * @param anonymity anonymity-level for the content | ||
959 | * @param expiration expiration time for the content | ||
960 | * @param uid unique identifier for the datum; | ||
961 | * maybe 0 if no unique identifier is available | ||
962 | * | ||
963 | * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue, | ||
964 | * GNUNET_NO to delete the item and continue (if supported) | ||
965 | */ | ||
966 | static int | ||
967 | check_present (void *cls, | ||
968 | void *next_cls, | ||
969 | const GNUNET_HashCode * key, | ||
970 | uint32_t size, | ||
971 | const void *data, | ||
972 | enum GNUNET_BLOCK_Type type, | ||
973 | uint32_t priority, | ||
974 | uint32_t anonymity, | ||
975 | struct GNUNET_TIME_Absolute | ||
976 | expiration, uint64_t uid) | ||
977 | { | ||
978 | struct PutContext *pc = cls; | ||
979 | const struct DataMessage *dm; | ||
980 | |||
981 | dm = (const struct DataMessage*) &pc[1]; | ||
982 | if (key == NULL) | ||
983 | { | ||
984 | if (pc->is_present == GNUNET_YES) | ||
985 | transmit_status (pc->client, GNUNET_OK, NULL); | ||
986 | else | ||
987 | execute_put (pc->client, dm); | ||
988 | GNUNET_SERVER_client_drop (pc->client); | ||
989 | GNUNET_free (pc); | ||
990 | return GNUNET_SYSERR; | ||
991 | } | ||
992 | if ( (size == ntohl(dm->size)) && | ||
993 | (0 == memcmp (&dm[1], | ||
994 | data, | ||
995 | size)) ) | ||
996 | { | ||
997 | pc->is_present = GNUNET_YES; | ||
998 | plugin->api->next_request (next_cls, GNUNET_YES); | ||
999 | } | ||
1000 | else | ||
1001 | { | ||
1002 | plugin->api->next_request (next_cls, GNUNET_NO); | ||
1003 | } | ||
1004 | return GNUNET_OK; | ||
1005 | } | ||
1006 | |||
1007 | |||
1008 | /** | ||
873 | * Handle PUT-message. | 1009 | * Handle PUT-message. |
874 | * | 1010 | * |
875 | * @param cls closure | 1011 | * @param cls closure |
@@ -882,10 +1018,9 @@ handle_put (void *cls, | |||
882 | const struct GNUNET_MessageHeader *message) | 1018 | const struct GNUNET_MessageHeader *message) |
883 | { | 1019 | { |
884 | const struct DataMessage *dm = check_data (message); | 1020 | const struct DataMessage *dm = check_data (message); |
885 | char *msg; | ||
886 | int ret; | ||
887 | int rid; | 1021 | int rid; |
888 | struct ReservationList *pos; | 1022 | struct ReservationList *pos; |
1023 | struct PutContext *pc; | ||
889 | uint32_t size; | 1024 | uint32_t size; |
890 | 1025 | ||
891 | if ( (dm == NULL) || | 1026 | if ( (dm == NULL) || |
@@ -924,45 +1059,22 @@ handle_put (void *cls, | |||
924 | GNUNET_NO); | 1059 | GNUNET_NO); |
925 | } | 1060 | } |
926 | } | 1061 | } |
927 | msg = NULL; | 1062 | if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (filter, |
928 | ret = plugin->api->put (plugin->api->cls, | 1063 | &dm->key)) |
929 | &dm->key, | ||
930 | size, | ||
931 | &dm[1], | ||
932 | ntohl(dm->type), | ||
933 | ntohl(dm->priority), | ||
934 | ntohl(dm->anonymity), | ||
935 | GNUNET_TIME_absolute_ntoh(dm->expiration), | ||
936 | &msg); | ||
937 | if (GNUNET_OK == ret) | ||
938 | { | ||
939 | GNUNET_STATISTICS_update (stats, | ||
940 | gettext_noop ("# bytes stored"), | ||
941 | size, | ||
942 | GNUNET_YES); | ||
943 | GNUNET_CONTAINER_bloomfilter_add (filter, | ||
944 | &dm->key); | ||
945 | #if DEBUG_DATASTORE | ||
946 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
947 | "Successfully stored %u bytes of type %u under key `%s'\n", | ||
948 | size, | ||
949 | ntohl(dm->type), | ||
950 | GNUNET_h2s (&dm->key)); | ||
951 | #endif | ||
952 | } | ||
953 | transmit_status (client, | ||
954 | (GNUNET_SYSERR == ret) ? GNUNET_SYSERR : GNUNET_OK, | ||
955 | msg); | ||
956 | GNUNET_free_non_null (msg); | ||
957 | if (quota - reserved - cache_size < plugin->api->get_size (plugin->api->cls)) | ||
958 | { | 1064 | { |
959 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1065 | pc = GNUNET_malloc (sizeof (struct PutContext) + size + sizeof (struct DataMessage)); |
960 | _("Need %llu bytes more space (%llu allowed, using %llu)\n"), | 1066 | pc->client = client; |
961 | (unsigned long long) size + GNUNET_DATASTORE_ENTRY_OVERHEAD, | 1067 | GNUNET_SERVER_client_keep (client); |
962 | (unsigned long long) (quota - reserved - cache_size), | 1068 | memcpy (&pc[1], dm, size + sizeof (struct DataMessage)); |
963 | (unsigned long long) plugin->api->get_size (plugin->api->cls)); | 1069 | plugin->api->get (plugin->api->cls, |
964 | manage_space (size + GNUNET_DATASTORE_ENTRY_OVERHEAD); | 1070 | &dm->key, |
1071 | NULL, | ||
1072 | ntohl (dm->type), | ||
1073 | &check_present, | ||
1074 | pc); | ||
1075 | return; | ||
965 | } | 1076 | } |
1077 | execute_put (client, dm); | ||
966 | } | 1078 | } |
967 | 1079 | ||
968 | 1080 | ||