aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO3
-rw-r--r--src/datastore/gnunet-service-datastore.c190
2 files changed, 151 insertions, 42 deletions
diff --git a/TODO b/TODO
index acac5e4f3..6c0de7df2 100644
--- a/TODO
+++ b/TODO
@@ -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 */
876struct 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 */
895static void
896execute_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 */
966static int
967check_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