Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(768)

Side by Side Diff: runtime/bin/directory_posix.cc

Issue 9310082: Run all directory async operations on a separate thread using native ports (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Adderssed review comments from ager@ (and rebased) Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/directory_impl.dart ('k') | runtime/bin/directory_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "bin/directory.h" 5 #include "bin/directory.h"
6 6
7 #include <dirent.h> 7 #include <dirent.h>
8 #include <errno.h> 8 #include <errno.h>
9 #include <sys/param.h> 9 #include <sys/param.h>
10 #include <sys/stat.h> 10 #include <sys/stat.h>
(...skipping 12 matching lines...) Expand all
23 23
24 static void SetOsErrorMessage(char* os_error_message, 24 static void SetOsErrorMessage(char* os_error_message,
25 int os_error_message_len) { 25 int os_error_message_len) {
26 SafeStrNCpy(os_error_message, strerror(errno), os_error_message_len); 26 SafeStrNCpy(os_error_message, strerror(errno), os_error_message_len);
27 } 27 }
28 28
29 29
30 // Forward declarations. 30 // Forward declarations.
31 static bool ListRecursively(const char* dir_name, 31 static bool ListRecursively(const char* dir_name,
32 bool recursive, 32 bool recursive,
33 Dart_Port dir_port, 33 DirectoryListing* listing);
34 Dart_Port file_port,
35 Dart_Port done_port,
36 Dart_Port error_port);
37 static bool DeleteRecursively(const char* dir_name); 34 static bool DeleteRecursively(const char* dir_name);
38 35
39 36
40 static bool ComputeFullPath(const char* dir_name, 37 static bool ComputeFullPath(const char* dir_name,
41 char* path, 38 char* path,
42 int* path_length) { 39 int* path_length) {
43 char* abs_path; 40 char* abs_path;
44 do { 41 do {
45 abs_path = realpath(dir_name, path); 42 abs_path = realpath(dir_name, path);
46 } while (abs_path == NULL && errno == EINTR); 43 } while (abs_path == NULL && errno == EINTR);
(...skipping 10 matching lines...) Expand all
57 } 54 }
58 *path_length += written; 55 *path_length += written;
59 return true; 56 return true;
60 } 57 }
61 58
62 59
63 static bool HandleDir(char* dir_name, 60 static bool HandleDir(char* dir_name,
64 char* path, 61 char* path,
65 int path_length, 62 int path_length,
66 bool recursive, 63 bool recursive,
67 Dart_Port dir_port, 64 DirectoryListing *listing) {
68 Dart_Port file_port,
69 Dart_Port done_port,
70 Dart_Port error_port) {
71 if (strcmp(dir_name, ".") != 0 && 65 if (strcmp(dir_name, ".") != 0 &&
72 strcmp(dir_name, "..") != 0) { 66 strcmp(dir_name, "..") != 0) {
73 size_t written = snprintf(path + path_length, 67 size_t written = snprintf(path + path_length,
74 PATH_MAX - path_length, 68 PATH_MAX - path_length,
75 "%s", 69 "%s",
76 dir_name); 70 dir_name);
77 if (written != strlen(dir_name)) { 71 if (written != strlen(dir_name)) {
78 return false; 72 return false;
79 } 73 }
80 if (dir_port != 0) { 74 bool ok = listing->HandleDirectory(dir_name);
81 Dart_Handle name = Dart_NewString(path); 75 if (!ok) return ok;
82 Dart_Post(dir_port, name);
83 }
84 if (recursive) { 76 if (recursive) {
85 return ListRecursively(path, 77 return ListRecursively(path, recursive, listing);
86 recursive,
87 dir_port,
88 file_port,
89 done_port,
90 error_port);
91 } 78 }
92 } 79 }
93 return true; 80 return true;
94 } 81 }
95 82
96 83
97 static bool HandleFile(char* file_name, 84 static bool HandleFile(char* file_name,
98 char* path, 85 char* path,
99 int path_length, 86 int path_length,
100 Dart_Port file_port) { 87 DirectoryListing *listing) {
101 if (file_port != 0) { 88 // TODO(sgjesse): Pass flags to indicate whether file responses are
102 size_t written = snprintf(path + path_length, 89 // needed.
103 PATH_MAX - path_length, 90 size_t written = snprintf(path + path_length,
104 "%s", 91 PATH_MAX - path_length,
105 file_name); 92 "%s",
106 if (written != strlen(file_name)) { 93 file_name);
107 return false; 94 if (written != strlen(file_name)) {
108 } 95 return false;
109 Dart_Handle name = Dart_NewString(path);
110 Dart_Post(file_port, name);
111 } 96 }
112 return true; 97 return listing->HandleFile(path);
113 } 98 }
114 99
115 100
116 static void PostError(Dart_Port error_port, 101 static void PostError(DirectoryListing *listing,
117 const char* prefix, 102 const char* prefix,
118 const char* suffix, 103 const char* suffix,
119 int error_code) { 104 int error_code) {
120 if (error_port != 0) { 105 // TODO(sgjesse): Pass flags to indicate whether error response is
121 char* error_str = Platform::StrError(error_code); 106 // needed.
122 int error_message_size = 107 char* error_str = Platform::StrError(error_code);
123 strlen(prefix) + strlen(suffix) + strlen(error_str) + 3; 108 int error_message_size =
124 char* message = static_cast<char*>(malloc(error_message_size + 1)); 109 strlen(prefix) + strlen(suffix) + strlen(error_str) + 3;
125 int written = snprintf(message, 110 char* message = static_cast<char*>(malloc(error_message_size + 1));
126 error_message_size + 1, 111 int written = snprintf(message,
127 "%s%s (%s)", 112 error_message_size + 1,
128 prefix, 113 "%s%s (%s)",
129 suffix, 114 prefix,
130 error_str); 115 suffix,
131 ASSERT(written == error_message_size); 116 error_str);
132 free(error_str); 117 ASSERT(written == error_message_size);
133 Dart_Post(error_port, Dart_NewString(message)); 118 free(error_str);
134 free(message); 119 listing->HandleError(message);
135 } 120 free(message);
136 } 121 }
137 122
138 123
139 static bool ListRecursively(const char* dir_name, 124 static bool ListRecursively(const char* dir_name,
140 bool recursive, 125 bool recursive,
141 Dart_Port dir_port, 126 DirectoryListing *listing) {
142 Dart_Port file_port,
143 Dart_Port done_port,
144 Dart_Port error_port) {
145 DIR* dir_pointer; 127 DIR* dir_pointer;
146 do { 128 do {
147 dir_pointer = opendir(dir_name); 129 dir_pointer = opendir(dir_name);
148 } while (dir_pointer == NULL && errno == EINTR); 130 } while (dir_pointer == NULL && errno == EINTR);
149 if (dir_pointer == NULL) { 131 if (dir_pointer == NULL) {
150 PostError(error_port, "Directory listing failed for: ", dir_name, errno); 132 PostError(listing, "Directory listing failed for: ", dir_name, errno);
151 return false; 133 return false;
152 } 134 }
153 135
154 // Compute full path for the directory currently being listed. The 136 // Compute full path for the directory currently being listed. The
155 // path buffer will be used to construct the current path in the 137 // path buffer will be used to construct the current path in the
156 // recursive traversal. path_length does not always equal 138 // recursive traversal. path_length does not always equal
157 // strlen(path) but indicates the current prefix of path that is the 139 // strlen(path) but indicates the current prefix of path that is the
158 // path of the current directory in the traversal. 140 // path of the current directory in the traversal.
159 char *path = static_cast<char*>(malloc(PATH_MAX)); 141 char *path = static_cast<char*>(malloc(PATH_MAX));
160 ASSERT(path != NULL); 142 ASSERT(path != NULL);
161 int path_length = 0; 143 int path_length = 0;
162 bool valid = ComputeFullPath(dir_name, path, &path_length); 144 bool valid = ComputeFullPath(dir_name, path, &path_length);
163 if (!valid) { 145 if (!valid) {
164 free(path); 146 free(path);
165 PostError(error_port, "Directory listing failed for: ", dir_name, errno); 147 PostError(listing, "Directory listing failed for: ", dir_name, errno);
166 return false; 148 return false;
167 } 149 }
168 150
169 // Iterated the directory and post the directories and files to the 151 // Iterated the directory and post the directories and files to the
170 // ports. 152 // ports.
171 int read = 0; 153 int read = 0;
172 bool success = true; 154 bool success = true;
173 dirent entry; 155 dirent entry;
174 dirent* result; 156 dirent* result;
175 while ((read = TEMP_FAILURE_RETRY(readdir_r(dir_pointer, 157 while ((read = TEMP_FAILURE_RETRY(readdir_r(dir_pointer,
176 &entry, 158 &entry,
177 &result))) == 0 && 159 &result))) == 0 &&
178 result != NULL && 160 result != NULL &&
179 success) { 161 success) {
180 switch (entry.d_type) { 162 switch (entry.d_type) {
181 case DT_DIR: 163 case DT_DIR:
182 success = success && HandleDir(entry.d_name, 164 success = success && HandleDir(entry.d_name,
183 path, 165 path,
184 path_length, 166 path_length,
185 recursive, 167 recursive,
186 dir_port, 168 listing);
187 file_port,
188 done_port,
189 error_port);
190 break; 169 break;
191 case DT_REG: 170 case DT_REG:
192 success = success && HandleFile(entry.d_name, 171 success = success && HandleFile(entry.d_name,
193 path, 172 path,
194 path_length, 173 path_length,
195 file_port); 174 listing);
196 break; 175 break;
197 case DT_UNKNOWN: { 176 case DT_UNKNOWN: {
198 // On some file systems the entry type is not determined by 177 // On some file systems the entry type is not determined by
199 // readdir_r. For those we use lstat to determine the entry 178 // readdir_r. For those we use lstat to determine the entry
200 // type. 179 // type.
201 struct stat entry_info; 180 struct stat entry_info;
202 size_t written = snprintf(path + path_length, 181 size_t written = snprintf(path + path_length,
203 PATH_MAX - path_length, 182 PATH_MAX - path_length,
204 "%s", 183 "%s",
205 entry.d_name); 184 entry.d_name);
206 if (written != strlen(entry.d_name)) { 185 if (written != strlen(entry.d_name)) {
207 success = false; 186 success = false;
208 break; 187 break;
209 } 188 }
210 int lstat_success = TEMP_FAILURE_RETRY(lstat(path, &entry_info)); 189 int lstat_success = TEMP_FAILURE_RETRY(lstat(path, &entry_info));
211 if (lstat_success == -1) { 190 if (lstat_success == -1) {
212 success = false; 191 success = false;
213 PostError(error_port, "Directory listing failed for: ", path, errno); 192 PostError(listing, "Directory listing failed for: ", path, errno);
214 break; 193 break;
215 } 194 }
216 if ((entry_info.st_mode & S_IFMT) == S_IFDIR) { 195 if ((entry_info.st_mode & S_IFMT) == S_IFDIR) {
217 success = success && HandleDir(entry.d_name, 196 success = success && HandleDir(entry.d_name,
218 path, 197 path,
219 path_length, 198 path_length,
220 recursive, 199 recursive,
221 dir_port, 200 listing);
222 file_port,
223 done_port,
224 error_port);
225 } else if ((entry_info.st_mode & S_IFMT) == S_IFREG) { 201 } else if ((entry_info.st_mode & S_IFMT) == S_IFREG) {
226 success = success && HandleFile(entry.d_name, 202 success = success && HandleFile(entry.d_name,
227 path, 203 path,
228 path_length, 204 path_length,
229 file_port); 205 listing);
230 } 206 }
231 break; 207 break;
232 } 208 }
233 default: 209 default:
234 break; 210 break;
235 } 211 }
236 } 212 }
237 213
238 if (read != 0) { 214 if (read != 0) {
239 success = false; 215 success = false;
240 PostError(error_port, "Directory listing failed", "", read); 216 PostError(listing, "Directory listing failed", "", read);
241 } 217 }
242 218
243 if (closedir(dir_pointer) == -1) { 219 if (closedir(dir_pointer) == -1) {
244 PostError(error_port, "Failed to close directory", "", errno); 220 PostError(listing, "Failed to close directory", "", errno);
245 } 221 }
246 free(path); 222 free(path);
247 223
248 return success; 224 return success;
249 } 225 }
250 226
251 227
252 static bool DeleteFile(char* file_name, 228 static bool DeleteFile(char* file_name,
253 char* path, 229 char* path,
254 int path_length) { 230 int path_length) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 if ((read != 0) || 333 if ((read != 0) ||
358 (closedir(dir_pointer) == -1) || 334 (closedir(dir_pointer) == -1) ||
359 (remove(dir_name) == -1)) { 335 (remove(dir_name) == -1)) {
360 return false; 336 return false;
361 } 337 }
362 338
363 return success; 339 return success;
364 } 340 }
365 341
366 342
367 void Directory::List(const char* dir_name, 343 bool Directory::List(const char* dir_name,
368 bool recursive, 344 bool recursive,
369 Dart_Port dir_port, 345 DirectoryListing *listing) {
370 Dart_Port file_port, 346 bool completed = ListRecursively(dir_name, recursive, listing);
371 Dart_Port done_port, 347 return completed;
372 Dart_Port error_port) {
373 bool completed = ListRecursively(dir_name,
374 recursive,
375 dir_port,
376 file_port,
377 done_port,
378 error_port);
379 if (done_port != 0) {
380 Dart_Handle value = Dart_NewBoolean(completed);
381 Dart_Post(done_port, value);
382 }
383 } 348 }
384 349
385 350
386 Directory::ExistsResult Directory::Exists(const char* dir_name) { 351 Directory::ExistsResult Directory::Exists(const char* dir_name) {
387 struct stat entry_info; 352 struct stat entry_info;
388 int lstat_success = TEMP_FAILURE_RETRY(lstat(dir_name, &entry_info)); 353 int lstat_success = TEMP_FAILURE_RETRY(lstat(dir_name, &entry_info));
389 if (lstat_success == 0) { 354 if (lstat_success == 0) {
390 if ((entry_info.st_mode & S_IFMT) == S_IFDIR) { 355 if ((entry_info.st_mode & S_IFMT) == S_IFDIR) {
391 return EXISTS; 356 return EXISTS;
392 } else { 357 } else {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 } 418 }
454 419
455 420
456 bool Directory::Delete(const char* dir_name, bool recursive) { 421 bool Directory::Delete(const char* dir_name, bool recursive) {
457 if (!recursive) { 422 if (!recursive) {
458 return (TEMP_FAILURE_RETRY(remove(dir_name)) == 0); 423 return (TEMP_FAILURE_RETRY(remove(dir_name)) == 0);
459 } else { 424 } else {
460 return DeleteRecursively(dir_name); 425 return DeleteRecursively(dir_name);
461 } 426 }
462 } 427 }
OLDNEW
« no previous file with comments | « runtime/bin/directory_impl.dart ('k') | runtime/bin/directory_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698