diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-14 23:18:52 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-14 23:18:52 +0000 |
commit | 2e9b3b16b6e8471da0f8f816490dba47d87c646d (patch) | |
tree | 1fab1f90a3fa22b11d47b2fad479c313d017012b /src | |
parent | 70ebf5bc2f2f8b0980d5a00a92fa3ed987b2c1a4 (diff) | |
download | gnunet-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.c | 132 |
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 | ||
105 | struct 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 | */ | ||
112 | struct 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 | |||
109 | struct AddDirContext | 129 | struct 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 | */ |
165 | struct GNUNET_FS_DirScanner | 178 | struct 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 | |||
312 | static int | 327 | static int |
313 | should_stop (struct AddDirContext *adc) | 328 | should_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 | */ |
537 | static void | 545 | static void |
538 | extract_file (struct AddDirContext *adc, const char *filename) | 546 | extract_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 | */ |
731 | static int | 739 | static int |
732 | scan_directory (void *cls, const char *filename) | 740 | scan_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 | |||
809 | GNUNET_FS_directory_scan_finish (struct GNUNET_FS_DirScanner *ds, | 816 | GNUNET_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 |
871 | run_directory_scan_thread (struct AddDirContext *adc) | 875 | run_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) |