struct MetaCounter *next;\r
};\r
\r
+struct AddDirContext;\r
+\r
+/**\r
+ * A structure used to hold a pointer to the tree item that is being\r
+ * processed.\r
+ * Needed to avoid changing the context for every recursive call.\r
+ */\r
+struct AddDirStack\r
+{\r
+ /**\r
+ * Context pointer\r
+ */\r
+ struct AddDirContext *adc;\r
+\r
+ /**\r
+ * Parent directory\r
+ */\r
+ struct ShareTreeItem *parent;\r
+};\r
+\r
/**\r
* Execution context for 'add_dir'\r
* Owned by the initiator thread.\r
struct AddDirContext\r
{\r
/**\r
- * Parent directory (used to access keyword and metadata counters,\r
- * and the like).\r
* After the scan is finished, it will contain a pointer to the\r
* top-level directory entry in the directory tree built by the\r
* scanner.\r
*/\r
- struct ShareTreeItem *parent;\r
+ struct ShareTreeItem *toplevel;\r
\r
/**\r
* Expanded filename (as given by the scan initiator).\r
char *filename_expanded;\r
\r
/**\r
- * A synchronization privitive. Whenever its state is altered,\r
- * it means that the initiator wants the scanner to wrap up.\r
- * It is owned by the initiator thread.\r
+ * A pipe end to read signals from.\r
+ * Owned by the initiator thread.\r
*/\r
-#if WINDOWS\r
- HANDLE stop;\r
-#else\r
- sem_t *stop;\r
-#endif\r
+ const struct GNUNET_DISK_FileHandle *stop_read;\r
\r
/**\r
* 1 if the scanner should stop, 0 otherwise. Set in response\r
*/\r
struct GNUNET_FS_DirScanner\r
{\r
- /**\r
- * A synchronization privitive that is used to signal the scanner to stop.\r
- * Owned by the initiator thread.\r
- */\r
-#if WINDOWS\r
- HANDLE stop;\r
-#else\r
- sem_t *stop;\r
-#endif\r
+ /**\r
+ * A pipe end to read signals from.\r
+ * Owned by the initiator thread.\r
+ */\r
+ const struct GNUNET_DISK_FileHandle *stop_write;\r
+ \r
+ /**\r
+ * A pipe transfer signals to the scanner.\r
+ * Owned by the initiator thread.\r
+ */\r
+ struct GNUNET_DISK_PipeHandle *stop_pipe;\r
\r
/**\r
* A thread object for the scanner thread.\r
static int\r
should_stop (struct AddDirContext *adc)\r
{\r
-#if WINDOWS\r
- if (WaitForSingleObject (adc->stop, 0) == WAIT_TIMEOUT)\r
- return 0;\r
- adc->do_stop = 1;\r
- return 1;\r
-#else\r
- int value;\r
- sem_getvalue(adc->stop, &value); \r
- if (value > 0)\r
+ errno = 0;\r
+ char c;\r
+ if (GNUNET_DISK_file_read_non_blocking (adc->stop_read, &c, 1) == 1\r
+ || errno != EAGAIN)\r
{\r
adc->do_stop = 1;\r
- return 1;\r
}\r
- return 0;\r
-#endif\r
+ return adc->do_stop;\r
}\r
\r
/**\r
* @param filename name of the file to process\r
*/\r
static void\r
-extract_file (struct AddDirContext *adc, const char *filename)\r
+extract_file (struct AddDirStack *ads, const char *filename)\r
{\r
struct ShareTreeItem *item;\r
const char *short_fn;\r
\r
- item = make_item (adc->parent);\r
+ item = make_item (ads->parent);\r
\r
GNUNET_DISK_file_size (filename, &item->file_size, GNUNET_YES);\r
item->is_directory = GNUNET_NO;\r
\r
item->meta = GNUNET_CONTAINER_meta_data_create ();\r
GNUNET_FS_meta_data_extract_from_file (item->meta, filename,\r
- adc->plugins);\r
+ ads->adc->plugins);\r
GNUNET_CONTAINER_meta_data_delete (item->meta, EXTRACTOR_METATYPE_FILENAME,\r
NULL, 0);\r
short_fn = GNUNET_STRINGS_get_short_name (filename);\r
* scan.\r
* TODO: find a way to make it non-recursive.\r
*\r
- * @param cls the 'struct AddDirContext*' we're in\r
+ * @param cls the 'struct AddDirStack *' we're in\r
* @param filename file or directory to scan\r
*/\r
static int\r
scan_directory (void *cls, const char *filename)\r
{\r
- struct AddDirContext *adc = cls, recurse_adc;\r
+ struct AddDirStack *ads = cls, recurse_ads;\r
+ struct AddDirContext *adc = ads->adc;\r
struct stat sbuf;\r
struct ShareTreeItem *item;\r
const char *short_fn;\r
}\r
\r
if (!S_ISDIR (sbuf.st_mode))\r
- extract_file (adc, filename);\r
+ extract_file (ads, filename);\r
else\r
{\r
- item = make_item (adc->parent);\r
+ item = make_item (ads->parent);\r
item->meta = GNUNET_CONTAINER_meta_data_create ();\r
\r
item->is_directory = GNUNET_YES;\r
\r
- /* copy fields from adc */\r
- recurse_adc = *adc;\r
- /* replace recurse_adc contents with the ones for this directory */\r
- recurse_adc.parent = item;\r
+ recurse_ads.adc = adc;\r
+ recurse_ads.parent = item;\r
\r
/* recurse into directory */\r
- GNUNET_DISK_directory_scan (filename, &scan_directory, &recurse_adc);\r
+ GNUNET_DISK_directory_scan (filename, &scan_directory, &recurse_ads);\r
\r
short_fn = GNUNET_STRINGS_get_short_name (filename);\r
\r
item->filename = GNUNET_strdup (filename);\r
item->short_filename = GNUNET_strdup (short_fn);\r
\r
- if (adc->parent == NULL)\r
+ if (ads->parent == NULL)\r
{\r
/* we're finished with the scan, make sure caller gets the top-level\r
* directory pointer\r
*/\r
- adc->parent = item;\r
+ adc->toplevel = item;\r
}\r
}\r
return GNUNET_OK;\r
GNUNET_FS_directory_scan_finish (struct GNUNET_FS_DirScanner *ds,\r
int close_pipe)\r
{\r
-#if WINDOWS\r
- SetEvent (ds->stop);\r
-#else\r
- sem_post (&ds->stop);\r
-#endif\r
+ char c = 1;\r
+ GNUNET_DISK_file_write (ds->stop_write, &c, 1);\r
+\r
if (close_pipe)\r
{\r
if (ds->progress_read_task != GNUNET_SCHEDULER_NO_TASK)\r
GNUNET_FS_directory_scan_finish (ds, GNUNET_YES);\r
#if WINDOWS\r
WaitForSingleObject (ds->thread, INFINITE);\r
- CloseHandle (ds->stop);\r
CloseHandle (ds->thread);\r
#else\r
pthread_join (ds->thread, NULL);\r
- sem_destroy (&ds->stop);\r
pthread_detach (ds->thread);\r
#endif\r
\r
+ GNUNET_DISK_pipe_close (ds->stop_pipe);\r
GNUNET_DISK_pipe_close (ds->progress_pipe);\r
- result = ds->adc->parent;\r
+ result = ds->adc->toplevel;\r
GNUNET_free (ds->adc);\r
GNUNET_free (ds);\r
return result;\r
#endif\r
run_directory_scan_thread (struct AddDirContext *adc)\r
{\r
- scan_directory (adc, adc->filename_expanded);\r
+ struct AddDirStack ads;\r
+ ads.adc = adc;\r
+ ads.parent = NULL;\r
+ scan_directory (&ads, adc->filename_expanded);\r
GNUNET_free (adc->filename_expanded);\r
if (adc->plugins != NULL)\r
EXTRACTOR_plugin_remove_all (adc->plugins);\r
\r
ds->adc = adc;\r
\r
-#if WINDOWS\r
- ds->stop = CreateEvent (NULL, TRUE, FALSE, NULL);\r
- adc->stop = ds->stop;\r
- ok = ds->stop != INVALID_HANDLE_VALUE;\r
-#else\r
- ok = !sem_init (&ds->stop, 0, 0);\r
- adc = &ds->stop;\r
-#endif\r
- if (!ok)\r
+ ds->stop_pipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO);\r
+ if (ds->stop_pipe == NULL)\r
{\r
GNUNET_free (adc);\r
GNUNET_free (ds);\r
GNUNET_DISK_pipe_close (progress_pipe);\r
return NULL;\r
}\r
+ ds->stop_write = GNUNET_DISK_pipe_handle (ds->stop_pipe,\r
+ GNUNET_DISK_PIPE_END_WRITE);\r
+ adc->stop_read = GNUNET_DISK_pipe_handle (ds->stop_pipe,\r
+ GNUNET_DISK_PIPE_END_READ);\r
\r
adc->plugins = NULL;\r
if (!disable_extractor)\r