aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-14 23:18:52 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-14 23:18:52 +0000
commit2e9b3b16b6e8471da0f8f816490dba47d87c646d (patch)
tree1fab1f90a3fa22b11d47b2fad479c313d017012b /src
parent70ebf5bc2f2f8b0980d5a00a92fa3ed987b2c1a4 (diff)
downloadgnunet-2e9b3b16b6e8471da0f8f816490dba47d87c646d.tar.gz
gnunet-2e9b3b16b6e8471da0f8f816490dba47d87c646d.zip
-LRN: use signal pipe instead of a semaphore
Diffstat (limited to 'src')
-rw-r--r--src/fs/fs_dirmetascan.c132
1 files changed, 68 insertions, 64 deletions
diff --git a/src/fs/fs_dirmetascan.c b/src/fs/fs_dirmetascan.c
index 6af186347..fd8ab15c4 100644
--- a/src/fs/fs_dirmetascan.c
+++ b/src/fs/fs_dirmetascan.c
@@ -102,6 +102,26 @@ struct MetaCounter
102 struct MetaCounter *next; 102 struct MetaCounter *next;
103}; 103};
104 104
105struct AddDirContext;
106
107/**
108 * A structure used to hold a pointer to the tree item that is being
109 * processed.
110 * Needed to avoid changing the context for every recursive call.
111 */
112struct AddDirStack
113{
114 /**
115 * Context pointer
116 */
117 struct AddDirContext *adc;
118
119 /**
120 * Parent directory
121 */
122 struct ShareTreeItem *parent;
123};
124
105/** 125/**
106 * Execution context for 'add_dir' 126 * Execution context for 'add_dir'
107 * Owned by the initiator thread. 127 * Owned by the initiator thread.
@@ -109,13 +129,11 @@ struct MetaCounter
109struct AddDirContext 129struct AddDirContext
110{ 130{
111 /** 131 /**
112 * Parent directory (used to access keyword and metadata counters,
113 * and the like).
114 * After the scan is finished, it will contain a pointer to the 132 * After the scan is finished, it will contain a pointer to the
115 * top-level directory entry in the directory tree built by the 133 * top-level directory entry in the directory tree built by the
116 * scanner. 134 * scanner.
117 */ 135 */
118 struct ShareTreeItem *parent; 136 struct ShareTreeItem *toplevel;
119 137
120 /** 138 /**
121 * Expanded filename (as given by the scan initiator). 139 * Expanded filename (as given by the scan initiator).
@@ -124,15 +142,10 @@ struct AddDirContext
124 char *filename_expanded; 142 char *filename_expanded;
125 143
126 /** 144 /**
127 * A synchronization privitive. Whenever its state is altered, 145 * A pipe end to read signals from.
128 * it means that the initiator wants the scanner to wrap up. 146 * Owned by the initiator thread.
129 * It is owned by the initiator thread.
130 */ 147 */
131#if WINDOWS 148 const struct GNUNET_DISK_FileHandle *stop_read;
132 HANDLE stop;
133#else
134 sem_t *stop;
135#endif
136 149
137 /** 150 /**
138 * 1 if the scanner should stop, 0 otherwise. Set in response 151 * 1 if the scanner should stop, 0 otherwise. Set in response
@@ -164,15 +177,17 @@ struct AddDirContext
164 */ 177 */
165struct GNUNET_FS_DirScanner 178struct GNUNET_FS_DirScanner
166{ 179{
167 /** 180 /**
168 * A synchronization privitive that is used to signal the scanner to stop. 181 * A pipe end to read signals from.
169 * Owned by the initiator thread. 182 * Owned by the initiator thread.
170 */ 183 */
171#if WINDOWS 184 const struct GNUNET_DISK_FileHandle *stop_write;
172 HANDLE stop; 185
173#else 186 /**
174 sem_t *stop; 187 * A pipe transfer signals to the scanner.
175#endif 188 * Owned by the initiator thread.
189 */
190 struct GNUNET_DISK_PipeHandle *stop_pipe;
176 191
177 /** 192 /**
178 * A thread object for the scanner thread. 193 * A thread object for the scanner thread.
@@ -312,21 +327,14 @@ struct ProcessMetadataContext
312static int 327static int
313should_stop (struct AddDirContext *adc) 328should_stop (struct AddDirContext *adc)
314{ 329{
315#if WINDOWS 330 errno = 0;
316 if (WaitForSingleObject (adc->stop, 0) == WAIT_TIMEOUT) 331 char c;
317 return 0; 332 if (GNUNET_DISK_file_read_non_blocking (adc->stop_read, &c, 1) == 1
318 adc->do_stop = 1; 333 || errno != EAGAIN)
319 return 1;
320#else
321 int value;
322 sem_getvalue(adc->stop, &value);
323 if (value > 0)
324 { 334 {
325 adc->do_stop = 1; 335 adc->do_stop = 1;
326 return 1;
327 } 336 }
328 return 0; 337 return adc->do_stop;
329#endif
330} 338}
331 339
332/** 340/**
@@ -535,19 +543,19 @@ make_item (struct ShareTreeItem *parent)
535 * @param filename name of the file to process 543 * @param filename name of the file to process
536 */ 544 */
537static void 545static void
538extract_file (struct AddDirContext *adc, const char *filename) 546extract_file (struct AddDirStack *ads, const char *filename)
539{ 547{
540 struct ShareTreeItem *item; 548 struct ShareTreeItem *item;
541 const char *short_fn; 549 const char *short_fn;
542 550
543 item = make_item (adc->parent); 551 item = make_item (ads->parent);
544 552
545 GNUNET_DISK_file_size (filename, &item->file_size, GNUNET_YES); 553 GNUNET_DISK_file_size (filename, &item->file_size, GNUNET_YES);
546 item->is_directory = GNUNET_NO; 554 item->is_directory = GNUNET_NO;
547 555
548 item->meta = GNUNET_CONTAINER_meta_data_create (); 556 item->meta = GNUNET_CONTAINER_meta_data_create ();
549 GNUNET_FS_meta_data_extract_from_file (item->meta, filename, 557 GNUNET_FS_meta_data_extract_from_file (item->meta, filename,
550 adc->plugins); 558 ads->adc->plugins);
551 GNUNET_CONTAINER_meta_data_delete (item->meta, EXTRACTOR_METATYPE_FILENAME, 559 GNUNET_CONTAINER_meta_data_delete (item->meta, EXTRACTOR_METATYPE_FILENAME,
552 NULL, 0); 560 NULL, 0);
553 short_fn = GNUNET_STRINGS_get_short_name (filename); 561 short_fn = GNUNET_STRINGS_get_short_name (filename);
@@ -725,13 +733,14 @@ process_keywords_and_metadata (struct ProcessMetadataStackItem *stack,
725 * scan. 733 * scan.
726 * TODO: find a way to make it non-recursive. 734 * TODO: find a way to make it non-recursive.
727 * 735 *
728 * @param cls the 'struct AddDirContext*' we're in 736 * @param cls the 'struct AddDirStack *' we're in
729 * @param filename file or directory to scan 737 * @param filename file or directory to scan
730 */ 738 */
731static int 739static int
732scan_directory (void *cls, const char *filename) 740scan_directory (void *cls, const char *filename)
733{ 741{
734 struct AddDirContext *adc = cls, recurse_adc; 742 struct AddDirStack *ads = cls, recurse_ads;
743 struct AddDirContext *adc = ads->adc;
735 struct stat sbuf; 744 struct stat sbuf;
736 struct ShareTreeItem *item; 745 struct ShareTreeItem *item;
737 const char *short_fn; 746 const char *short_fn;
@@ -763,33 +772,31 @@ scan_directory (void *cls, const char *filename)
763 } 772 }
764 773
765 if (!S_ISDIR (sbuf.st_mode)) 774 if (!S_ISDIR (sbuf.st_mode))
766 extract_file (adc, filename); 775 extract_file (ads, filename);
767 else 776 else
768 { 777 {
769 item = make_item (adc->parent); 778 item = make_item (ads->parent);
770 item->meta = GNUNET_CONTAINER_meta_data_create (); 779 item->meta = GNUNET_CONTAINER_meta_data_create ();
771 780
772 item->is_directory = GNUNET_YES; 781 item->is_directory = GNUNET_YES;
773 782
774 /* copy fields from adc */ 783 recurse_ads.adc = adc;
775 recurse_adc = *adc; 784 recurse_ads.parent = item;
776 /* replace recurse_adc contents with the ones for this directory */
777 recurse_adc.parent = item;
778 785
779 /* recurse into directory */ 786 /* recurse into directory */
780 GNUNET_DISK_directory_scan (filename, &scan_directory, &recurse_adc); 787 GNUNET_DISK_directory_scan (filename, &scan_directory, &recurse_ads);
781 788
782 short_fn = GNUNET_STRINGS_get_short_name (filename); 789 short_fn = GNUNET_STRINGS_get_short_name (filename);
783 790
784 item->filename = GNUNET_strdup (filename); 791 item->filename = GNUNET_strdup (filename);
785 item->short_filename = GNUNET_strdup (short_fn); 792 item->short_filename = GNUNET_strdup (short_fn);
786 793
787 if (adc->parent == NULL) 794 if (ads->parent == NULL)
788 { 795 {
789 /* we're finished with the scan, make sure caller gets the top-level 796 /* we're finished with the scan, make sure caller gets the top-level
790 * directory pointer 797 * directory pointer
791 */ 798 */
792 adc->parent = item; 799 adc->toplevel = item;
793 } 800 }
794 } 801 }
795 return GNUNET_OK; 802 return GNUNET_OK;
@@ -809,11 +816,9 @@ void
809GNUNET_FS_directory_scan_finish (struct GNUNET_FS_DirScanner *ds, 816GNUNET_FS_directory_scan_finish (struct GNUNET_FS_DirScanner *ds,
810 int close_pipe) 817 int close_pipe)
811{ 818{
812#if WINDOWS 819 char c = 1;
813 SetEvent (ds->stop); 820 GNUNET_DISK_file_write (ds->stop_write, &c, 1);
814#else 821
815 sem_post (&ds->stop);
816#endif
817 if (close_pipe) 822 if (close_pipe)
818 { 823 {
819 if (ds->progress_read_task != GNUNET_SCHEDULER_NO_TASK) 824 if (ds->progress_read_task != GNUNET_SCHEDULER_NO_TASK)
@@ -845,16 +850,15 @@ GNUNET_FS_directory_scan_cleanup (struct GNUNET_FS_DirScanner *ds)
845 GNUNET_FS_directory_scan_finish (ds, GNUNET_YES); 850 GNUNET_FS_directory_scan_finish (ds, GNUNET_YES);
846#if WINDOWS 851#if WINDOWS
847 WaitForSingleObject (ds->thread, INFINITE); 852 WaitForSingleObject (ds->thread, INFINITE);
848 CloseHandle (ds->stop);
849 CloseHandle (ds->thread); 853 CloseHandle (ds->thread);
850#else 854#else
851 pthread_join (ds->thread, NULL); 855 pthread_join (ds->thread, NULL);
852 sem_destroy (&ds->stop);
853 pthread_detach (ds->thread); 856 pthread_detach (ds->thread);
854#endif 857#endif
855 858
859 GNUNET_DISK_pipe_close (ds->stop_pipe);
856 GNUNET_DISK_pipe_close (ds->progress_pipe); 860 GNUNET_DISK_pipe_close (ds->progress_pipe);
857 result = ds->adc->parent; 861 result = ds->adc->toplevel;
858 GNUNET_free (ds->adc); 862 GNUNET_free (ds->adc);
859 GNUNET_free (ds); 863 GNUNET_free (ds);
860 return result; 864 return result;
@@ -870,7 +874,10 @@ static int
870#endif 874#endif
871run_directory_scan_thread (struct AddDirContext *adc) 875run_directory_scan_thread (struct AddDirContext *adc)
872{ 876{
873 scan_directory (adc, adc->filename_expanded); 877 struct AddDirStack ads;
878 ads.adc = adc;
879 ads.parent = NULL;
880 scan_directory (&ads, adc->filename_expanded);
874 GNUNET_free (adc->filename_expanded); 881 GNUNET_free (adc->filename_expanded);
875 if (adc->plugins != NULL) 882 if (adc->plugins != NULL)
876 EXTRACTOR_plugin_remove_all (adc->plugins); 883 EXTRACTOR_plugin_remove_all (adc->plugins);
@@ -1060,15 +1067,8 @@ GNUNET_FS_directory_scan_start (const char *filename,
1060 1067
1061 ds->adc = adc; 1068 ds->adc = adc;
1062 1069
1063#if WINDOWS 1070 ds->stop_pipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO);
1064 ds->stop = CreateEvent (NULL, TRUE, FALSE, NULL); 1071 if (ds->stop_pipe == NULL)
1065 adc->stop = ds->stop;
1066 ok = ds->stop != INVALID_HANDLE_VALUE;
1067#else
1068 ok = !sem_init (&ds->stop, 0, 0);
1069 adc = &ds->stop;
1070#endif
1071 if (!ok)
1072 { 1072 {
1073 GNUNET_free (adc); 1073 GNUNET_free (adc);
1074 GNUNET_free (ds); 1074 GNUNET_free (ds);
@@ -1076,6 +1076,10 @@ GNUNET_FS_directory_scan_start (const char *filename,
1076 GNUNET_DISK_pipe_close (progress_pipe); 1076 GNUNET_DISK_pipe_close (progress_pipe);
1077 return NULL; 1077 return NULL;
1078 } 1078 }
1079 ds->stop_write = GNUNET_DISK_pipe_handle (ds->stop_pipe,
1080 GNUNET_DISK_PIPE_END_WRITE);
1081 adc->stop_read = GNUNET_DISK_pipe_handle (ds->stop_pipe,
1082 GNUNET_DISK_PIPE_END_READ);
1079 1083
1080 adc->plugins = NULL; 1084 adc->plugins = NULL;
1081 if (!disable_extractor) 1085 if (!disable_extractor)