Index: base/directory_watcher_inotify.cc |
=================================================================== |
--- base/directory_watcher_inotify.cc (revision 16266) |
+++ base/directory_watcher_inotify.cc (working copy) |
@@ -88,8 +88,6 @@ |
DirectoryWatcherImpl(); |
~DirectoryWatcherImpl(); |
- void EnsureSetupFinished(); |
- |
// Called for each event coming from one of watches. |
void OnInotifyEvent(const inotify_event* event); |
@@ -120,11 +118,14 @@ |
// Watch returned by InotifyReader. |
InotifyReader::Watch watch_; |
- // Set of watched inodes. |
- InodeSet inodes_watched_; |
+ // Needed because inotify event-> name only provides name of the |
+ // newly created/deleted file, without any path information. |
+ // event->name = SubDir |
+ // With this data structure we can get /tmp/DirectoryWatcherTest/SubDir. |
+ base::hash_map<InotifyReader::Watch, FilePath> paths_; |
- // Keep track of registered watches. |
- WatchSet watches_; |
+ typedef std::pair<ino_t, FilePath> InodeInfo; |
+ base::hash_map<InotifyReader::Watch, InodeInfo> watches_; |
// Lock to protect inodes_watched_ and watches_. |
Lock lock_; |
@@ -302,7 +303,6 @@ |
paths_[watch] = path; // We don't yet watch this path. |
watchers_[watch].insert(watcher); |
- |
return watch; |
} |
@@ -323,7 +323,6 @@ |
watchers_.erase(watch); |
return (inotify_rm_watch(inotify_fd_, watch) == 0); |
} |
- |
return true; |
} |
@@ -341,7 +340,7 @@ |
watchers_[event->wd].end()); |
} |
- for (WatcherSet::iterator watcher = watchers_to_notify.begin(); |
+ for (WatcherSet::const_iterator watcher = watchers_to_notify.begin(); |
watcher != watchers_to_notify.end(); |
++watcher) { |
(*watcher)->OnInotifyEvent(event); |
@@ -359,13 +358,14 @@ |
if (recursive_) |
recursive_setup_finished_.Wait(); |
- for (WatchSet::iterator watch = watches_.begin(); |
- watch != watches_.end(); |
- ++watch) { |
- Singleton<InotifyReader>::get()->RemoveWatch(*watch, this); |
+ |
+ for (base::hash_map<InotifyReader::Watch, InodeInfo>::const_iterator it = |
+ watches_.begin(); |
+ it != watches_.end(); |
+ ++it) { |
+ Singleton<InotifyReader>::get()->RemoveWatch(it->first, this); |
} |
watches_.clear(); |
- inodes_watched_.clear(); |
} |
void DirectoryWatcherImpl::OnInotifyEvent(const inotify_event* event) { |
@@ -375,17 +375,55 @@ |
if (!(event->mask & IN_ISDIR)) |
return; |
+ FilePath path(watches_[event->wd].second); |
+ path.Append(event->name); |
if (event->mask & IN_CREATE || event->mask & IN_MOVED_TO) { |
- // TODO(phajdan.jr): add watch for this new directory. |
- NOTIMPLEMENTED(); |
+ // Don't do anything, if not recursive watch; |
+ if (!recursive_) |
+ return; |
+ if (event->mask & IN_MOVED_TO) { |
+ // Don't do anything, if path is moved outside of root_path_. |
+ if (path.value().compare(0, root_path_.value().length(), |
+ root_path_.value())) |
+ return; |
+ } |
+ recursive_setup_finished_.Wait(); |
+ scoped_ptr<Task> subtree_task(new RegisterSubtreeWatchesTask(this, path)); |
+ subtree_task->Run(); |
} else if (event->mask & IN_DELETE || event->mask & IN_MOVED_FROM) { |
- // TODO(phajdan.jr): remove our watch for this directory. |
- NOTIMPLEMENTED(); |
+ Singleton<InotifyReader>::get()->RemoveWatch(event->wd, this); |
+ |
+ WatchSet delete_us; |
+ AutoLock auto_lock(lock_); |
+ watches_.erase(event->wd); |
+ // Iterating on paths_ to find children wathces because inotify only fires |
+ // an event for the parent directory, when a directory subtree is deleted. |
+ for (base::hash_map<InotifyReader::Watch, InodeInfo>::const_iterator it = |
+ watches_.begin(); |
+ it != watches_.end(); |
+ ++it) { |
+ if (it->second.second.value().compare(0, path.value().length(), |
+ path.value())) |
+ continue; |
+ delete_us.insert(it->first); |
+ Singleton<InotifyReader>::get()->RemoveWatch(it->first, this); |
+ } |
+ for (WatchSet::const_iterator it = delete_us.begin(); |
+ it != delete_us.end(); ++it) { |
+ watches_.erase(*it); |
+ } |
} |
} |
bool DirectoryWatcherImpl::IsInodeWatched(ino_t inode) const { |
- return inodes_watched_.find(inode) != inodes_watched_.end(); |
+ for (base::hash_map<InotifyReader::Watch, InodeInfo>::const_iterator it = |
+ watches_.begin(); |
+ it != watches_.end(); |
+ ++it) { |
+ if (it->second.first == inode) |
+ return true; |
+ } |
+ return false; |
} |
bool DirectoryWatcherImpl::OnEnumeratedSubtree(const FilePathSet& subtree) { |
@@ -395,10 +433,8 @@ |
recursive_setup_finished_.Signal(); |
return false; |
} |
- |
bool success = true; |
- AutoLock auto_lock(lock_); |
- for (FilePathSet::iterator subdirectory = subtree.begin(); |
+ for (FilePathSet::const_iterator subdirectory = subtree.begin(); |
subdirectory != subtree.end(); |
++subdirectory) { |
ino_t inode; |
@@ -411,8 +447,10 @@ |
InotifyReader::Watch watch = |
Singleton<InotifyReader>::get()->AddWatch(*subdirectory, this); |
if (watch != InotifyReader::kInvalidWatch) { |
- watches_.insert(watch); |
- inodes_watched_.insert(inode); |
+ { |
+ AutoLock auto_lock(lock_); |
+ watches_[watch] = std::make_pair(inode, *subdirectory); |
+ } |
} |
} |
recursive_setup_finished_.Signal(); |
@@ -422,7 +460,6 @@ |
bool DirectoryWatcherImpl::Watch(const FilePath& path, |
DirectoryWatcher::Delegate* delegate, |
MessageLoop* backend_loop, bool recursive) { |
- |
// Can only watch one path. |
DCHECK(watch_ == InotifyReader::kInvalidWatch); |
@@ -443,8 +480,7 @@ |
{ |
AutoLock auto_lock(lock_); |
- inodes_watched_.insert(inode); |
- watches_.insert(watch_); |
+ watches_[watch_] = std::make_pair(inode, root_path_); |
} |
if (recursive_) { |