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

Side by Side Diff: base/files/file_path_watcher_kqueue.cc

Issue 13406005: Stop casting uintptr_t* to int*. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge in comment changes Created 7 years, 8 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 | « base/files/file_path_watcher.h ('k') | no next file » | 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 Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/files/file_path_watcher.h" 5 #include "base/files/file_path_watcher.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <sys/event.h> 8 #include <sys/event.h>
9 #include <sys/param.h> 9 #include <sys/param.h>
10 10
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 // Returns true if the kevent values are error free. 87 // Returns true if the kevent values are error free.
88 bool AreKeventValuesValid(struct kevent* kevents, int count); 88 bool AreKeventValuesValid(struct kevent* kevents, int count);
89 89
90 // Respond to a change of attributes of the path component represented by 90 // Respond to a change of attributes of the path component represented by
91 // |event|. Sets |target_file_affected| to true if |target_| is affected. 91 // |event|. Sets |target_file_affected| to true if |target_| is affected.
92 // Sets |update_watches| to true if |events_| need to be updated. 92 // Sets |update_watches| to true if |events_| need to be updated.
93 void HandleAttributesChange(const EventVector::iterator& event, 93 void HandleAttributesChange(const EventVector::iterator& event,
94 bool* target_file_affected, 94 bool* target_file_affected,
95 bool* update_watches); 95 bool* update_watches);
96 96
97 // Respond to a move of deletion of the path component represented by 97 // Respond to a move or deletion of the path component represented by
98 // |event|. Sets |target_file_affected| to true if |target_| is affected. 98 // |event|. Sets |target_file_affected| to true if |target_| is affected.
99 // Sets |update_watches| to true if |events_| need to be updated. 99 // Sets |update_watches| to true if |events_| need to be updated.
100 void HandleDeleteOrMoveChange(const EventVector::iterator& event, 100 void HandleDeleteOrMoveChange(const EventVector::iterator& event,
101 bool* target_file_affected, 101 bool* target_file_affected,
102 bool* update_watches); 102 bool* update_watches);
103 103
104 // Respond to a creation of an item in the path component represented by 104 // Respond to a creation of an item in the path component represented by
105 // |event|. Sets |target_file_affected| to true if |target_| is affected. 105 // |event|. Sets |target_file_affected| to true if |target_| is affected.
106 // Sets |update_watches| to true if |events_| need to be updated. 106 // Sets |update_watches| to true if |events_| need to be updated.
107 void HandleCreateItemChange(const EventVector::iterator& event, 107 void HandleCreateItemChange(const EventVector::iterator& event,
108 bool* target_file_affected, 108 bool* target_file_affected,
109 bool* update_watches); 109 bool* update_watches);
110 110
111 // Update |events_| with the current status of the system. 111 // Update |events_| with the current status of the system.
112 // Sets |target_file_affected| to true if |target_| is affected. 112 // Sets |target_file_affected| to true if |target_| is affected.
113 // Returns false if an error occurs. 113 // Returns false if an error occurs.
114 bool UpdateWatches(bool* target_file_affected); 114 bool UpdateWatches(bool* target_file_affected);
115 115
116 // Fills |events| with one kevent per component in |path|. 116 // Fills |events| with one kevent per component in |path|.
117 // Returns the number of valid events created where a valid event is 117 // Returns the number of valid events created where a valid event is
118 // defined as one that has a ident (file descriptor) field != -1. 118 // defined as one that has a ident (file descriptor) field != -1.
119 static int EventsForPath(FilePath path, EventVector *events); 119 static int EventsForPath(FilePath path, EventVector *events);
120 120
121 // Release a kevent generated by EventsForPath. 121 // Release a kevent generated by EventsForPath.
122 static void ReleaseEvent(struct kevent& event); 122 static void ReleaseEvent(struct kevent& event);
123 123
124 // Returns a file descriptor that will not block the system from deleting 124 // Returns a file descriptor that will not block the system from deleting
125 // the file it references. 125 // the file it references.
126 static int FileDescriptorForPath(const FilePath& path); 126 static uintptr_t FileDescriptorForPath(const FilePath& path);
127
128 static const uintptr_t kNoFileDescriptor = static_cast<uintptr_t>(-1);
127 129
128 // Closes |*fd| and sets |*fd| to -1. 130 // Closes |*fd| and sets |*fd| to -1.
129 static void CloseFileDescriptor(int* fd); 131 static void CloseFileDescriptor(uintptr_t* fd);
130 132
131 // Returns true if kevent has open file descriptor. 133 // Returns true if kevent has open file descriptor.
132 static bool IsKeventFileDescriptorOpen(const struct kevent& event) { 134 static bool IsKeventFileDescriptorOpen(const struct kevent& event) {
133 return event.ident != static_cast<uintptr_t>(-1); 135 return event.ident != kNoFileDescriptor;
134 } 136 }
135 137
136 static EventData* EventDataForKevent(const struct kevent& event) { 138 static EventData* EventDataForKevent(const struct kevent& event) {
137 return reinterpret_cast<EventData*>(event.udata); 139 return reinterpret_cast<EventData*>(event.udata);
138 } 140 }
139 141
140 EventVector events_; 142 EventVector events_;
141 scoped_refptr<base::MessageLoopProxy> io_message_loop_; 143 scoped_refptr<base::MessageLoopProxy> io_message_loop_;
142 MessageLoopForIO::FileDescriptorWatcher kqueue_watcher_; 144 MessageLoopForIO::FileDescriptorWatcher kqueue_watcher_;
143 FilePathWatcher::Callback callback_; 145 FilePathWatcher::Callback callback_;
144 FilePath target_; 146 FilePath target_;
145 int kqueue_; 147 int kqueue_;
146 148
147 DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl); 149 DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl);
148 }; 150 };
149 151
150 void FilePathWatcherImpl::ReleaseEvent(struct kevent& event) { 152 void FilePathWatcherImpl::ReleaseEvent(struct kevent& event) {
151 CloseFileDescriptor(reinterpret_cast<int*>(&event.ident)); 153 CloseFileDescriptor(&event.ident);
152 EventData* entry = EventDataForKevent(event); 154 EventData* entry = EventDataForKevent(event);
153 delete entry; 155 delete entry;
154 event.udata = NULL; 156 event.udata = NULL;
155 } 157 }
156 158
157 int FilePathWatcherImpl::EventsForPath(FilePath path, EventVector* events) { 159 int FilePathWatcherImpl::EventsForPath(FilePath path, EventVector* events) {
158 DCHECK(MessageLoopForIO::current()); 160 DCHECK(MessageLoopForIO::current());
159 // Make sure that we are working with a clean slate. 161 // Make sure that we are working with a clean slate.
160 DCHECK(events->empty()); 162 DCHECK(events->empty());
161 163
162 std::vector<FilePath::StringType> components; 164 std::vector<FilePath::StringType> components;
163 path.GetComponents(&components); 165 path.GetComponents(&components);
164 166
165 if (components.size() < 1) { 167 if (components.size() < 1) {
166 return -1; 168 return -1;
167 } 169 }
168 170
169 int last_existing_entry = 0; 171 int last_existing_entry = 0;
170 FilePath built_path; 172 FilePath built_path;
171 bool path_still_exists = true; 173 bool path_still_exists = true;
172 for(std::vector<FilePath::StringType>::iterator i = components.begin(); 174 for(std::vector<FilePath::StringType>::iterator i = components.begin();
173 i != components.end(); ++i) { 175 i != components.end(); ++i) {
174 if (i == components.begin()) { 176 if (i == components.begin()) {
175 built_path = FilePath(*i); 177 built_path = FilePath(*i);
176 } else { 178 } else {
177 built_path = built_path.Append(*i); 179 built_path = built_path.Append(*i);
178 } 180 }
179 int fd = -1; 181 uintptr_t fd = kNoFileDescriptor;
180 if (path_still_exists) { 182 if (path_still_exists) {
181 fd = FileDescriptorForPath(built_path); 183 fd = FileDescriptorForPath(built_path);
182 if (fd == -1) { 184 if (fd == kNoFileDescriptor) {
183 path_still_exists = false; 185 path_still_exists = false;
184 } else { 186 } else {
185 ++last_existing_entry; 187 ++last_existing_entry;
186 } 188 }
187 } 189 }
188 FilePath::StringType subdir = (i != (components.end() - 1)) ? *(i + 1) : ""; 190 FilePath::StringType subdir = (i != (components.end() - 1)) ? *(i + 1) : "";
189 EventData* data = new EventData(built_path, subdir); 191 EventData* data = new EventData(built_path, subdir);
190 struct kevent event; 192 struct kevent event;
191 EV_SET(&event, fd, EVFILT_VNODE, (EV_ADD | EV_CLEAR | EV_RECEIPT), 193 EV_SET(&event, fd, EVFILT_VNODE, (EV_ADD | EV_CLEAR | EV_RECEIPT),
192 (NOTE_DELETE | NOTE_WRITE | NOTE_ATTRIB | 194 (NOTE_DELETE | NOTE_WRITE | NOTE_ATTRIB |
193 NOTE_RENAME | NOTE_REVOKE | NOTE_EXTEND), 0, data); 195 NOTE_RENAME | NOTE_REVOKE | NOTE_EXTEND), 0, data);
194 events->push_back(event); 196 events->push_back(event);
195 } 197 }
196 return last_existing_entry; 198 return last_existing_entry;
197 } 199 }
198 200
199 int FilePathWatcherImpl::FileDescriptorForPath(const FilePath& path) { 201 uintptr_t FilePathWatcherImpl::FileDescriptorForPath(const FilePath& path) {
200 return HANDLE_EINTR(open(path.value().c_str(), O_EVTONLY)); 202 int fd = HANDLE_EINTR(open(path.value().c_str(), O_EVTONLY));
203 if (fd == -1)
204 return kNoFileDescriptor;
205 return fd;
201 } 206 }
202 207
203 void FilePathWatcherImpl::CloseFileDescriptor(int *fd) { 208 void FilePathWatcherImpl::CloseFileDescriptor(uintptr_t* fd) {
204 if (*fd == -1) { 209 if (*fd == kNoFileDescriptor) {
205 return; 210 return;
206 } 211 }
207 212
208 if (HANDLE_EINTR(close(*fd)) != 0) { 213 if (HANDLE_EINTR(close(*fd)) != 0) {
209 DPLOG(ERROR) << "close"; 214 DPLOG(ERROR) << "close";
210 } 215 }
211 *fd = -1; 216 *fd = kNoFileDescriptor;
212 } 217 }
213 218
214 bool FilePathWatcherImpl::AreKeventValuesValid(struct kevent* kevents, 219 bool FilePathWatcherImpl::AreKeventValuesValid(struct kevent* kevents,
215 int count) { 220 int count) {
216 if (count < 0) { 221 if (count < 0) {
217 DPLOG(ERROR) << "kevent"; 222 DPLOG(ERROR) << "kevent";
218 return false; 223 return false;
219 } 224 }
220 bool valid = true; 225 bool valid = true;
221 for (int i = 0; i < count; ++i) { 226 for (int i = 0; i < count; ++i) {
222 if (kevents[i].flags & EV_ERROR && kevents[i].data) { 227 if (kevents[i].flags & EV_ERROR && kevents[i].data) {
223 // Find the kevent in |events_| that matches the kevent with the error. 228 // Find the kevent in |events_| that matches the kevent with the error.
224 EventVector::iterator event = events_.begin(); 229 EventVector::iterator event = events_.begin();
225 for (; event != events_.end(); ++event) { 230 for (; event != events_.end(); ++event) {
226 if (event->ident == kevents[i].ident) { 231 if (event->ident == kevents[i].ident) {
227 break; 232 break;
228 } 233 }
229 } 234 }
230 std::string path_name; 235 std::string path_name;
231 if (event != events_.end()) { 236 if (event != events_.end()) {
232 EventData* event_data = EventDataForKevent(*event); 237 EventData* event_data = EventDataForKevent(*event);
233 if (event_data != NULL) { 238 if (event_data != NULL) {
234 path_name = event_data->path_.value(); 239 path_name = event_data->path_.value();
235 } 240 }
236 } 241 }
237 if (path_name.empty()) { 242 if (path_name.empty()) {
238 path_name = base::StringPrintf( 243 path_name = base::StringPrintf(
239 "fd %d", *reinterpret_cast<int*>(&kevents[i].ident)); 244 "fd %ld", reinterpret_cast<long>(&kevents[i].ident));
240 } 245 }
241 DLOG(ERROR) << "Error: " << kevents[i].data << " for " << path_name; 246 DLOG(ERROR) << "Error: " << kevents[i].data << " for " << path_name;
242 valid = false; 247 valid = false;
243 } 248 }
244 } 249 }
245 return valid; 250 return valid;
246 } 251 }
247 252
248 void FilePathWatcherImpl::HandleAttributesChange( 253 void FilePathWatcherImpl::HandleAttributesChange(
249 const EventVector::iterator& event, 254 const EventVector::iterator& event,
250 bool* target_file_affected, 255 bool* target_file_affected,
251 bool* update_watches) { 256 bool* update_watches) {
252 EventVector::iterator next_event = event + 1; 257 EventVector::iterator next_event = event + 1;
253 EventData* next_event_data = EventDataForKevent(*next_event); 258 EventData* next_event_data = EventDataForKevent(*next_event);
254 // Check to see if the next item in path is still accessible. 259 // Check to see if the next item in path is still accessible.
255 int have_access = FileDescriptorForPath(next_event_data->path_); 260 uintptr_t have_access = FileDescriptorForPath(next_event_data->path_);
256 if (have_access == -1) { 261 if (have_access == kNoFileDescriptor) {
257 *target_file_affected = true; 262 *target_file_affected = true;
258 *update_watches = true; 263 *update_watches = true;
259 EventVector::iterator local_event(event); 264 EventVector::iterator local_event(event);
260 for (; local_event != events_.end(); ++local_event) { 265 for (; local_event != events_.end(); ++local_event) {
261 // Close all nodes from the event down. This has the side effect of 266 // Close all nodes from the event down. This has the side effect of
262 // potentially rendering other events in |updates| invalid. 267 // potentially rendering other events in |updates| invalid.
263 // There is no need to remove the events from |kqueue_| because this 268 // There is no need to remove the events from |kqueue_| because this
264 // happens as a side effect of closing the file descriptor. 269 // happens as a side effect of closing the file descriptor.
265 CloseFileDescriptor(reinterpret_cast<int*>(&local_event->ident)); 270 CloseFileDescriptor(&local_event->ident);
266 } 271 }
267 } else { 272 } else {
268 CloseFileDescriptor(&have_access); 273 CloseFileDescriptor(&have_access);
269 } 274 }
270 } 275 }
271 276
272 void FilePathWatcherImpl::HandleDeleteOrMoveChange( 277 void FilePathWatcherImpl::HandleDeleteOrMoveChange(
273 const EventVector::iterator& event, 278 const EventVector::iterator& event,
274 bool* target_file_affected, 279 bool* target_file_affected,
275 bool* update_watches) { 280 bool* update_watches) {
276 *target_file_affected = true; 281 *target_file_affected = true;
277 *update_watches = true; 282 *update_watches = true;
278 EventVector::iterator local_event(event); 283 EventVector::iterator local_event(event);
279 for (; local_event != events_.end(); ++local_event) { 284 for (; local_event != events_.end(); ++local_event) {
280 // Close all nodes from the event down. This has the side effect of 285 // Close all nodes from the event down. This has the side effect of
281 // potentially rendering other events in |updates| invalid. 286 // potentially rendering other events in |updates| invalid.
282 // There is no need to remove the events from |kqueue_| because this 287 // There is no need to remove the events from |kqueue_| because this
283 // happens as a side effect of closing the file descriptor. 288 // happens as a side effect of closing the file descriptor.
284 CloseFileDescriptor(reinterpret_cast<int*>(&local_event->ident)); 289 CloseFileDescriptor(&local_event->ident);
285 } 290 }
286 } 291 }
287 292
288 void FilePathWatcherImpl::HandleCreateItemChange( 293 void FilePathWatcherImpl::HandleCreateItemChange(
289 const EventVector::iterator& event, 294 const EventVector::iterator& event,
290 bool* target_file_affected, 295 bool* target_file_affected,
291 bool* update_watches) { 296 bool* update_watches) {
292 // Get the next item in the path. 297 // Get the next item in the path.
293 EventVector::iterator next_event = event + 1; 298 EventVector::iterator next_event = event + 1;
294 EventData* next_event_data = EventDataForKevent(*next_event);
295
296 // Check to see if it already has a valid file descriptor. 299 // Check to see if it already has a valid file descriptor.
297 if (!IsKeventFileDescriptorOpen(*next_event)) { 300 if (!IsKeventFileDescriptorOpen(*next_event)) {
301 EventData* next_event_data = EventDataForKevent(*next_event);
298 // If not, attempt to open a file descriptor for it. 302 // If not, attempt to open a file descriptor for it.
299 next_event->ident = FileDescriptorForPath(next_event_data->path_); 303 next_event->ident = FileDescriptorForPath(next_event_data->path_);
300 if (IsKeventFileDescriptorOpen(*next_event)) { 304 if (IsKeventFileDescriptorOpen(*next_event)) {
301 *update_watches = true; 305 *update_watches = true;
302 if (next_event_data->subdir_.empty()) { 306 if (next_event_data->subdir_.empty()) {
303 *target_file_affected = true; 307 *target_file_affected = true;
304 } 308 }
305 } 309 }
306 } 310 }
307 } 311 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 // Iterate through each of the updates and react to them. 378 // Iterate through each of the updates and react to them.
375 for (int i = 0; i < count; ++i) { 379 for (int i = 0; i < count; ++i) {
376 // Find our kevent record that matches the update notification. 380 // Find our kevent record that matches the update notification.
377 EventVector::iterator event = events_.begin(); 381 EventVector::iterator event = events_.begin();
378 for (; event != events_.end(); ++event) { 382 for (; event != events_.end(); ++event) {
379 if (!IsKeventFileDescriptorOpen(*event) || 383 if (!IsKeventFileDescriptorOpen(*event) ||
380 event->ident == updates[i].ident) { 384 event->ident == updates[i].ident) {
381 break; 385 break;
382 } 386 }
383 } 387 }
384 if (!IsKeventFileDescriptorOpen(*event) || event == events_.end()) { 388 if (event == events_.end() || !IsKeventFileDescriptorOpen(*event)) {
385 // The event may no longer exist in |events_| because another event 389 // The event may no longer exist in |events_| because another event
386 // modified |events_| in such a way to make it invalid. For example if 390 // modified |events_| in such a way to make it invalid. For example if
387 // the path is /foo/bar/bam and foo is deleted, NOTE_DELETE events for 391 // the path is /foo/bar/bam and foo is deleted, NOTE_DELETE events for
388 // foo, bar and bam will be sent. If foo is processed first, then 392 // foo, bar and bam will be sent. If foo is processed first, then
389 // the file descriptors for bar and bam will already be closed and set 393 // the file descriptors for bar and bam will already be closed and set
390 // to -1 before they get a chance to be processed. 394 // to -1 before they get a chance to be processed.
391 continue; 395 continue;
392 } 396 }
393 397
394 EventData* event_data = EventDataForKevent(*event); 398 EventData* event_data = EventDataForKevent(*event);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 return; 490 return;
487 } 491 }
488 CancelOnMessageLoopThread(); 492 CancelOnMessageLoopThread();
489 } 493 }
490 494
491 void FilePathWatcherImpl::CancelOnMessageLoopThread() { 495 void FilePathWatcherImpl::CancelOnMessageLoopThread() {
492 DCHECK(MessageLoopForIO::current()); 496 DCHECK(MessageLoopForIO::current());
493 if (!is_cancelled()) { 497 if (!is_cancelled()) {
494 set_cancelled(); 498 set_cancelled();
495 kqueue_watcher_.StopWatchingFileDescriptor(); 499 kqueue_watcher_.StopWatchingFileDescriptor();
496 CloseFileDescriptor(&kqueue_); 500 if (HANDLE_EINTR(close(kqueue_)) != 0) {
501 DPLOG(ERROR) << "close kqueue";
502 }
503 kqueue_ = -1;
497 std::for_each(events_.begin(), events_.end(), ReleaseEvent); 504 std::for_each(events_.begin(), events_.end(), ReleaseEvent);
498 events_.clear(); 505 events_.clear();
499 io_message_loop_ = NULL; 506 io_message_loop_ = NULL;
500 MessageLoop::current()->RemoveDestructionObserver(this); 507 MessageLoop::current()->RemoveDestructionObserver(this);
501 callback_.Reset(); 508 callback_.Reset();
502 } 509 }
503 } 510 }
504 511
505 } // namespace 512 } // namespace
506 513
507 FilePathWatcher::FilePathWatcher() { 514 FilePathWatcher::FilePathWatcher() {
508 impl_ = new FilePathWatcherImpl(); 515 impl_ = new FilePathWatcherImpl();
509 } 516 }
510 517
511 } // namespace base 518 } // namespace base
OLDNEW
« no previous file with comments | « base/files/file_path_watcher.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698