Commit 0bd449fb authored by Ge Jun's avatar Ge Jun

Remove code for unused FilePathWatcher and fix a warning under gcc 7.3

parent 94e89087
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This module provides a way to monitor a file or directory for changes.
#ifndef BUTIL_FILES_FILE_PATH_WATCHER_H_
#define BUTIL_FILES_FILE_PATH_WATCHER_H_
#include "butil/base_export.h"
#include "butil/basictypes.h"
#include "butil/callback.h"
#include "butil/files/file_path.h"
#include "butil/memory/ref_counted.h"
#include "butil/message_loop/message_loop_proxy.h"
namespace butil {
// This class lets you register interest in changes on a FilePath.
// The callback will get called whenever the file or directory referenced by the
// FilePath is changed, including created or deleted. Due to limitations in the
// underlying OS APIs, FilePathWatcher has slightly different semantics on OS X
// than on Windows or Linux. FilePathWatcher on Linux and Windows will detect
// modifications to files in a watched directory. FilePathWatcher on Mac will
// detect the creation and deletion of files in a watched directory, but will
// not detect modifications to those files. See file_path_watcher_kqueue.cc for
// details.
class BUTIL_EXPORT FilePathWatcher {
public:
// Callback type for Watch(). |path| points to the file that was updated,
// and |error| is true if the platform specific code detected an error. In
// that case, the callback won't be invoked again.
typedef butil::Callback<void(const FilePath& path, bool error)> Callback;
// Used internally to encapsulate different members on different platforms.
class PlatformDelegate : public butil::RefCountedThreadSafe<PlatformDelegate> {
public:
PlatformDelegate();
// Start watching for the given |path| and notify |delegate| about changes.
virtual bool Watch(const FilePath& path,
bool recursive,
const Callback& callback) WARN_UNUSED_RESULT = 0;
// Stop watching. This is called from FilePathWatcher's dtor in order to
// allow to shut down properly while the object is still alive.
// It can be called from any thread.
virtual void Cancel() = 0;
protected:
friend class butil::RefCountedThreadSafe<PlatformDelegate>;
friend class FilePathWatcher;
virtual ~PlatformDelegate();
// Stop watching. This is only called on the thread of the appropriate
// message loop. Since it can also be called more than once, it should
// check |is_cancelled()| to avoid duplicate work.
virtual void CancelOnMessageLoopThread() = 0;
scoped_refptr<butil::MessageLoopProxy> message_loop() const {
return message_loop_;
}
void set_message_loop(butil::MessageLoopProxy* loop) {
message_loop_ = loop;
}
// Must be called before the PlatformDelegate is deleted.
void set_cancelled() {
cancelled_ = true;
}
bool is_cancelled() const {
return cancelled_;
}
private:
scoped_refptr<butil::MessageLoopProxy> message_loop_;
bool cancelled_;
};
FilePathWatcher();
virtual ~FilePathWatcher();
// A callback that always cleans up the PlatformDelegate, either when executed
// or when deleted without having been executed at all, as can happen during
// shutdown.
static void CancelWatch(const scoped_refptr<PlatformDelegate>& delegate);
// Returns true if the platform and OS version support recursive watches.
static bool RecursiveWatchAvailable();
// Invokes |callback| whenever updates to |path| are detected. This should be
// called at most once, and from a MessageLoop of TYPE_IO. Set |recursive| to
// true, to watch |path| and its children. The callback will be invoked on
// the same loop. Returns true on success.
//
// Recursive watch is not supported on all platforms and file systems.
// Watch() will return false in the case of failure.
bool Watch(const FilePath& path, bool recursive, const Callback& callback);
private:
scoped_refptr<PlatformDelegate> impl_;
DISALLOW_COPY_AND_ASSIGN(FilePathWatcher);
};
} // namespace butil
#endif // BUTIL_FILES_FILE_PATH_WATCHER_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BUTIL_FILES_FILE_PATH_WATCHER_FSEVENTS_H_
#define BUTIL_FILES_FILE_PATH_WATCHER_FSEVENTS_H_
#include <CoreServices/CoreServices.h>
#include <vector>
#include "butil/files/file_path.h"
#include "butil/files/file_path_watcher.h"
namespace butil {
// Mac-specific file watcher implementation based on FSEvents.
// There are trade-offs between the FSEvents implementation and a kqueue
// implementation. The biggest issues are that FSEvents on 10.6 sometimes drops
// events and kqueue does not trigger for modifications to a file in a watched
// directory. See file_path_watcher_mac.cc for the code that decides when to
// use which one.
class FilePathWatcherFSEvents : public FilePathWatcher::PlatformDelegate {
public:
FilePathWatcherFSEvents();
// Called from the FSEvents callback whenever there is a change to the paths.
void OnFilePathsChanged(const std::vector<FilePath>& paths);
// (Re-)Initialize the event stream to start reporting events from
// |start_event|.
void UpdateEventStream(FSEventStreamEventId start_event);
// Returns true if resolving the target path got a different result than
// last time it was done.
bool ResolveTargetPath();
// FilePathWatcher::PlatformDelegate overrides.
virtual bool Watch(const FilePath& path,
bool recursive,
const FilePathWatcher::Callback& callback) OVERRIDE;
virtual void Cancel() OVERRIDE;
private:
virtual ~FilePathWatcherFSEvents();
// Destroy the event stream.
void DestroyEventStream();
// Start watching the FSEventStream.
void StartEventStream(FSEventStreamEventId start_event);
// Cleans up and stops the event stream.
virtual void CancelOnMessageLoopThread() OVERRIDE;
// Callback to notify upon changes.
FilePathWatcher::Callback callback_;
// Target path to watch (passed to callback).
FilePath target_;
// Target path with all symbolic links resolved.
FilePath resolved_target_;
// Backend stream we receive event callbacks from (strong reference).
FSEventStreamRef fsevent_stream_;
DISALLOW_COPY_AND_ASSIGN(FilePathWatcherFSEvents);
};
} // namespace butil
#endif // BUTIL_FILES_FILE_PATH_WATCHER_FSEVENTS_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BUTIL_FILES_FILE_PATH_WATCHER_KQUEUE_H_
#define BUTIL_FILES_FILE_PATH_WATCHER_KQUEUE_H_
#include <sys/event.h>
#include <vector>
#include "butil/files/file_path.h"
#include "butil/files/file_path_watcher.h"
#include "butil/message_loop/message_loop.h"
#include "butil/message_loop/message_loop_proxy.h"
namespace butil {
// Mac-specific file watcher implementation based on kqueue.
// The Linux and Windows versions are able to detect:
// - file creation/deletion/modification in a watched directory
// - file creation/deletion/modification for a watched file
// - modifications to the paths to a watched object that would affect the
// object such as renaming/attibute changes etc.
// The kqueue implementation will handle all of the items in the list above
// except for detecting modifications to files in a watched directory. It will
// detect the creation and deletion of files, just not the modification of
// files. It does however detect the attribute changes that the FSEvents impl
// would miss.
class FilePathWatcherKQueue : public FilePathWatcher::PlatformDelegate,
public MessageLoopForIO::Watcher,
public MessageLoop::DestructionObserver {
public:
FilePathWatcherKQueue();
// MessageLoopForIO::Watcher overrides.
virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;
// MessageLoop::DestructionObserver overrides.
virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
// FilePathWatcher::PlatformDelegate overrides.
virtual bool Watch(const FilePath& path,
bool recursive,
const FilePathWatcher::Callback& callback) OVERRIDE;
virtual void Cancel() OVERRIDE;
protected:
virtual ~FilePathWatcherKQueue();
private:
class EventData {
public:
EventData(const FilePath& path, const FilePath::StringType& subdir)
: path_(path), subdir_(subdir) { }
FilePath path_; // Full path to this item.
FilePath::StringType subdir_; // Path to any sub item.
};
typedef std::vector<struct kevent> EventVector;
// Can only be called on |io_message_loop_|'s thread.
virtual void CancelOnMessageLoopThread() OVERRIDE;
// Returns true if the kevent values are error free.
bool AreKeventValuesValid(struct kevent* kevents, int count);
// Respond to a change of attributes of the path component represented by
// |event|. Sets |target_file_affected| to true if |target_| is affected.
// Sets |update_watches| to true if |events_| need to be updated.
void HandleAttributesChange(const EventVector::iterator& event,
bool* target_file_affected,
bool* update_watches);
// Respond to a move or deletion of the path component represented by
// |event|. Sets |target_file_affected| to true if |target_| is affected.
// Sets |update_watches| to true if |events_| need to be updated.
void HandleDeleteOrMoveChange(const EventVector::iterator& event,
bool* target_file_affected,
bool* update_watches);
// Respond to a creation of an item in the path component represented by
// |event|. Sets |target_file_affected| to true if |target_| is affected.
// Sets |update_watches| to true if |events_| need to be updated.
void HandleCreateItemChange(const EventVector::iterator& event,
bool* target_file_affected,
bool* update_watches);
// Update |events_| with the current status of the system.
// Sets |target_file_affected| to true if |target_| is affected.
// Returns false if an error occurs.
bool UpdateWatches(bool* target_file_affected);
// Fills |events| with one kevent per component in |path|.
// Returns the number of valid events created where a valid event is
// defined as one that has a ident (file descriptor) field != -1.
static int EventsForPath(FilePath path, EventVector *events);
// Release a kevent generated by EventsForPath.
static void ReleaseEvent(struct kevent& event);
// Returns a file descriptor that will not block the system from deleting
// the file it references.
static uintptr_t FileDescriptorForPath(const FilePath& path);
static const uintptr_t kNoFileDescriptor = static_cast<uintptr_t>(-1);
// Closes |*fd| and sets |*fd| to -1.
static void CloseFileDescriptor(uintptr_t* fd);
// Returns true if kevent has open file descriptor.
static bool IsKeventFileDescriptorOpen(const struct kevent& event) {
return event.ident != kNoFileDescriptor;
}
static EventData* EventDataForKevent(const struct kevent& event) {
return reinterpret_cast<EventData*>(event.udata);
}
EventVector events_;
scoped_refptr<butil::MessageLoopProxy> io_message_loop_;
MessageLoopForIO::FileDescriptorWatcher kqueue_watcher_;
FilePathWatcher::Callback callback_;
FilePath target_;
int kqueue_;
DISALLOW_COPY_AND_ASSIGN(FilePathWatcherKQueue);
};
} // namespace butil
#endif // BUTIL_FILES_FILE_PATH_WATCHER_KQUEUE_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "butil/files/file_path_watcher.h"
#include "butil/files/file_path_watcher_kqueue.h"
#if !defined(OS_IOS)
#include "butil/files/file_path_watcher_fsevents.h"
#endif
namespace butil {
namespace {
class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate {
public:
virtual bool Watch(const FilePath& path,
bool recursive,
const FilePathWatcher::Callback& callback) OVERRIDE {
// Use kqueue for non-recursive watches and FSEvents for recursive ones.
DCHECK(!impl_.get());
if (recursive) {
if (!FilePathWatcher::RecursiveWatchAvailable())
return false;
#if !defined(OS_IOS)
impl_ = new FilePathWatcherFSEvents();
#endif // OS_IOS
} else {
impl_ = new FilePathWatcherKQueue();
}
DCHECK(impl_.get());
return impl_->Watch(path, recursive, callback);
}
virtual void Cancel() OVERRIDE {
if (impl_)
impl_->Cancel();
set_cancelled();
}
virtual void CancelOnMessageLoopThread() OVERRIDE {
if (impl_)
impl_->Cancel();
set_cancelled();
}
protected:
virtual ~FilePathWatcherImpl() {}
scoped_refptr<PlatformDelegate> impl_;
};
} // namespace
FilePathWatcher::FilePathWatcher() {
impl_ = new FilePathWatcherImpl();
}
} // namespace butil
...@@ -56,9 +56,10 @@ TEST(VersionTest, GetVersionFromString) { ...@@ -56,9 +56,10 @@ TEST(VersionTest, GetVersionFromString) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
Version version(cases[i].input); Version version(cases[i].input);
EXPECT_EQ(cases[i].success, version.IsValid()); EXPECT_EQ(cases[i].success, version.IsValid());
if (cases[i].success) if (cases[i].success) {
EXPECT_EQ(cases[i].parts, version.components().size()); EXPECT_EQ(cases[i].parts, version.components().size());
} }
}
} }
TEST(VersionTest, Compare) { TEST(VersionTest, Compare) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment