diff --git a/rhizome.h b/rhizome.h index 6deb5a48..8237ed3e 100644 --- a/rhizome.h +++ b/rhizome.h @@ -361,6 +361,7 @@ int rhizome_ignore_manifest_check(unsigned char *bid_prefix, int prefix_len); #define MAX_CANDIDATES 16 int rhizome_suggest_queue_manifest_import(rhizome_manifest *m, const struct sockaddr_in *peerip,const unsigned char peersid[SID_SIZE]); +rhizome_manifest * rhizome_fetch_search(unsigned char *id, int prefix_length); typedef struct rhizome_http_request { struct sched_ent alarm; diff --git a/rhizome_database.c b/rhizome_database.c index 79bdd06e..75862fae 100644 --- a/rhizome_database.c +++ b/rhizome_database.c @@ -1422,8 +1422,13 @@ int rhizome_is_bar_interesting(unsigned char *bar){ DEBUGF("Ignoring %s", id_hex); return 0; } - - // do we have this bundle [or later]? + + // are we already fetching this bundle [or later]? + rhizome_manifest *m=rhizome_fetch_search(&bar[RHIZOME_BAR_PREFIX_OFFSET], RHIZOME_BAR_PREFIX_BYTES); + if (m && m->version >= version) + return 0; + + // do we have this bundle [or later]? sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT; sqlite3_stmt *statement = sqlite_prepare(&retry, "SELECT id, version FROM manifests WHERE id like ? and version >= ?"); diff --git a/rhizome_fetch.c b/rhizome_fetch.c index c8f0540e..626a04d5 100644 --- a/rhizome_fetch.c +++ b/rhizome_fetch.c @@ -854,6 +854,26 @@ static void rhizome_start_next_queued_fetches(struct sched_ent *alarm) rhizome_start_next_queued_fetch(&rhizome_fetch_queues[i].active); } +/* Search all fetch slots, including active downloads, for a matching manifest */ +rhizome_manifest * rhizome_fetch_search(unsigned char *id, int prefix_length){ + int i, j; + for (i = 0; i < NQUEUES; ++i) { + struct rhizome_fetch_queue *q = &rhizome_fetch_queues[i]; + + if (q->active.state != RHIZOME_FETCH_FREE && + memcmp(id, q->active.manifest->cryptoSignPublic, prefix_length) == 0) + return q->active.manifest; + + for (j = 0; j < q->candidate_queue_size; j++) { + struct rhizome_fetch_candidate *c = &q->candidate_queue[j]; + if (c->manifest && memcmp(id, c->manifest->cryptoSignPublic, prefix_length) == 0) + return c->manifest; + } + } + + return NULL; +} + /* Queue a fetch for the payload of the given manifest. If 'peerip' is not NULL, then it is used as * the port and IP address of an HTTP server from which the fetch is performed. Otherwise the fetch * is performed over MDP.