aboutsummaryrefslogtreecommitdiff
path: root/src/fs
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-29 21:20:17 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-29 21:20:17 +0000
commitee4d754ebbcc11369dd7e78b50db733e3b921fc2 (patch)
tree547c981117541be04bae9cd18b9bdceeb51be5d9 /src/fs
parent6f912718b1e65181e9e3a62c6c7b8cf32f7d1165 (diff)
downloadgnunet-ee4d754ebbcc11369dd7e78b50db733e3b921fc2.tar.gz
gnunet-ee4d754ebbcc11369dd7e78b50db733e3b921fc2.zip
-towards external meta scanner process
Diffstat (limited to 'src/fs')
-rw-r--r--src/fs/fs_dirmetascan.c265
-rw-r--r--src/fs/gnunet-helper-fs-publish.c14
-rw-r--r--src/fs/gnunet-publish.c85
3 files changed, 292 insertions, 72 deletions
diff --git a/src/fs/fs_dirmetascan.c b/src/fs/fs_dirmetascan.c
index 6d97f1553..69c7770db 100644
--- a/src/fs/fs_dirmetascan.c
+++ b/src/fs/fs_dirmetascan.c
@@ -68,11 +68,20 @@ struct GNUNET_FS_DirScanner
68 /** 68 /**
69 * After the scan is finished, it will contain a pointer to the 69 * After the scan is finished, it will contain a pointer to the
70 * top-level directory entry in the directory tree built by the 70 * top-level directory entry in the directory tree built by the
71 * scanner. Must only be manipulated by the thread for the 71 * scanner.
72 * duration of the thread's runtime.
73 */ 72 */
74 struct GNUNET_FS_ShareTreeItem *toplevel; 73 struct GNUNET_FS_ShareTreeItem *toplevel;
75 74
75 /**
76 * Current position during processing.
77 */
78 struct GNUNET_FS_ShareTreeItem *pos;
79
80 /**
81 * Arguments for helper.
82 */
83 char *args[4];
84
76}; 85};
77 86
78 87
@@ -121,6 +130,76 @@ GNUNET_FS_directory_scan_get_result (struct GNUNET_FS_DirScanner *ds)
121 130
122 131
123/** 132/**
133 * Move in the directory from the given position to the next file
134 * in DFS traversal.
135 *
136 * @param pos current position
137 * @return next file, NULL for none
138 */
139static struct GNUNET_FS_ShareTreeItem *
140advance (struct GNUNET_FS_ShareTreeItem *pos)
141{
142 int moved;
143
144 GNUNET_assert (NULL != pos);
145 moved = 0; /* must not terminate, even on file, otherwise "normal" */
146 while ( (pos->is_directory) ||
147 (0 == moved) )
148 {
149 if ( (moved != -1) &&
150 (NULL != pos->children_head) )
151 {
152 pos = pos->children_head;
153 moved = 1; /* can terminate if file */
154 continue;
155 }
156 if (NULL != pos->next)
157 {
158 pos = pos->next;
159 moved = 1; /* can terminate if file */
160 continue;
161 }
162 if (NULL != pos->parent)
163 {
164 pos = pos->parent;
165 moved = -1; /* force move to 'next' or 'parent' */
166 continue;
167 }
168 /* no more options, end of traversal */
169 return NULL;
170 }
171 return pos;
172}
173
174
175/**
176 * Add another child node to the tree.
177 *
178 * @param parent parent of the child, NULL for top level
179 * @param filename name of the file or directory
180 * @param is_directory GNUNET_YES for directories
181 * @return new entry that was just created
182 */
183static struct GNUNET_FS_ShareTreeItem *
184expand_tree (struct GNUNET_FS_ShareTreeItem *parent,
185 const char *filename,
186 int is_directory)
187{
188 struct GNUNET_FS_ShareTreeItem *chld;
189
190 chld = GNUNET_malloc (sizeof (struct GNUNET_FS_ShareTreeItem));
191 chld->parent = parent;
192 chld->filename = GNUNET_strdup (filename);
193 chld->is_directory = is_directory;
194 if (NULL != parent)
195 GNUNET_CONTAINER_DLL_insert (parent->children_head,
196 parent->children_tail,
197 chld);
198 return chld;
199}
200
201
202/**
124 * Called every time there is data to read from the scanner. 203 * Called every time there is data to read from the scanner.
125 * Calls the scanner progress handler. 204 * Calls the scanner progress handler.
126 * 205 *
@@ -134,35 +213,145 @@ process_helper_msgs (void *cls,
134 const struct GNUNET_MessageHeader *msg) 213 const struct GNUNET_MessageHeader *msg)
135{ 214{
136 struct GNUNET_FS_DirScanner *ds = cls; 215 struct GNUNET_FS_DirScanner *ds = cls;
137 ds++; 216 const char *filename;
138#if 0 217 size_t left;
139 enum GNUNET_FS_DirScannerProgressUpdateReason reason; 218
140 size_t filename_len; 219 left = ntohs (msg->size) - sizeof (struct GNUNET_MessageHeader);
141 int is_directory; 220 filename = (const char*) &msg[1];
142 char *filename; 221 switch (ntohs (msg->type))
143 222 {
144 /* Process message. If message is malformed or can't be read, end the scanner */ 223 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_FILE:
145 /* read successfully, notify client about progress */ 224 if (filename[left-1] != '\0')
225 {
226 GNUNET_break (0);
227 break;
228 }
229 ds->progress_callback (ds->progress_callback_cls,
230 filename, GNUNET_NO,
231 GNUNET_FS_DIRSCANNER_FILE_START);
232 expand_tree (ds->pos,
233 filename, GNUNET_NO);
234 return;
235 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY:
236 if (filename[left-1] != '\0')
237 {
238 GNUNET_break (0);
239 break;
240 }
241 if (0 == strcmp ("..", filename))
242 {
243 if (NULL == ds->pos)
244 {
245 GNUNET_break (0);
246 break;
247 }
248 ds->pos = ds->pos->parent;
249 return;
250 }
251 ds->progress_callback (ds->progress_callback_cls,
252 filename, GNUNET_YES,
253 GNUNET_FS_DIRSCANNER_FILE_START);
254 ds->pos = expand_tree (ds->pos,
255 filename, GNUNET_YES);
256 if (NULL == ds->toplevel)
257 ds->toplevel = ds->pos;
258 return;
259 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR:
260 break;
261 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_SKIP_FILE:
262 if (filename[left-1] != '\0')
263 break;
264 ds->progress_callback (ds->progress_callback_cls,
265 filename, GNUNET_SYSERR,
266 GNUNET_FS_DIRSCANNER_FILE_IGNORED);
267 return;
268 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE:
269 if (0 != left)
270 {
271 GNUNET_break (0);
272 break;
273 }
274 ds->progress_callback (ds->progress_callback_cls,
275 NULL, GNUNET_SYSERR,
276 GNUNET_FS_DIRSCANNER_ALL_COUNTED);
277 ds->pos = ds->toplevel;
278 if (ds->pos->is_directory)
279 ds->pos = advance (ds->pos);
280 return;
281 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA:
282 {
283 size_t nlen;
284 const char *end;
285
286 if (NULL == ds->pos)
287 {
288 GNUNET_break (0);
289 break;
290 }
291 end = memchr (filename, 0, left);
292 if (NULL == end)
293 {
294 GNUNET_break (0);
295 break;
296 }
297 end++;
298 nlen = end - filename;
299 left -= nlen;
300 if (0 != strcmp (filename,
301 ds->pos->filename))
302 {
303 GNUNET_break (0);
304 break;
305 }
306 ds->progress_callback (ds->progress_callback_cls,
307 filename, GNUNET_YES,
308 GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED);
309 if (0 < left)
310 {
311 ds->pos->meta = GNUNET_CONTAINER_meta_data_deserialize (end, left);
312 if (NULL == ds->pos->meta)
313 {
314 GNUNET_break (0);
315 break;
316 }
317 /* having full filenames is too dangerous; always make sure we clean them up */
318 ds->pos->short_filename = GNUNET_strdup (GNUNET_STRINGS_get_short_name (filename));
319 GNUNET_CONTAINER_meta_data_delete (ds->pos->meta,
320 EXTRACTOR_METATYPE_FILENAME,
321 NULL, 0);
322 GNUNET_CONTAINER_meta_data_insert (ds->pos->meta, "<libgnunetfs>",
323 EXTRACTOR_METATYPE_FILENAME,
324 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
325 ds->pos->short_filename,
326 strlen (ds->pos->short_filename) + 1);
327 }
328 ds->pos = advance (ds->pos);
329 return;
330 }
331 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED:
332 if (NULL != ds->pos)
333 {
334 GNUNET_break (0);
335 break;
336 }
337 if (0 != left)
338 {
339 GNUNET_break (0);
340 break;
341 }
342 ds->progress_callback (ds->progress_callback_cls,
343 NULL, GNUNET_SYSERR,
344 GNUNET_FS_DIRSCANNER_INTERNAL_ERROR);
345
346 return;
347 default:
348 GNUNET_break (0);
349 break;
350 }
146 ds->progress_callback (ds->progress_callback_cls, 351 ds->progress_callback (ds->progress_callback_cls,
147 ds, 352 NULL, GNUNET_SYSERR,
148 filename, 353 GNUNET_FS_DIRSCANNER_INTERNAL_ERROR);
149 is_directory, 354
150 reason);
151 GNUNET_free (filename);
152
153
154 /* having full filenames is too dangerous; always make sure we clean them up */
155 item->short_filename = GNUNET_strdup (GNUNET_STRINGS_get_short_name (filename));
156
157 GNUNET_CONTAINER_meta_data_delete (item->meta,
158 EXTRACTOR_METATYPE_FILENAME,
159 NULL, 0);
160 GNUNET_CONTAINER_meta_data_insert (item->meta, "<libgnunetfs>",
161 EXTRACTOR_METATYPE_FILENAME,
162 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
163 item->short_filename,
164 strlen (item->short_filename) + 1);
165#endif
166} 355}
167 356
168 357
@@ -185,7 +374,6 @@ GNUNET_FS_directory_scan_start (const char *filename,
185 struct stat sbuf; 374 struct stat sbuf;
186 char *filename_expanded; 375 char *filename_expanded;
187 struct GNUNET_FS_DirScanner *ds; 376 struct GNUNET_FS_DirScanner *ds;
188 char *args[4];
189 377
190 if (0 != STAT (filename, &sbuf)) 378 if (0 != STAT (filename, &sbuf))
191 return NULL; 379 return NULL;
@@ -199,13 +387,16 @@ GNUNET_FS_directory_scan_start (const char *filename,
199 ds->progress_callback = cb; 387 ds->progress_callback = cb;
200 ds->progress_callback_cls = cb_cls; 388 ds->progress_callback_cls = cb_cls;
201 ds->filename_expanded = filename_expanded; 389 ds->filename_expanded = filename_expanded;
202 ds->ex_arg = GNUNET_strdup ((disable_extractor) ? "-" : ex); 390 if (disable_extractor)
203 args[0] = "gnunet-helper-fs-publish"; 391 ds->ex_arg = GNUNET_strdup ("-");
204 args[1] = ds->filename_expanded; 392 else
205 args[2] = ds->ex_arg; 393 ds->ex_arg = (NULL != ex) ? GNUNET_strdup (ex) : NULL;
206 args[3] = NULL; 394 ds->args[0] = "gnunet-helper-fs-publish";
395 ds->args[1] = ds->filename_expanded;
396 ds->args[2] = ds->ex_arg;
397 ds->args[3] = NULL;
207 ds->helper = GNUNET_HELPER_start ("gnunet-helper-fs-publish", 398 ds->helper = GNUNET_HELPER_start ("gnunet-helper-fs-publish",
208 args, 399 ds->args,
209 &process_helper_msgs, 400 &process_helper_msgs,
210 ds); 401 ds);
211 if (NULL == ds->helper) 402 if (NULL == ds->helper)
diff --git a/src/fs/gnunet-helper-fs-publish.c b/src/fs/gnunet-helper-fs-publish.c
index 21ec19fe9..7accf79ac 100644
--- a/src/fs/gnunet-helper-fs-publish.c
+++ b/src/fs/gnunet-helper-fs-publish.c
@@ -223,9 +223,10 @@ scan_callback (void *cls,
223 return GNUNET_SYSERR; 223 return GNUNET_SYSERR;
224 } 224 }
225 chld->parent = rc->parent; 225 chld->parent = rc->parent;
226 GNUNET_CONTAINER_DLL_insert (rc->parent->children_head, 226 if (NULL != rc->parent)
227 rc->parent->children_tail, 227 GNUNET_CONTAINER_DLL_insert (rc->parent->children_head,
228 chld); 228 rc->parent->children_tail,
229 chld);
229 return GNUNET_OK; 230 return GNUNET_OK;
230} 231}
231 232
@@ -282,6 +283,10 @@ preprocess_file (const char *filename,
282 free_tree (item); 283 free_tree (item);
283 return GNUNET_SYSERR; 284 return GNUNET_SYSERR;
284 } 285 }
286 if (GNUNET_OK !=
287 write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY,
288 "..", 3))
289 return GNUNET_SYSERR;
285 } 290 }
286 *dst = item; 291 *dst = item;
287 return GNUNET_OK; 292 return GNUNET_OK;
@@ -379,7 +384,8 @@ int main(int argc,
379 } 384 }
380 filename_expanded = argv[1]; 385 filename_expanded = argv[1];
381 ex = argv[2]; 386 ex = argv[2];
382 if (0 != strcmp (ex, "-")) 387 if ( (ex == NULL) ||
388 (0 != strcmp (ex, "-")) )
383 { 389 {
384 plugins = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY); 390 plugins = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY);
385 if (NULL != ex) 391 if (NULL != ex)
diff --git a/src/fs/gnunet-publish.c b/src/fs/gnunet-publish.c
index 05bd66e31..9cc55a290 100644
--- a/src/fs/gnunet-publish.c
+++ b/src/fs/gnunet-publish.c
@@ -425,50 +425,67 @@ directory_trim_complete ()
425} 425}
426 426
427 427
428/**
429 * Function called by the directory scanner as we build the tree
430 * that we will need to publish later.
431 *
432 * @param cls closure
433 * @param filename which file we are making progress on
434 * @param is_directory GNUNET_YES if this is a directory,
435 * GNUNET_NO if this is a file
436 * GNUNET_SYSERR if it is neither (or unknown)
437 * @param reason kind of progress we are making
438 */
428static void 439static void
429directory_scan_cb (void *cls, struct GNUNET_FS_DirScanner *ds, 440directory_scan_cb (void *cls,
430 const char *filename, 441 const char *filename,
431 int is_directory, 442 int is_directory,
432 enum GNUNET_FS_DirScannerProgressUpdateReason reason) 443 enum GNUNET_FS_DirScannerProgressUpdateReason reason)
433{ 444{
434 switch (reason) 445 switch (reason)
435 { 446 {
436 case GNUNET_FS_DIRSCANNER_FILE_START: 447 case GNUNET_FS_DIRSCANNER_FILE_START:
448 if (verbose > 1)
449 {
437 if (is_directory) 450 if (is_directory)
438 FPRINTF (stdout, _("Scanning directory `%s'.\n"), filename); 451 FPRINTF (stdout, _("Scanning directory `%s'.\n"), filename);
439 else 452 else
440 FPRINTF (stdout, _("Scanning file `%s'.\n"), filename); 453 FPRINTF (stdout, _("Scanning file `%s'.\n"), filename);
441 break; 454 }
442 case GNUNET_FS_DIRSCANNER_ALL_COUNTED: 455 break;
456 case GNUNET_FS_DIRSCANNER_FILE_IGNORED:
457 FPRINTF (stderr,
458 _("There was trouble processing file `%s', skipping it.\n"),
459 filename);
460 break;
461 case GNUNET_FS_DIRSCANNER_ALL_COUNTED:
462 if (verbose)
443 FPRINTF (stdout, "%s", _("Preprocessing complete.\n")); 463 FPRINTF (stdout, "%s", _("Preprocessing complete.\n"));
444 break; 464 break;
445 case GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED: 465 case GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED:
466 if (verbose > 2)
446 FPRINTF (stdout, _("Extracting meta data from file `%s' complete.\n"), filename); 467 FPRINTF (stdout, _("Extracting meta data from file `%s' complete.\n"), filename);
447 break; 468 break;
448 case GNUNET_FS_DIRSCANNER_DOES_NOT_EXIST: 469 case GNUNET_FS_DIRSCANNER_FINISHED:
449 FPRINTF (stdout, 470 if (verbose > 1)
450 _("There was trouble processing file `%s', skipping it.\n"), 471 FPRINTF (stdout, "%s", _("Meta data extraction has finished.\n"));
451 filename); 472 directory_scan_result = GNUNET_FS_directory_scan_get_result (ds);
452 break; 473 ds = NULL;
453 case GNUNET_FS_DIRSCANNER_FINISHED: 474 GNUNET_FS_share_tree_trim (directory_scan_result);
454 FPRINTF (stdout, "%s", _("Scanner has finished.\n")); 475 directory_trim_complete ();
455 directory_scan_result = GNUNET_FS_directory_scan_get_result (ds); 476 break;
456 ds = NULL; 477 case GNUNET_FS_DIRSCANNER_INTERNAL_ERROR:
457 GNUNET_FS_share_tree_trim (directory_scan_result); 478 FPRINTF (stdout, "%s", _("Internal error scanning directory.\n"));
458 directory_trim_complete (); 479 GNUNET_FS_directory_scan_abort (ds);
459 break; 480 ds = NULL;
460 case GNUNET_FS_DIRSCANNER_INTERNAL_ERROR: 481 if (namespace != NULL)
461 FPRINTF (stdout, "%s", _("Internal error scanning directory.\n")); 482 GNUNET_FS_namespace_delete (namespace, GNUNET_NO);
462 GNUNET_FS_directory_scan_abort (ds); 483 GNUNET_FS_stop (ctx);
463 ds = NULL; 484 ret = 1;
464 if (namespace != NULL) 485 break;
465 GNUNET_FS_namespace_delete (namespace, GNUNET_NO); 486 default:
466 GNUNET_FS_stop (ctx); 487 GNUNET_assert (0);
467 ret = 1; 488 break;
468 break;
469 default:
470 GNUNET_assert (0);
471 break;
472 } 489 }
473 fflush (stdout); 490 fflush (stdout);
474} 491}
@@ -587,6 +604,12 @@ run (void *cls, char *const *args, const char *cfgfile,
587 disable_extractor, 604 disable_extractor,
588 ex, 605 ex,
589 &directory_scan_cb, NULL); 606 &directory_scan_cb, NULL);
607 if (NULL == ds)
608 {
609 FPRINTF (stderr,
610 "%s", _("Failed to start meta directory scanner. Is gnunet-helper-publish-fs installed?\n"));
611 return;
612 }
590 kill_task = 613 kill_task =
591 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task, 614 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task,
592 NULL); 615 NULL);