aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/fs/fs_api.c32
-rw-r--r--src/fs/fs_api.h57
-rw-r--r--src/fs/fs_download.c10
-rw-r--r--src/fs/fs_search.c99
-rw-r--r--src/include/gnunet_fs_service.h6
5 files changed, 137 insertions, 67 deletions
diff --git a/src/fs/fs_api.c b/src/fs/fs_api.c
index 29fc0cdd7..302020d7d 100644
--- a/src/fs/fs_api.c
+++ b/src/fs/fs_api.c
@@ -65,9 +65,13 @@ start_job (struct GNUNET_FS_QueueEntry *qe)
65 "Starting job %p (%u active)\n", 65 "Starting job %p (%u active)\n",
66 qe, 66 qe,
67 qe->h->active_downloads); 67 qe->h->active_downloads);
68 GNUNET_CONTAINER_DLL_remove (qe->h->pending_head, qe->h->pending_tail, qe); 68 GNUNET_CONTAINER_DLL_remove (qe->h->pending_head,
69 GNUNET_CONTAINER_DLL_insert_after (qe->h->running_head, qe->h->running_tail, 69 qe->h->pending_tail,
70 qe->h->running_tail, qe); 70 qe);
71 GNUNET_CONTAINER_DLL_insert_after (qe->h->running_head,
72 qe->h->running_tail,
73 qe->h->running_tail,
74 qe);
71} 75}
72 76
73 77
@@ -207,19 +211,25 @@ process_job_queue (void *cls,
207 num_downloads_expired, 211 num_downloads_expired,
208 num_downloads_waiting); 212 num_downloads_waiting);
209 /* calculate start/stop decisions */ 213 /* calculate start/stop decisions */
210 if (h->active_downloads + num_downloads_waiting > h->max_parallel_requests) 214 if (h->active_downloads + num_downloads_waiting > h->max_parallel_downloads)
211 { 215 {
212 /* stop probes if possible */ 216 /* stop as many probes as there are downloads and probes */
213 num_probes_change = - num_probes_active; 217 num_probes_change = - GNUNET_MIN (num_probes_active,
214 num_downloads_change = h->max_parallel_requests - h->active_downloads; 218 num_downloads_waiting);
219 /* start as many downloads as there are free slots, including those
220 we just opened up */
221 num_downloads_change = h->max_parallel_downloads - h->active_downloads - num_probes_change;
215 } 222 }
216 else 223 else
217 { 224 {
218 /* start all downloads */ 225 /* start all downloads (we can) */
219 num_downloads_change = num_downloads_waiting; 226 num_downloads_change = num_downloads_waiting;
220 /* start as many probes as we can */ 227 /* also start probes if there is room, but use a lower cap of (mpd/4) + 1 */
221 num_probes_change = GNUNET_MIN (num_probes_waiting, 228 if (h->max_parallel_downloads / 2 >= (h->active_downloads + num_downloads_change))
222 h->max_parallel_requests - (h->active_downloads + num_downloads_waiting)); 229 num_probes_change = GNUNET_MIN (num_probes_waiting,
230 (1 + h->max_parallel_downloads / 4) - (h->active_downloads + num_downloads_change));
231 else
232 num_probes_change = 0;
223 } 233 }
224 234
225 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 235 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
diff --git a/src/fs/fs_api.h b/src/fs/fs_api.h
index d43da2028..46f398e86 100644
--- a/src/fs/fs_api.h
+++ b/src/fs/fs_api.h
@@ -531,6 +531,16 @@ struct GNUNET_FS_SearchResult
531 struct GNUNET_FS_Handle *h; 531 struct GNUNET_FS_Handle *h;
532 532
533 /** 533 /**
534 * Kept in a DLL while probing.
535 */
536 struct GNUNET_FS_SearchResult *next;
537
538 /**
539 * Kept in a DLL while probing.
540 */
541 struct GNUNET_FS_SearchResult *prev;
542
543 /**
534 * Search context this result belongs to; can be NULL 544 * Search context this result belongs to; can be NULL
535 * for probes that come from a directory result. 545 * for probes that come from a directory result.
536 */ 546 */
@@ -592,12 +602,6 @@ struct GNUNET_FS_SearchResult
592 GNUNET_SCHEDULER_TaskIdentifier probe_cancel_task; 602 GNUNET_SCHEDULER_TaskIdentifier probe_cancel_task;
593 603
594 /** 604 /**
595 * Task we use to report periodically to the application that the
596 * probe is still running.
597 */
598 GNUNET_SCHEDULER_TaskIdentifier probe_ping_task;
599
600 /**
601 * When did the current probe become active? 605 * When did the current probe become active?
602 */ 606 */
603 struct GNUNET_TIME_Absolute probe_active_time; 607 struct GNUNET_TIME_Absolute probe_active_time;
@@ -651,8 +655,11 @@ struct GNUNET_FS_SearchResult
651 * @return queue handle 655 * @return queue handle
652 */ 656 */
653struct GNUNET_FS_QueueEntry * 657struct GNUNET_FS_QueueEntry *
654GNUNET_FS_queue_ (struct GNUNET_FS_Handle *h, GNUNET_FS_QueueStart start, 658GNUNET_FS_queue_ (struct GNUNET_FS_Handle *h,
655 GNUNET_FS_QueueStop stop, void *cls, unsigned int blocks, 659 GNUNET_FS_QueueStart start,
660 GNUNET_FS_QueueStop stop,
661 void *cls,
662 unsigned int blocks,
656 enum GNUNET_FS_QueuePriority priority); 663 enum GNUNET_FS_QueuePriority priority);
657 664
658 665
@@ -903,7 +910,8 @@ GNUNET_FS_remove_sync_file_ (struct GNUNET_FS_Handle *h, const char *ext,
903 * @param uni unique name of parent 910 * @param uni unique name of parent
904 */ 911 */
905void 912void
906GNUNET_FS_remove_sync_dir_ (struct GNUNET_FS_Handle *h, const char *ext, 913GNUNET_FS_remove_sync_dir_ (struct GNUNET_FS_Handle *h,
914 const char *ext,
907 const char *uni); 915 const char *uni);
908 916
909 917
@@ -1003,7 +1011,7 @@ GNUNET_FS_search_signal_suspend_ (void *cls);
1003 * Create SUSPEND event for the given download operation 1011 * Create SUSPEND event for the given download operation
1004 * and then clean up our state (without stop signal). 1012 * and then clean up our state (without stop signal).
1005 * 1013 *
1006 * @param cls the 'struct GNUNET_FS_DownloadContext' to signal for 1014 * @param cls the `struct GNUNET_FS_DownloadContext` to signal for
1007 */ 1015 */
1008void 1016void
1009GNUNET_FS_download_signal_suspend_ (void *cls); 1017GNUNET_FS_download_signal_suspend_ (void *cls);
@@ -1138,12 +1146,28 @@ struct GNUNET_FS_Handle
1138 struct GNUNET_FS_QueueEntry *pending_tail; 1146 struct GNUNET_FS_QueueEntry *pending_tail;
1139 1147
1140 /** 1148 /**
1149 * Head of active probes.
1150 */
1151 struct GNUNET_FS_SearchResult *probes_head;
1152
1153 /**
1154 * Tail of active probes.
1155 */
1156 struct GNUNET_FS_SearchResult *probes_tail;
1157
1158 /**
1141 * Task that processes the jobs in the running and pending queues 1159 * Task that processes the jobs in the running and pending queues
1142 * (and moves jobs around as needed). 1160 * (and moves jobs around as needed).
1143 */ 1161 */
1144 GNUNET_SCHEDULER_TaskIdentifier queue_job; 1162 GNUNET_SCHEDULER_TaskIdentifier queue_job;
1145 1163
1146 /** 1164 /**
1165 * Task we use to report periodically to the application that
1166 * certain search probes (from @e probes_head) are still running.
1167 */
1168 GNUNET_SCHEDULER_TaskIdentifier probe_ping_task;
1169
1170 /**
1147 * Average time we take for a single request to be satisfied. 1171 * Average time we take for a single request to be satisfied.
1148 * FIXME: not yet calcualted properly... 1172 * FIXME: not yet calcualted properly...
1149 */ 1173 */
@@ -1563,7 +1587,7 @@ struct GNUNET_FS_SearchContext
1563 char *emsg; 1587 char *emsg;
1564 1588
1565 /** 1589 /**
1566 * Map that contains a "struct GNUNET_FS_SearchResult" for each result that 1590 * Map that contains a `struct GNUNET_FS_SearchResult` for each result that
1567 * was found in the search. The key for each entry is the XOR of 1591 * was found in the search. The key for each entry is the XOR of
1568 * the key and query in the CHK URI (as a unique identifier for the 1592 * the key and query in the CHK URI (as a unique identifier for the
1569 * search result). 1593 * search result).
@@ -1769,6 +1793,15 @@ GNUNET_FS_free_download_request_ (struct DownloadRequest *dr);
1769 1793
1770 1794
1771/** 1795/**
1796 * Stop the ping task for this search result.
1797 *
1798 * @param sr result to start pinging for.
1799 */
1800void
1801GNUNET_FS_stop_probe_ping_task_ (struct GNUNET_FS_SearchResult *sr);
1802
1803
1804/**
1772 * Context for controlling a download. 1805 * Context for controlling a download.
1773 */ 1806 */
1774struct GNUNET_FS_DownloadContext 1807struct GNUNET_FS_DownloadContext
@@ -1912,7 +1945,7 @@ struct GNUNET_FS_DownloadContext
1912 /** 1945 /**
1913 * ID of a task that is using this struct and that must be cancelled 1946 * ID of a task that is using this struct and that must be cancelled
1914 * when the download is being stopped (if not 1947 * when the download is being stopped (if not
1915 * GNUNET_SCHEDULER_NO_TASK). Used for the task that adds some 1948 * #GNUNET_SCHEDULER_NO_TASK). Used for the task that adds some
1916 * artificial delay when trying to reconnect to the FS service or 1949 * artificial delay when trying to reconnect to the FS service or
1917 * the task processing incrementally the data on disk, or the 1950 * the task processing incrementally the data on disk, or the
1918 * task requesting blocks, etc. 1951 * task requesting blocks, etc.
diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c
index b3726e9bb..348a0bc17 100644
--- a/src/fs/fs_download.c
+++ b/src/fs/fs_download.c
@@ -2257,11 +2257,7 @@ GNUNET_FS_download_start_from_search (struct GNUNET_FS_Handle *h,
2257 { 2257 {
2258 GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); 2258 GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES);
2259 sr->probe_ctx = NULL; 2259 sr->probe_ctx = NULL;
2260 } 2260 GNUNET_FS_stop_probe_ping_task_ (sr);
2261 if (GNUNET_SCHEDULER_NO_TASK != sr->probe_ping_task)
2262 {
2263 GNUNET_SCHEDULER_cancel (sr->probe_ping_task);
2264 sr->probe_ping_task = GNUNET_SCHEDULER_NO_TASK;
2265 } 2261 }
2266 return dc; 2262 return dc;
2267} 2263}
@@ -2314,14 +2310,14 @@ GNUNET_FS_download_resume (struct GNUNET_FS_DownloadContext *dc)
2314 2310
2315 pi.status = GNUNET_FS_STATUS_DOWNLOAD_ACTIVE; 2311 pi.status = GNUNET_FS_STATUS_DOWNLOAD_ACTIVE;
2316 GNUNET_FS_download_make_status_ (&pi, dc); 2312 GNUNET_FS_download_make_status_ (&pi, dc);
2317 2313
2318 dc->job_queue = 2314 dc->job_queue =
2319 GNUNET_FS_queue_ (dc->h, &activate_fs_download, &deactivate_fs_download, 2315 GNUNET_FS_queue_ (dc->h, &activate_fs_download, &deactivate_fs_download,
2320 dc, (dc->length + DBLOCK_SIZE - 1) / DBLOCK_SIZE, 2316 dc, (dc->length + DBLOCK_SIZE - 1) / DBLOCK_SIZE,
2321 (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE)) 2317 (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE))
2322 ? GNUNET_FS_QUEUE_PRIORITY_NORMAL 2318 ? GNUNET_FS_QUEUE_PRIORITY_NORMAL
2323 : GNUNET_FS_QUEUE_PRIORITY_PROBE); 2319 : GNUNET_FS_QUEUE_PRIORITY_PROBE);
2324 2320
2325} 2321}
2326 2322
2327 2323
diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c
index a9c9389c4..c85d6d3df 100644
--- a/src/fs/fs_search.c
+++ b/src/fs/fs_search.c
@@ -171,7 +171,9 @@ struct GetResultContext
171 * @return #GNUNET_OK 171 * @return #GNUNET_OK
172 */ 172 */
173static int 173static int
174get_result_present (void *cls, const struct GNUNET_HashCode * key, void *value) 174get_result_present (void *cls,
175 const struct GNUNET_HashCode *key,
176 void *value)
175{ 177{
176 struct GetResultContext *grc = cls; 178 struct GetResultContext *grc = cls;
177 struct GNUNET_FS_SearchResult *sr = value; 179 struct GNUNET_FS_SearchResult *sr = value;
@@ -216,7 +218,8 @@ signal_probe_result (struct GNUNET_FS_SearchResult *sr)
216 * @param tc scheduler context 218 * @param tc scheduler context
217 */ 219 */
218static void 220static void
219probe_failure_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 221probe_failure_handler (void *cls,
222 const struct GNUNET_SCHEDULER_TaskContext *tc)
220{ 223{
221 struct GNUNET_FS_SearchResult *sr = cls; 224 struct GNUNET_FS_SearchResult *sr = cls;
222 225
@@ -224,11 +227,7 @@ probe_failure_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
224 sr->availability_trials++; 227 sr->availability_trials++;
225 GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); 228 GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES);
226 sr->probe_ctx = NULL; 229 sr->probe_ctx = NULL;
227 if (GNUNET_SCHEDULER_NO_TASK != sr->probe_ping_task) 230 GNUNET_FS_stop_probe_ping_task_ (sr);
228 {
229 GNUNET_SCHEDULER_cancel (sr->probe_ping_task);
230 sr->probe_ping_task = GNUNET_SCHEDULER_NO_TASK;
231 }
232 GNUNET_FS_search_result_sync_ (sr); 231 GNUNET_FS_search_result_sync_ (sr);
233 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
234 "Probe #%u for search result %p failed\n", 233 "Probe #%u for search result %p failed\n",
@@ -245,7 +244,8 @@ probe_failure_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
245 * @param tc scheduler context 244 * @param tc scheduler context
246 */ 245 */
247static void 246static void
248probe_success_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 247probe_success_handler (void *cls,
248 const struct GNUNET_SCHEDULER_TaskContext *tc)
249{ 249{
250 struct GNUNET_FS_SearchResult *sr = cls; 250 struct GNUNET_FS_SearchResult *sr = cls;
251 251
@@ -254,11 +254,7 @@ probe_success_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
254 sr->availability_success++; 254 sr->availability_success++;
255 GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); 255 GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES);
256 sr->probe_ctx = NULL; 256 sr->probe_ctx = NULL;
257 if (GNUNET_SCHEDULER_NO_TASK != sr->probe_ping_task) 257 GNUNET_FS_stop_probe_ping_task_ (sr);
258 {
259 GNUNET_SCHEDULER_cancel (sr->probe_ping_task);
260 sr->probe_ping_task = GNUNET_SCHEDULER_NO_TASK;
261 }
262 GNUNET_FS_search_result_sync_ (sr); 258 GNUNET_FS_search_result_sync_ (sr);
263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 259 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
264 "Probe #%u for search result %p succeeded\n", 260 "Probe #%u for search result %p succeeded\n",
@@ -367,20 +363,64 @@ GNUNET_FS_search_probe_progress_ (void *cls,
367/** 363/**
368 * Task run periodically to remind clients that a probe is active. 364 * Task run periodically to remind clients that a probe is active.
369 * 365 *
370 * @param cls the 'struct GNUNET_FS_SearchResult' that we are probing for 366 * @param cls the `struct GNUNET_FS_SearchResult` that we are probing for
371 * @param tc scheduler context 367 * @param tc scheduler context
372 */ 368 */
373static void 369static void
374probe_ping_task (void *cls, 370probe_ping_task_cb (void *cls,
375 const struct GNUNET_SCHEDULER_TaskContext *tc) 371 const struct GNUNET_SCHEDULER_TaskContext *tc)
376{ 372{
377 struct GNUNET_FS_SearchResult *sr = cls; 373 struct GNUNET_FS_Handle *h = cls;
374 struct GNUNET_FS_SearchResult *sr;
378 375
379 signal_probe_result (sr); 376 for (sr = h->probes_head; NULL != sr; sr = sr->next)
380 sr->probe_ping_task 377 if (NULL != sr->probe_ctx->client)
378 signal_probe_result (sr);
379 h->probe_ping_task
381 = GNUNET_SCHEDULER_add_delayed (GNUNET_FS_PROBE_UPDATE_FREQUENCY, 380 = GNUNET_SCHEDULER_add_delayed (GNUNET_FS_PROBE_UPDATE_FREQUENCY,
382 &probe_ping_task, 381 &probe_ping_task_cb,
383 sr); 382 h);
383}
384
385
386/**
387 * Start the ping task for this search result.
388 *
389 * @param sr result to start pinging for.
390 */
391static void
392start_probe_ping_task (struct GNUNET_FS_SearchResult *sr)
393{
394 struct GNUNET_FS_Handle *h = sr->h;
395
396 GNUNET_CONTAINER_DLL_insert (h->probes_head,
397 h->probes_tail,
398 sr);
399 if (GNUNET_SCHEDULER_NO_TASK == h->probe_ping_task)
400 h->probe_ping_task
401 = GNUNET_SCHEDULER_add_now (&probe_ping_task_cb,
402 h);
403}
404
405
406/**
407 * Stop the ping task for this search result.
408 *
409 * @param sr result to start pinging for.
410 */
411void
412GNUNET_FS_stop_probe_ping_task_ (struct GNUNET_FS_SearchResult *sr)
413{
414 struct GNUNET_FS_Handle *h = sr->h;
415
416 GNUNET_CONTAINER_DLL_remove (h->probes_head,
417 h->probes_tail,
418 sr);
419 if (NULL == h->probes_head)
420 {
421 GNUNET_SCHEDULER_cancel (h->probe_ping_task);
422 h->probe_ping_task = GNUNET_SCHEDULER_NO_TASK;
423 }
384} 424}
385 425
386 426
@@ -431,9 +471,7 @@ GNUNET_FS_search_start_probe_ (struct GNUNET_FS_SearchResult *sr)
431 len, sr->anonymity, 471 len, sr->anonymity,
432 GNUNET_FS_DOWNLOAD_NO_TEMPORARIES | 472 GNUNET_FS_DOWNLOAD_NO_TEMPORARIES |
433 GNUNET_FS_DOWNLOAD_IS_PROBE, sr, NULL); 473 GNUNET_FS_DOWNLOAD_IS_PROBE, sr, NULL);
434 sr->probe_ping_task 474 start_probe_ping_task (sr);
435 = GNUNET_SCHEDULER_add_now (&probe_ping_task,
436 sr);
437} 475}
438 476
439 477
@@ -480,11 +518,7 @@ GNUNET_FS_search_stop_probe_ (struct GNUNET_FS_SearchResult *sr)
480 { 518 {
481 GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); 519 GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES);
482 sr->probe_ctx = NULL; 520 sr->probe_ctx = NULL;
483 } 521 GNUNET_FS_stop_probe_ping_task_ (sr);
484 if (GNUNET_SCHEDULER_NO_TASK != sr->probe_ping_task)
485 {
486 GNUNET_SCHEDULER_cancel (sr->probe_ping_task);
487 sr->probe_ping_task = GNUNET_SCHEDULER_NO_TASK;
488 } 522 }
489 if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) 523 if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task)
490 { 524 {
@@ -1410,11 +1444,7 @@ search_result_freeze_probes (void *cls,
1410 { 1444 {
1411 GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); 1445 GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES);
1412 sr->probe_ctx = NULL; 1446 sr->probe_ctx = NULL;
1413 } 1447 GNUNET_FS_stop_probe_ping_task_ (sr);
1414 if (GNUNET_SCHEDULER_NO_TASK != sr->probe_ping_task)
1415 {
1416 GNUNET_SCHEDULER_cancel (sr->probe_ping_task);
1417 sr->probe_ping_task = GNUNET_SCHEDULER_NO_TASK;
1418 } 1448 }
1419 if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) 1449 if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task)
1420 { 1450 {
@@ -1692,7 +1722,6 @@ search_result_free (void *cls,
1692 } 1722 }
1693 GNUNET_break (NULL == sr->probe_ctx); 1723 GNUNET_break (NULL == sr->probe_ctx);
1694 GNUNET_break (GNUNET_SCHEDULER_NO_TASK == sr->probe_cancel_task); 1724 GNUNET_break (GNUNET_SCHEDULER_NO_TASK == sr->probe_cancel_task);
1695 GNUNET_break (GNUNET_SCHEDULER_NO_TASK == sr->probe_ping_task);
1696 GNUNET_break (NULL == sr->client_info); 1725 GNUNET_break (NULL == sr->client_info);
1697 GNUNET_free_non_null (sr->serialization); 1726 GNUNET_free_non_null (sr->serialization);
1698 GNUNET_FS_uri_destroy (sr->uri); 1727 GNUNET_FS_uri_destroy (sr->uri);
diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h
index aa2f2076c..9f3ff0d12 100644
--- a/src/include/gnunet_fs_service.h
+++ b/src/include/gnunet_fs_service.h
@@ -88,8 +88,10 @@ struct GNUNET_FS_Uri;
88 * @param is_mandatory is the keyword mandatory (in a search) 88 * @param is_mandatory is the keyword mandatory (in a search)
89 * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to abort 89 * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to abort
90 */ 90 */
91typedef int (*GNUNET_FS_KeywordIterator) (void *cls, const char *keyword, 91typedef int
92 int is_mandatory); 92(*GNUNET_FS_KeywordIterator) (void *cls,
93 const char *keyword,
94 int is_mandatory);
93 95
94 96
95 97