| 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_) {
|
|
|