#include "common.h"
#include <math.h>
#include "dq.h"
#include "mq.h"
#include "gmsg.h"
#include "pmsg.h"
#include "nodes.h"
#include "gnet_stats.h"
#include "qrp.h"
#include "vmsg.h"
#include "search.h"
#include "alive.h"
#include "if/gnet_property_priv.h"
#include "lib/atoms.h"
#include "lib/cq.h"
#include "lib/endian.h"
#include "lib/glib-missing.h"
#include "lib/misc.h"
#include "lib/tm.h"
#include "lib/walloc.h"
#include "lib/override.h"
Data Structures | |
struct | next_up |
Structure produced by dq_fill_next_up, representing the nodes to which we could send the query, along with routing information to be able to favor UPs that report a QRP match early in the querying process. More... | |
struct | dquery |
The dynamic query. More... | |
struct | pmsg_info |
Information about query messages sent. More... | |
struct | cancel_context |
Defines | |
#define | DQ_MAX_LIFETIME 300000 /**< 5 minutes, in ms */ |
5 minutes, in ms | |
#define | DQ_PROBE_TIMEOUT 1500 /**< 1.5 s extra per connection */ |
1.5 s extra per connection | |
#define | DQ_PENDING_TIMEOUT 1200 /**< 1.2 s extra per pending message */ |
1.2 s extra per pending message | |
#define | DQ_QUERY_TIMEOUT 3700 /**< 3.7 s */ |
3.7 s | |
#define | DQ_TIMEOUT_ADJUST 100 /**< 100 ms at each connection */ |
100 ms at each connection | |
#define | DQ_MIN_TIMEOUT 1500 /**< 1.5 s at least between queries */ |
1.5 s at least between queries | |
#define | DQ_LINGER_TIMEOUT 120000 /**< 2 minutes, in ms */ |
2 minutes, in ms | |
#define | DQ_STATUS_TIMEOUT 30000 /**< 30 s, in ms, to reply to query status */ |
30 s, in ms, to reply to query status | |
#define | DQ_MAX_PENDING 3 /**< Max pending queries we allow */ |
Max pending queries we allow. | |
#define | DQ_LEAF_RESULTS 50 /**< # of results targetted for leaves */ |
# of results targetted for leaves | |
#define | DQ_LOCAL_RESULTS 150 /**< # of results for local queries */ |
# of results for local queries | |
#define | DQ_SHA1_DECIMATOR 25 /**< Divide expected by that much for SHA1 */ |
Divide expected by that much for SHA1. | |
#define | DQ_PROBE_UP 3 /**< Amount of UPs for initial probe */ |
Amount of UPs for initial probe. | |
#define | DQ_MAX_HORIZON 500000 /**< Stop after that many UP queried */ |
Stop after that many UP queried. | |
#define | DQ_MIN_HORIZON 3000 /**< Min horizon before timeout adjustment */ |
Min horizon before timeout adjustment. | |
#define | DQ_LOW_RESULTS 10 /**< After DQ_MIN_HORIZON queried for adj. */ |
After DQ_MIN_HORIZON queried for adj. | |
#define | DQ_PERCENT_KEPT 5 /**< Assume 5% of results kept, worst case */ |
Assume 5% of results kept, worst case. | |
#define | DQ_MAX_TTL 5 /**< Max TTL we can use */ |
Max TTL we can use. | |
#define | DQ_AVG_ULTRA_NODES 2 /**< Avg # of ultranodes a leaf queries */ |
Avg # of ultranodes a leaf queries. | |
#define | DQ_MQ_EPSILON 2048 /**< Queues identical at +/- 2K */ |
Queues identical at +/- 2K. | |
#define | DQ_FUZZY_FACTOR 0.80 /**< Corrector for theoretical horizon */ |
Corrector for theoretical horizon. | |
#define | QUERY_TEXT(m) ((m) + sizeof(struct gnutella_header) + 2) |
Compute start of search string (which is NUL terminated) in query. | |
#define | DQ_F_ID_CLEANING 0x00000001 /**< Cleaning the `by_node_id' table */ |
Cleaning the `by_node_id' table. | |
#define | DQ_F_LINGER 0x00000002 /**< Lingering to monitor extra hits */ |
Lingering to monitor extra hits. | |
#define | DQ_F_LEAF_GUIDED 0x00000004 /**< Leaf-guided query */ |
Leaf-guided query. | |
#define | DQ_F_WAITING 0x00000008 /**< Waiting guidance reply from leaf */ |
Waiting guidance reply from leaf. | |
#define | DQ_F_GOT_GUIDANCE 0x00000010 /**< Got unsolicited leaf guidance */ |
Got unsolicited leaf guidance. | |
#define | DQ_F_USR_CANCELLED 0x00000020 /**< Explicitely cancelled by user */ |
Explicitely cancelled by user. | |
#define | DQ_F_EXITING 0x80000000 /**< Final cleanup at exit time */ |
Final cleanup at exit time. | |
#define | MAX_DEGREE 50 |
#define | MAX_TTL 5 |
Typedefs | |
typedef dquery | dquery_t |
The dynamic query. | |
Functions | |
RCSID ("$Id:dq.c, v 1.31 2005/09/28 21:41:37 rmanfredi Exp $") | |
void | dq_send_next (dquery_t *dq) |
Iterate over the UPs which have not seen our query yet, select one and send it the query. | |
void | dq_terminate (dquery_t *dq) |
Terminate active querying. | |
void | fill_hosts (void) |
Compute the hosts[] table so that:. | |
guint32 | dq_get_horizon (gint degree, gint ttl) |
Computes theoretical horizon reached by a query sent to a host advertising a given degree if it is going to travel ttl hops. | |
guint32 | dq_kept_results (dquery_t *dq) |
Compute amount of results "kept" for the query, if we have this information available. | |
gint | dq_select_ttl (dquery_t *dq, gnutella_node_t *node, gint connections) |
Select the proper TTL for the next query we're going to send to the specified node, assuming hosts are equally split among the remaining connections we have yet to query. | |
pmsg_info * | dq_pmi_alloc (dquery_t *dq, guint16 degree, guint8 ttl, guint32 node_id) |
Create a pmsg_info structure, giving meta-information about the message we're about to send. | |
void | dq_pmi_free (struct pmsg_info *pmi) |
Get rid of the pmsg_info structure. | |
gboolean | dq_alive (dquery_t *dq, guint32 qid) |
Check whether query bearing the specified ID is still alive and has not been cancelled yet. | |
void | dq_pmsg_free (pmsg_t *mb, gpointer arg) |
Free routine for an extended message block. | |
pmsg_t * | dq_pmsg_by_ttl (dquery_t *dq, gint ttl) |
Fetch message for a given TTL. | |
gint | dq_fill_probe_up (dquery_t *dq, gnutella_node_t **nv, gint ncount) |
Fill node vector with UP hosts to which we could send our probe query. | |
gint | dq_fill_next_up (dquery_t *dq, struct next_up *nv, gint ncount) |
Fill node vector with UP hosts to which we could send our next query. | |
void | dq_sendto_leaves (dquery_t *dq, gnutella_node_t *source) |
Forward message to all the leaves but the one originating this query, according to their QRP tables. | |
void | dq_free (dquery_t *dq) |
Release the dynamic query object. | |
void | dq_expired (cqueue_t *unused_cq, gpointer obj) |
Callout queue callback invoked when the dynamic query has expired. | |
void | dq_results_expired (cqueue_t *unused_cq, gpointer obj) |
Callout queue callback invoked when the result timer has expired. | |
gint | node_mq_cmp (const void *np1, const void *np2) |
qsort() callback for sorting nodes by increasing queue size. | |
gint | node_mq_qrp_cmp (const void *np1, const void *np2) |
qsort() callback for sorting nodes by increasing queue size, with a preference towards nodes that have a QRP match. | |
void | dq_send_query (dquery_t *dq, gnutella_node_t *n, gint ttl) |
Send individual query to selected node at the supplied TTL. | |
void | dq_send_probe (dquery_t *dq) |
Send probe query (initial querying). | |
void | dq_common_init (dquery_t *dq) |
Common initialization code for a dynamic query. | |
void | dq_launch_net (gnutella_node_t *n, query_hashvec_t *qhv) |
Start new dynamic query out of a message we got from one of our leaves. | |
void | dq_launch_local (gnet_search_t handle, pmsg_t *mb, query_hashvec_t *qhv) |
Start new dynamic query for a local search. | |
void | dq_node_removed (guint32 node_id) |
Tells us a node ID has been removed. | |
gboolean | dq_count_results (gchar *muid, gint count, gboolean oob) |
Common code to count the results. | |
gboolean | dq_got_results (gchar *muid, guint count) |
Called every time we successfully parsed a query hit from the network. | |
gboolean | dq_oob_results_ind (gchar *muid, gint count) |
Called every time we get notified about the presence of some OOB hits. | |
void | dq_oob_results_got (const gchar *muid, guint count) |
Called when OOB results were received, after dq_got_results() was called to record them. | |
void | dq_got_query_status (gchar *muid, guint32 node_id, guint16 kept) |
Called when we get a "Query Status Response" message where the querying node informs us about the amount of results he kept after filtering. | |
void | dq_cancel_local (gpointer key, gpointer unused_value, gpointer udata) |
Cancel local query bearing the specified search handle. | |
void | dq_search_closed (gnet_search_t handle) |
Invoked when a local search is closed. | |
gboolean | dq_get_results_wanted (gchar *muid, guint32 *wanted) |
Called for OOB-proxied queries when we get an "OOB Reply Indication" from remote hosts. | |
void | dq_init (void) |
Initialize dynamic querying. | |
void | free_query (gpointer key, gpointer unused_value, gpointer unused_udata) |
Hashtable iteration callback to free the dquery_t object held as the key. | |
void | free_query_list (gpointer key, gpointer value, gpointer unused_udata) |
Hashtable iteration callback to free the items remaining in the by_node_id table. | |
void | free_muid (gpointer key, gpointer unused_value, gpointer unused_udata) |
Hashtable iteration callback to free the MUIDs in the `by_muid' table. | |
void | dq_close (void) |
Cleanup data structures used by dynamic querying. | |
Variables | |
GHashTable * | dqueries = NULL |
This table keeps track of all the dynamic query objects that we have created and which are alive. | |
GHashTable * | by_node_id = NULL |
This table keeps track of all the dynamic query objects created for a given node ID. | |
GHashTable * | by_muid = NULL |
This table keeps track of the association between a MUID and the dynamic query, so that when results come back, we may account them for the relevant query. | |
guint32 | hosts [MAX_DEGREE][MAX_TTL] |
Pre-computed horizon. | |
guint32 | dyn_query_id = 0 |
|
Avg # of ultranodes a leaf queries.
|
|
Final cleanup at exit time.
|
|
Got unsolicited leaf guidance.
|
|
Cleaning the `by_node_id' table.
|
|
Leaf-guided query.
|
|
Lingering to monitor extra hits.
|
|
Explicitely cancelled by user.
|
|
Waiting guidance reply from leaf.
|
|
Corrector for theoretical horizon.
|
|
# of results targetted for leaves
|
|
2 minutes, in ms
|
|
# of results for local queries
|
|
After DQ_MIN_HORIZON queried for adj.
|
|
Stop after that many UP queried.
|
|
5 minutes, in ms
|
|
Max pending queries we allow.
|
|
Max TTL we can use.
|
|
Min horizon before timeout adjustment.
|
|
1.5 s at least between queries
|
|
Queues identical at +/- 2K.
|
|
1.2 s extra per pending message
|
|
Assume 5% of results kept, worst case.
|
|
1.5 s extra per connection
|
|
Amount of UPs for initial probe.
|
|
3.7 s
|
|
Divide expected by that much for SHA1.
|
|
30 s, in ms, to reply to query status
|
|
100 ms at each connection
|
|
|
|
|
|
Compute start of search string (which is NUL terminated) in query. The "+2" skips the "speed" field in the query. |
|
The dynamic query.
|
|
Check whether query bearing the specified ID is still alive and has not been cancelled yet.
|
|
Cancel local query bearing the specified search handle. -- hash table iterator callback |
|
Cleanup data structures used by dynamic querying.
|
|
Common initialization code for a dynamic query.
|
|
Common code to count the results.
|
|
Callout queue callback invoked when the dynamic query has expired.
|
|
Fill node vector with UP hosts to which we could send our next query.
|
|
Fill node vector with UP hosts to which we could send our probe query.
|
|
Release the dynamic query object.
|
|
Computes theoretical horizon reached by a query sent to a host advertising a given degree if it is going to travel ttl hops. We adjust the horizon by DQ_FUZZY_FACTOR, assuming that at each hop there is deperdition due to flow-control, network cycles, etc... |
|
Called for OOB-proxied queries when we get an "OOB Reply Indication" from remote hosts. The aim is to determine whether the query still needs results, to decide whether we'll claim the advertised results or not.
|
|
Called when we get a "Query Status Response" message where the querying node informs us about the amount of results he kept after filtering.
|
|
Called every time we successfully parsed a query hit from the network. If we have a dynamic query registered for the MUID, increase the result count.
|
|
Initialize dynamic querying.
|
|
Compute amount of results "kept" for the query, if we have this information available.
|
|
Start new dynamic query for a local search. We become the owner of the `mb' and `qhv' pointers. |
|
Start new dynamic query out of a message we got from one of our leaves.
|
|
Tells us a node ID has been removed. Get rid of all the queries registered for that node. |
|
Called when OOB results were received, after dq_got_results() was called to record them. We need to undo the accounting made when dq_oob_results_ind() was called (to register unclaimed hits, which were finally claimed and parsed). |
|
Called every time we get notified about the presence of some OOB hits. The hits have not yet been claimed.
|
|
Create a pmsg_info structure, giving meta-information about the message we're about to send.
|
|
Get rid of the pmsg_info structure.
|
|
Fetch message for a given TTL. If no such message exists yet, create it from the "template" message. |
|
Free routine for an extended message block.
|
|
Callout queue callback invoked when the result timer has expired.
|
|
Invoked when a local search is closed.
|
|
Select the proper TTL for the next query we're going to send to the specified node, assuming hosts are equally split among the remaining connections we have yet to query.
|
|
Iterate over the UPs which have not seen our query yet, select one and send it the query. If no more UP remain, terminate this query. |
|
Send probe query (initial querying). This can generate up to DQ_PROBE_UP individual queries. |
|
Send individual query to selected node at the supplied TTL. If the node advertises a lower maximum TTL, the supplied TTL is adjusted down accordingly. |
|
Forward message to all the leaves but the one originating this query, according to their QRP tables.
|
|
Terminate active querying.
|
|
Compute the hosts[] table so that:. hosts[i][j] = Sum[i^k, 0 <= k <= j] following the formula: hosts(degree,ttl) = Sum[(degree-1)^i, 0 <= i <= ttl-1] |
|
Hashtable iteration callback to free the MUIDs in the `by_muid' table. Normally, after having freed the dqueries table, there should not be anything remaining, hence warn! |
|
Hashtable iteration callback to free the dquery_t object held as the key.
|
|
Hashtable iteration callback to free the items remaining in the by_node_id table. Normally, after having freed the dqueries table, there should not be anything remaining, hence warn! |
|
qsort() callback for sorting nodes by increasing queue size.
|
|
qsort() callback for sorting nodes by increasing queue size, with a preference towards nodes that have a QRP match.
|
|
|
|
This table keeps track of the association between a MUID and the dynamic query, so that when results come back, we may account them for the relevant query. The keys are MUIDs (GUID atoms), the values are the dquery_t object. |
|
This table keeps track of all the dynamic query objects created for a given node ID. The key is the node ID (converted to a pointer) and the value is a GSList containing all the queries for that node. |
|
This table keeps track of all the dynamic query objects that we have created and which are alive.
|
|
|
|
Pre-computed horizon.
|