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

Unified Diff: base/directory_watcher_inotify.cc

Issue 52005: Implement recursive DirectoryWatcher watches on Linux (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 11 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/directory_watcher_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_) {
« no previous file with comments | « no previous file | base/directory_watcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698