diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-12-07 16:05:22 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-12-07 16:05:22 +0000 |
commit | f6afaac108cefb138fa9b38db7fdc68382a55731 (patch) | |
tree | 3ada7c0237a179644e64a3313b1f8a64ea56cbe2 /src | |
parent | 0d45e157a134a01ec59e8fc564918a1caa5070c4 (diff) | |
download | gnunet-f6afaac108cefb138fa9b38db7fdc68382a55731.tar.gz gnunet-f6afaac108cefb138fa9b38db7fdc68382a55731.zip |
-more work on FS profiler
Diffstat (limited to 'src')
-rw-r--r-- | src/fs/gnunet-daemon-fsprofiler.c | 304 |
1 files changed, 301 insertions, 3 deletions
diff --git a/src/fs/gnunet-daemon-fsprofiler.c b/src/fs/gnunet-daemon-fsprofiler.c index fa9bfd3b2..e83b3e6f2 100644 --- a/src/fs/gnunet-daemon-fsprofiler.c +++ b/src/fs/gnunet-daemon-fsprofiler.c | |||
@@ -28,6 +28,59 @@ | |||
28 | #include "gnunet_statistics_service.h" | 28 | #include "gnunet_statistics_service.h" |
29 | 29 | ||
30 | /** | 30 | /** |
31 | * We use 'patterns' of the form (x,y,t) to specify desired download/publish | ||
32 | * activities of a peer. They are stored in a DLL. | ||
33 | */ | ||
34 | struct Pattern | ||
35 | { | ||
36 | /** | ||
37 | * Kept in a DLL. | ||
38 | */ | ||
39 | struct Pattern *next; | ||
40 | |||
41 | /** | ||
42 | * Kept in a DLL. | ||
43 | */ | ||
44 | struct Pattern *prev; | ||
45 | |||
46 | /** | ||
47 | * Execution context for the pattern (FS-handle to the operation). | ||
48 | */ | ||
49 | void *ctx; | ||
50 | |||
51 | /** | ||
52 | * Secondary execution context for the pattern (FS-handle to the operation). | ||
53 | */ | ||
54 | void *sctx; | ||
55 | |||
56 | /** | ||
57 | * When did the operation start? | ||
58 | */ | ||
59 | struct GNUNET_TIME_Absolute start_time; | ||
60 | |||
61 | /** | ||
62 | * With how much delay should this operation be started? | ||
63 | */ | ||
64 | struct GNUNET_TIME_Relative delay; | ||
65 | |||
66 | /** | ||
67 | * Task to run the operation. | ||
68 | */ | ||
69 | GNUNET_SCHEDULER_TaskIdentifier task; | ||
70 | |||
71 | /** | ||
72 | * X-value. | ||
73 | */ | ||
74 | unsigned long long x; | ||
75 | |||
76 | /** | ||
77 | * Y-value. | ||
78 | */ | ||
79 | unsigned long long y; | ||
80 | }; | ||
81 | |||
82 | |||
83 | /** | ||
31 | * Return value from 'main'. | 84 | * Return value from 'main'. |
32 | */ | 85 | */ |
33 | static int global_ret; | 86 | static int global_ret; |
@@ -52,8 +105,140 @@ static struct GNUNET_FS_Handle *fs_handle; | |||
52 | */ | 105 | */ |
53 | static unsigned long long my_peerid; | 106 | static unsigned long long my_peerid; |
54 | 107 | ||
108 | /** | ||
109 | * Desired anonymity level. | ||
110 | */ | ||
111 | static unsigned long long anonymity_level; | ||
112 | |||
113 | /** | ||
114 | * Desired replication level. | ||
115 | */ | ||
116 | static unsigned long long replication_level; | ||
117 | |||
118 | /** | ||
119 | * String describing which publishing operations this peer should | ||
120 | * perform. The format is "(SIZE,SEED,TIME)*", for example: | ||
121 | * "(1,5,0)(7,3,13)" means to publish a file with 1 byte and | ||
122 | * seed/keyword 5 immediately and another file with 7 bytes and | ||
123 | * seed/keyword 3 after 13 ms. | ||
124 | */ | ||
125 | static char *publish_pattern; | ||
126 | |||
127 | /** | ||
128 | * Head of the DLL of publish patterns. | ||
129 | */ | ||
130 | static struct Pattern *publish_head; | ||
131 | |||
132 | /** | ||
133 | * Tail of the DLL of publish patterns. | ||
134 | */ | ||
135 | static struct Pattern *publish_tail; | ||
136 | |||
137 | /** | ||
138 | * String describing which download operations this peer should | ||
139 | * perform. The format is "(KEYWORD,SIZE,DELAY)*"; for example, | ||
140 | * "(1,7,3)(3,8,8)" means to download one file of 7 bytes under | ||
141 | * keyword "1" starting the search after 3 ms; and another one of 8 | ||
142 | * bytes under keyword '3' starting after 8 ms. The file size is | ||
143 | * used to determine which search result(s) should be used or ignored. | ||
144 | */ | ||
145 | static char *download_pattern; | ||
55 | 146 | ||
147 | /** | ||
148 | * Head of the DLL of publish patterns. | ||
149 | */ | ||
150 | static struct Pattern *download_head; | ||
56 | 151 | ||
152 | /** | ||
153 | * Tail of the DLL of publish patterns. | ||
154 | */ | ||
155 | static struct Pattern *download_tail; | ||
156 | |||
157 | |||
158 | /** | ||
159 | * Parse a pattern string and store the corresponding | ||
160 | * 'struct Pattern' in the given head/tail. | ||
161 | * | ||
162 | * @param head where to store the head | ||
163 | * @param tail where to store the tail | ||
164 | * @param pattern pattern to parse | ||
165 | * @return GNUNET_OK on success | ||
166 | */ | ||
167 | static int | ||
168 | parse_pattern (struct Pattern **head, | ||
169 | struct Pattern **tail, | ||
170 | const char *pattern) | ||
171 | { | ||
172 | struct Pattern *p; | ||
173 | unsigned long long x; | ||
174 | unsigned long long y; | ||
175 | unsigned long long t; | ||
176 | |||
177 | while (3 == sscanf (pattern, | ||
178 | "(%llu,%llu,%llu)", | ||
179 | &x, &y, &t)) | ||
180 | { | ||
181 | p = GNUNET_malloc (sizeof (struct Pattern)); | ||
182 | p->x = x; | ||
183 | p->y = y; | ||
184 | p->delay.rel_value = (uint64_t) t; | ||
185 | GNUNET_CONTAINER_DLL_insert (*head, *tail, p); | ||
186 | pattern = strstr (pattern, ")"); | ||
187 | GNUNET_assert (NULL != pattern); | ||
188 | pattern++; | ||
189 | } | ||
190 | return (0 == strlen (pattern)) ? GNUNET_OK : GNUNET_SYSERR; | ||
191 | } | ||
192 | |||
193 | |||
194 | /** | ||
195 | * Create a file of the given length with a deterministic amount | ||
196 | * of data to be published under keyword 'kval'. | ||
197 | * | ||
198 | * @param length number of bytes in the file | ||
199 | * @param kval keyword value and seed for the data of the file | ||
200 | * @param ctx context to pass to 'fi' | ||
201 | * @return file information handle for the file | ||
202 | */ | ||
203 | static struct GNUNET_FS_FileInformation * | ||
204 | make_file (uint64_t length, | ||
205 | uint64_t kval, | ||
206 | void *ctx) | ||
207 | { | ||
208 | struct GNUNET_FS_FileInformation *fi; | ||
209 | struct GNUNET_FS_BlockOptions bo; | ||
210 | char *data; | ||
211 | struct GNUNET_FS_Uri *keywords; | ||
212 | char kw[128]; | ||
213 | unsigned long long i; | ||
214 | uint64_t xor; | ||
215 | |||
216 | data = NULL; /* to make compilers happy */ | ||
217 | if ( (0 != length) && | ||
218 | (NULL == (data = GNUNET_malloc_large ((size_t) length))) ) | ||
219 | return NULL; | ||
220 | /* initialize data with 'unique' data only depending on 'kval' and 'size', | ||
221 | making sure that blocks do not repeat */ | ||
222 | for (i=0;i<length; i+=8) | ||
223 | { | ||
224 | xor = length ^ kval ^ (uint64_t) (i / 32 / 1024); | ||
225 | memcpy (&data[i], &xor, GNUNET_MIN (length - i, sizeof (uint64_t))); | ||
226 | } | ||
227 | bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS); | ||
228 | bo.anonymity_level = (uint32_t) anonymity_level; | ||
229 | bo.content_priority = 128; | ||
230 | bo.replication_level = (uint32_t) replication_level; | ||
231 | GNUNET_snprintf (kw, sizeof (kw), | ||
232 | "%llu", (unsigned long long) kval); | ||
233 | keywords = GNUNET_FS_uri_ksk_create (kw, NULL); | ||
234 | fi = GNUNET_FS_file_information_create_from_data (fs_handle, | ||
235 | ctx, | ||
236 | length, | ||
237 | data, keywords, | ||
238 | NULL, GNUNET_NO, &bo); | ||
239 | GNUNET_FS_uri_destroy (keywords); | ||
240 | return fi; | ||
241 | } | ||
57 | 242 | ||
58 | 243 | ||
59 | /** | 244 | /** |
@@ -65,12 +250,33 @@ static unsigned long long my_peerid; | |||
65 | static void | 250 | static void |
66 | shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 251 | shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
67 | { | 252 | { |
253 | struct Pattern *p; | ||
254 | |||
255 | while (NULL != (p = publish_head)) | ||
256 | { | ||
257 | if (GNUNET_SCHEDULER_NO_TASK != p->task) | ||
258 | GNUNET_SCHEDULER_cancel (p->task); | ||
259 | if (NULL != p->ctx) | ||
260 | GNUNET_FS_publish_stop (p->ctx); | ||
261 | GNUNET_CONTAINER_DLL_remove (publish_head, publish_tail, p); | ||
262 | GNUNET_free (p); | ||
263 | } | ||
264 | while (NULL != (p = download_head)) | ||
265 | { | ||
266 | if (GNUNET_SCHEDULER_NO_TASK != p->task) | ||
267 | GNUNET_SCHEDULER_cancel (p->task); | ||
268 | if (NULL != p->ctx) | ||
269 | GNUNET_FS_download_stop (p->ctx, GNUNET_YES); | ||
270 | if (NULL != p->sctx) | ||
271 | GNUNET_FS_search_stop (p->sctx); | ||
272 | GNUNET_CONTAINER_DLL_remove (download_head, download_tail, p); | ||
273 | GNUNET_free (p); | ||
274 | } | ||
68 | if (NULL != fs_handle) | 275 | if (NULL != fs_handle) |
69 | { | 276 | { |
70 | GNUNET_FS_stop (fs_handle); | 277 | GNUNET_FS_stop (fs_handle); |
71 | fs_handle = NULL; | 278 | fs_handle = NULL; |
72 | } | 279 | } |
73 | |||
74 | if (NULL != stats_handle) | 280 | if (NULL != stats_handle) |
75 | { | 281 | { |
76 | GNUNET_STATISTICS_destroy (stats_handle, GNUNET_YES); | 282 | GNUNET_STATISTICS_destroy (stats_handle, GNUNET_YES); |
@@ -98,11 +304,60 @@ static void * | |||
98 | progress_cb (void *cls, | 304 | progress_cb (void *cls, |
99 | const struct GNUNET_FS_ProgressInfo *info) | 305 | const struct GNUNET_FS_ProgressInfo *info) |
100 | { | 306 | { |
307 | // FIXME: | ||
308 | // - search result => start download | ||
309 | // - publishing done => staitstic, terminate 'struct Pattern' | ||
310 | // - download done => statistic, terminate 'struct Pattern' | ||
311 | // => all patterns done => then what!? (how do we tell the | ||
312 | // drive that we are done!?) | ||
101 | return NULL; | 313 | return NULL; |
102 | } | 314 | } |
103 | 315 | ||
104 | 316 | ||
105 | /** | 317 | /** |
318 | * Start publish operation. | ||
319 | * | ||
320 | * @param cls the 'struct Pattern' specifying the operation to perform | ||
321 | * @param tc scheduler context | ||
322 | */ | ||
323 | static void | ||
324 | start_publish (void *cls, | ||
325 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
326 | { | ||
327 | struct Pattern *p = cls; | ||
328 | struct GNUNET_FS_FileInformation *fi; | ||
329 | |||
330 | p->task = GNUNET_SCHEDULER_NO_TASK; | ||
331 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
332 | return; | ||
333 | fi = make_file (p->x, p->y, p); | ||
334 | p->ctx = GNUNET_FS_publish_start (fs_handle, | ||
335 | fi, | ||
336 | NULL, NULL, NULL, | ||
337 | GNUNET_FS_PUBLISH_OPTION_NONE); | ||
338 | } | ||
339 | |||
340 | |||
341 | /** | ||
342 | * Start download operation. | ||
343 | * | ||
344 | * @param cls the 'struct Pattern' specifying the operation to perform | ||
345 | * @param tc scheduler context | ||
346 | */ | ||
347 | static void | ||
348 | start_download (void *cls, | ||
349 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
350 | { | ||
351 | struct Pattern *p = cls; | ||
352 | |||
353 | p->task = GNUNET_SCHEDULER_NO_TASK; | ||
354 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
355 | return; | ||
356 | // FIXME: start search operation | ||
357 | } | ||
358 | |||
359 | |||
360 | /** | ||
106 | * @brief Main function that will be run by the scheduler. | 361 | * @brief Main function that will be run by the scheduler. |
107 | * | 362 | * |
108 | * @param cls closure | 363 | * @param cls closure |
@@ -115,6 +370,9 @@ run (void *cls, char *const *args GNUNET_UNUSED, | |||
115 | const char *cfgfile GNUNET_UNUSED, | 370 | const char *cfgfile GNUNET_UNUSED, |
116 | const struct GNUNET_CONFIGURATION_Handle *cfg_) | 371 | const struct GNUNET_CONFIGURATION_Handle *cfg_) |
117 | { | 372 | { |
373 | char myoptname[128]; | ||
374 | struct Pattern *p; | ||
375 | |||
118 | cfg = cfg_; | 376 | cfg = cfg_; |
119 | /* Scheduled the task to clean up when shutdown is called */ | 377 | /* Scheduled the task to clean up when shutdown is called */ |
120 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, | 378 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, |
@@ -131,6 +389,42 @@ run (void *cls, char *const *args GNUNET_UNUSED, | |||
131 | GNUNET_SCHEDULER_shutdown (); | 389 | GNUNET_SCHEDULER_shutdown (); |
132 | return; | 390 | return; |
133 | } | 391 | } |
392 | if (GNUNET_OK != | ||
393 | GNUNET_CONFIGURATION_get_value_number (cfg, | ||
394 | "FSPROFILER", "ANONYMITY_LEVEL", | ||
395 | &anonymity_level)) | ||
396 | anonymity_level = 1; | ||
397 | if (GNUNET_OK != | ||
398 | GNUNET_CONFIGURATION_get_value_number (cfg, | ||
399 | "FSPROFILER", "REPLICATION_LEVEL", | ||
400 | &replication_level)) | ||
401 | replication_level = 1; | ||
402 | GNUNET_snprintf (myoptname, sizeof (myoptname), | ||
403 | "DOWNLOAD-PATTERN-%u", my_peerid); | ||
404 | if (GNUNET_OK != | ||
405 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
406 | "FSPROFILER", myoptname, | ||
407 | &download_pattern)) | ||
408 | download_pattern = GNUNET_strdup (""); | ||
409 | GNUNET_snprintf (myoptname, sizeof (myoptname), | ||
410 | "PUBLISH-PATTERN-%u", my_peerid); | ||
411 | if (GNUNET_OK != | ||
412 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
413 | "FSPROFILER", myoptname, | ||
414 | &publish_pattern)) | ||
415 | publish_pattern = GNUNET_strdup (""); | ||
416 | if ( (GNUNET_OK != | ||
417 | parse_pattern (&download_head, | ||
418 | &download_tail, | ||
419 | download_pattern)) || | ||
420 | (GNUNET_OK != | ||
421 | parse_pattern (&publish_head, | ||
422 | &publish_tail, | ||
423 | publish_pattern)) ) | ||
424 | { | ||
425 | GNUNET_SCHEDULER_shutdown (); | ||
426 | return; | ||
427 | } | ||
134 | 428 | ||
135 | stats_handle = GNUNET_STATISTICS_create ("fsprofiler", cfg); | 429 | stats_handle = GNUNET_STATISTICS_create ("fsprofiler", cfg); |
136 | fs_handle = | 430 | fs_handle = |
@@ -141,7 +435,6 @@ run (void *cls, char *const *args GNUNET_UNUSED, | |||
141 | GNUNET_FS_OPTIONS_DOWNLOAD_PARALLELISM, 1, | 435 | GNUNET_FS_OPTIONS_DOWNLOAD_PARALLELISM, 1, |
142 | GNUNET_FS_OPTIONS_REQUEST_PARALLELISM, 1, | 436 | GNUNET_FS_OPTIONS_REQUEST_PARALLELISM, 1, |
143 | GNUNET_FS_OPTIONS_END); | 437 | GNUNET_FS_OPTIONS_END); |
144 | |||
145 | if (NULL == fs_handle) | 438 | if (NULL == fs_handle) |
146 | { | 439 | { |
147 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not acquire FS handle. Exiting.\n"); | 440 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not acquire FS handle. Exiting.\n"); |
@@ -149,7 +442,12 @@ run (void *cls, char *const *args GNUNET_UNUSED, | |||
149 | GNUNET_SCHEDULER_shutdown (); | 442 | GNUNET_SCHEDULER_shutdown (); |
150 | return; | 443 | return; |
151 | } | 444 | } |
152 | 445 | for (p = publish_head; NULL != p; p = p->next) | |
446 | p->task = GNUNET_SCHEDULER_add_delayed (p->delay, | ||
447 | &start_publish, p); | ||
448 | for (p = download_head; NULL != p; p = p->next) | ||
449 | p->task = GNUNET_SCHEDULER_add_delayed (p->delay, | ||
450 | &start_download, p); | ||
153 | } | 451 | } |
154 | 452 | ||
155 | 453 | ||