diff options
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/fs/Makefile.am | 1 | ||||
-rw-r--r-- | src/fs/gnunet-service-fs.c | 108 | ||||
-rw-r--r-- | src/include/Makefile.am | 1 | ||||
-rw-r--r-- | src/include/gnunet_peer_lib.h | 91 | ||||
-rw-r--r-- | src/peer/Makefile.am | 29 | ||||
-rw-r--r-- | src/peer/peer.c | 212 |
8 files changed, 441 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac index 28094e057d..20bff6c6af 100644 --- a/configure.ac +++ b/configure.ac @@ -753,6 +753,7 @@ src/hello/Makefile src/include/Makefile src/include/gnunet_directories.h src/hostlist/Makefile +src/peer/Makefile src/peerinfo/Makefile src/resolver/Makefile src/statistics/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 7e92437c6a..a394944d2c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,7 @@ SUBDIRS = \ arm \ fragmentation \ hello \ + peer \ peerinfo \ resolver \ statistics \ diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am index e2f2e62678..a91459e643 100644 --- a/src/fs/Makefile.am +++ b/src/fs/Makefile.am @@ -88,6 +88,7 @@ gnunet_service_fs_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/core/libgnunetcore.la \ + $(top_builddir)/src/peer/libgnunetpeer.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c index 1f248c0592..5237cee042 100644 --- a/src/fs/gnunet-service-fs.c +++ b/src/fs/gnunet-service-fs.c @@ -42,6 +42,7 @@ #include "platform.h" #include "gnunet_core_service.h" #include "gnunet_datastore_service.h" +#include "gnunet_peer_lib.h" #include "gnunet_protocols.h" #include "gnunet_signatures.h" #include "gnunet_util_lib.h" @@ -341,12 +342,112 @@ struct ProcessGetContext /** - * Information we keep for each pending - * request. + * Information we keep for each pending request. We should try to + * keep this struct as small as possible since its memory consumption + * is key to how many requests we can have pending at once. */ struct PendingRequest { - // FIXME + + /** + * ID of a client making a request, NULL if this entry is for a + * peer. + */ + struct GNUNET_SERVER_Client *client; + + /** + * If this is a namespace query, pointer to the hash of the public + * key of the namespace; otherwise NULL. + */ + GNUNET_HashCode *namespace; + + /** + * Bloomfilter we use to filter out replies that we don't care about + * (anymore). NULL as long as we are interested in all replies. + */ + struct GNUNET_CONTAINER_BloomFilter *bf; + + /** + * Hash code of all replies that we have seen so far (only valid + * if client is not NULL since we only track replies like this for + * our own clients). + */ + GNUNET_HashCode *replies_seen; + + /** + * When did we first see this request (form this peer), or, if our + * client is initiating, when did we last initiate a search? + */ + struct GNUNET_TIME_Absolute start_time; + + /** + * The query that this request is for. + */ + GNUNET_HashCode query; + + /** + * (Interned) Peer identifier (only valid if "client" is NULL) + * that identifies a peer that gave us this request. + */ + GNUNET_PEER_Id source_pid; + + /** + * (Interned) Peer identifier that identifies a preferred target + * for requests. + */ + GNUNET_PEER_Id target_pid; + + /** + * (Interned) Peer identifiers of peers that have already + * received our query for this content. + */ + GNUNET_PEER_Id *used_pids; + + /** + * How many entries in "used_pids" are actually valid? + */ + unsigned int used_pids_off; + + /** + * How long is the "used_pids" array? + */ + unsigned int used_pids_size; + + /** + * How many entries in "replies_seen" are actually valid? + */ + unsigned int replies_seen_off; + + /** + * How long is the "replies_seen" array? + */ + unsigned int replies_seen_size; + + /** + * Priority with which this request was made. If one of our clients + * made the request, then this is the current priority that we are + * using when initiating the request. This value is used when + * we decide to reward other peers with trust for providing a reply. + */ + uint32_t priority; + + /** + * Priority points left for us to spend when forwarding this request + * to other peers. + */ + uint32_t remaining_priority; + + /** + * TTL with which we saw this request (or, if we initiated, TTL that + * we used for the request). + */ + int32_t ttl; + + /** + * Type of the content that this request is for. + */ + uint32_t type; + }; @@ -1080,6 +1181,7 @@ handle_on_demand_block (const GNUNET_HashCode * key, off = GNUNET_ntohll (odb->offset); fn = (const char*) GNUNET_CONTAINER_multihashmap_get (ifm, &odb->file_id); + fh = NULL; if ( (NULL == fn) || (NULL == (fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READ))) || diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 008d6a180e..39fb2f0f5d 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -30,6 +30,7 @@ gnunetinclude_HEADERS = \ gnunet_getopt_lib.h \ gnunet_hello_lib.h \ gnunet_network_lib.h \ + gnunet_peer_lib.h \ gnunet_peerinfo_service.h \ gnunet_program_lib.h \ gnunet_protocols.h \ diff --git a/src/include/gnunet_peer_lib.h b/src/include/gnunet_peer_lib.h new file mode 100644 index 0000000000..036eea1dc6 --- /dev/null +++ b/src/include/gnunet_peer_lib.h @@ -0,0 +1,91 @@ +/* + This file is part of GNUnet. + (C) 2006, 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file include/gnunet_peer_lib.h + * @brief helper library for interning of peer identifiers + * @author Christian Grothoff + */ + +#ifndef GNUNET_PEER_LIB_H +#define GNUNET_PEER_LIB_H + +#include "gnunet_util_lib.h" + +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + +/** + * A GNUNET_PEER_Id is simply a shorter + * version of a "struct GNUNET_PeerIdentifier" + * that can be used inside of a GNUnet peer + * to save memory when the same identifier + * needs to be used over and over again. + */ +typedef unsigned int GNUNET_PEER_Id; + + +/** + * Intern an peer identity. If the identity is already known, its + * reference counter will be increased by one. + * + * @param pid identity to intern + * @return the interned identity. + */ +GNUNET_PEER_Id GNUNET_PEER_intern (const struct GNUNET_PeerIdentity * pid); + + +/** + * Change the reference counter of an interned PID. + * + * @param id identity to change the RC of + * @param delta how much to change the RC + */ +void GNUNET_PEER_change_rc (GNUNET_PEER_Id id, int delta); + + +/** + * Decrement multiple RCs of peer identities by one. + * + * @param ids array of PIDs to decrement the RCs of + * @param count size of the ids array + */ +void GNUNET_PEER_decrement_rcs (const GNUNET_PEER_Id * ids, + unsigned int count); + + +/** + * Convert an interned PID to a normal peer identity. + * + * @param id interned PID to convert + * @param pid where to write the normal peer identity + */ +void GNUNET_PEER_resolve (GNUNET_PEER_Id id, + struct GNUNET_PeerIdentity * pid); + + +/* ifndef GNUNET_PEER_LIB_H */ +#endif +/* end of gnunet_peer_lib.h */ diff --git a/src/peer/Makefile.am b/src/peer/Makefile.am new file mode 100644 index 0000000000..bd268cf39d --- /dev/null +++ b/src/peer/Makefile.am @@ -0,0 +1,29 @@ +INCLUDES = -I$(top_srcdir)/src/include + +if MINGW + WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols +endif + +if USE_COVERAGE + AM_CFLAGS = --coverage -O0 + XLIB = -lgcov +endif + +lib_LTLIBRARIES = libgnunetpeer.la + +libgnunetpeer_la_SOURCES = \ + peer.c +libgnunetpeer_la_LIBADD = \ + $(top_builddir)/src/util/libgnunetutil.la $(XLIB) + +#check_PROGRAMS = \ +# test_peer +# +#TESTS = $(check_PROGRAMS) +# +#test_peer_SOURCES = \ +# test_peer.c +#test_peer_LDADD = \ +# $(top_builddir)/src/peer/libgnunetpeer.la \ +# $(top_builddir)/src/util/libgnunetutil.la + diff --git a/src/peer/peer.c b/src/peer/peer.c new file mode 100644 index 0000000000..02c95f4db9 --- /dev/null +++ b/src/peer/peer.c @@ -0,0 +1,212 @@ +/* + This file is part of GNUnet + (C) 2006, 2008, 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +/** + * @file peer/peer.c + * @brief peer-ID table that assigns integer IDs to peer-IDs to save memory + * @author Christian Grothoff + */ + +#include "platform.h" +#include "gnunet_peer_lib.h" + + +struct PeerEntry +{ + /** + * the identifier itself + */ + struct GNUNET_PeerIdentity id; + + /** + * Short version of the identifier; + * if the RC==0, then index of next + * free slot in table, otherwise + * equal to this slot in the table. + */ + GNUNET_PEER_Id pid; + + /** + * Reference counter, 0 if this slot + * is not used. + */ + unsigned int rc; +}; + + +/** + * Table with our interned peer IDs. + */ +static struct PeerEntry *table; + +/** + * Hashmap of PeerIdentities to "struct PeerEntry" + * (for fast lookup). NULL until the library + * is actually being used. + */ +static struct GNUNET_CONTAINER_MultiHashMap *map; + +/** + * Size of the "table". + */ +static unsigned int size; + +/** + * Index of the beginning of the free list in the table; set to "size" + * if no slots are free in the table. + */ +static unsigned int free_list_start; + + +/** + * Intern an peer identity. If the identity is already known, its + * reference counter will be increased by one. + * + * @param pid identity to intern + * @return the interned identity. + */ +GNUNET_PEER_Id +GNUNET_PEER_intern (const struct GNUNET_PeerIdentity * pid) +{ + GNUNET_PEER_Id ret; + struct PeerEntry *e; + unsigned int i; + + if (pid == NULL) + return 0; + if (NULL == map) + map = GNUNET_CONTAINER_multihashmap_create (32); + e = GNUNET_CONTAINER_multihashmap_get (map, + &pid->hashPubKey); + if (e != NULL) + { + GNUNET_assert (e->rc > 0); + e->rc++; + return e->pid; + } + ret = free_list_start; + if (ret == size) + { + GNUNET_array_grow (table, size, size + 16); + for (i=ret;i<size;i++) + table[i].pid = i + 1; + } + if (ret == 0) + { + table[0].pid = 0; + table[0].rc = 1; + ret = 1; + } + GNUNET_assert (ret < size); + GNUNET_assert (table[ret].rc == 0); + free_list_start = table[ret].pid; + table[ret].id = *pid; + table[ret].rc = 1; + table[ret].pid = ret; + GNUNET_CONTAINER_multihashmap_put (map, + &pid->hashPubKey, + &table[ret], + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + return ret; +} + + +/** + * Decrement multiple RCs of peer identities by one. + * + * @param ids array of PIDs to decrement the RCs of + * @param count size of the ids array + */ +void +GNUNET_PEER_decrement_rcs (const GNUNET_PEER_Id * ids, + unsigned int count) +{ + int i; + GNUNET_PEER_Id id; + + if (count == 0) + return; + for (i = count - 1; i >= 0; i--) + { + id = ids[i]; + GNUNET_assert (id < size); + GNUNET_assert (table[id].rc > 0); + table[id].rc--; + if (table[id].rc == 0) + { + GNUNET_CONTAINER_multihashmap_remove (map, + &table[id].id.hashPubKey, + &table[id]); + table[id].pid = free_list_start; + free_list_start = id; + } + } +} + + +/** + * Change the reference counter of an interned PID. + * + * @param id identity to change the RC of + * @param delta how much to change the RC + */ +void +GNUNET_PEER_change_rc (GNUNET_PEER_Id id, int delta) +{ + if (id == 0) + return; + GNUNET_assert (id < size); + GNUNET_assert (table[id].rc > 0); + GNUNET_assert ((delta >= 0) || (table[id].rc >= -delta)); + table[id].rc += delta; + if (table[id].rc == 0) + { + GNUNET_CONTAINER_multihashmap_remove (map, + &table[id].id.hashPubKey, + &table[id]); + table[id].pid = free_list_start; + free_list_start = id; + } +} + + +/** + * Convert an interned PID to a normal peer identity. + * + * @param id interned PID to convert + * @param pid where to write the normal peer identity + */ +void +GNUNET_PEER_resolve (GNUNET_PEER_Id id, + struct GNUNET_PeerIdentity * pid) +{ + if (id == 0) + { + memset (pid, 0, sizeof (struct GNUNET_PeerIdentity)); + GNUNET_break (0); + return; + } + GNUNET_assert (id < size); + GNUNET_assert (table[id].rc > 0); + *pid = table[id].id; +} + + +/* end of peer.c */ |