-
Notifications
You must be signed in to change notification settings - Fork 73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
File system watcher #20
Conversation
… FS (not relevant, yet)
I guess we should also support some more events like changing file permissions or renaming files |
ref #3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some questions mainly about the windows backend.
if (!hEvent) | ||
throw std::runtime_error("failed creating wait event"); | ||
|
||
auto lw = std::make_shared<LocalWatcher>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the shared pointers here ever shared between several objects, or are they unique? (seems to me that way). Maybe we can use unique_ptr, or even just plain handles?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shared_ptr is used because you can specify the delete functions for the object, which in case of Windows HANDLE is the ::CloseHandle function. Out of pure convenience, and to avoid dangling handles.
NULL); | ||
if (ret != 0) { | ||
std::string fname(fileName, fileName + ret); | ||
std::replace(fname.begin(), fname.end(), '\\', '/'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to convert path delimiters, FilePath already takes care of that
|
||
protected: | ||
std::shared_ptr<LocalFileSystem> m_fs; ///< File system that created this watcher | ||
std::shared_ptr<void> m_waitStopEvent; ///< Event to stop watch function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are not shared in any way, so it should be unique_ptr instead of shared_ptr. But also that smart pointer does not do anything, the handle has been released by specific API-functions anyway, so I would suggest to just use void* here.
if (event->mask & IN_CREATE) eventType = FileCreated; | ||
else if (event->mask & IN_DELETE) eventType = FileRemoved; | ||
else if (event->mask & IN_MODIFY) eventType = FileModified; | ||
else if (event->mask & IN_ATTRIB) eventType = FileModified; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add a new type FileAttribChanged instead of implicitly merging them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea.
uint32_t flags = 0; | ||
if (events & FileCreated) flags |= IN_CREATE; | ||
if (events & FileRemoved) flags |= IN_DELETE; | ||
if (events & FileModified) flags |= (IN_MODIFY | IN_ATTRIB); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add a new type FileAttribChanged instead of implicitly merging them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
* This class is used for file systems that do not support | ||
* file system watchers, such as remote file systems. | ||
*/ | ||
class CPPFS_API NullFileWatcher : public AbstractFileWatcherBackend |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do like the null object pattern.
However, I have the impression that our remaining code base uses nullptr
in similiar cases.
Does using this pattern simplify our code base?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used it in some of my older projects with the private implementation pattern (which we also use here). It makes it simpler because one can just assume that the implementation object is always valid and doesn't have to check it in each function. But you're right, we're checking m_backend in all functions to far, so maybe we should stick to that pattern (use nullptr instead of null-implementation)
|
||
AbstractFileWatcherBackend::AbstractFileWatcherBackend(FileWatcher * fileWatcher) | ||
: m_fileWatcher(fileWatcher) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation states that m_fileWatcher
may never be nullptr
.
I suggest to add the corresponding assertion here.
* @brief | ||
* Watcher entry | ||
*/ | ||
struct Watcher { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to reorder the members?
I suggest from large to small.
For this case, this may result in something like this:
struct Watcher {
std::shared_ptr<void> handle;
std::shared_ptr<void> platform;
FileHandle fileHandle;
RecursiveMode recursive;
unsigned int events;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rationale: hopefully reduce object size. Probably we should measure this properly. Using the attribute packed
may be another option.
uint32_t flags = 0; | ||
if (events & FileCreated) flags |= IN_CREATE; | ||
if (events & FileRemoved) flags |= IN_DELETE; | ||
if (events & FileModified) flags |= (IN_MODIFY | IN_ATTRIB); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
…ystem, remove configuration option for remote login
… flag (off by default)
deleting of directories
This is our first take on implementing a file system watcher interface. It can be merged as soon as the Windows implementation of LocalFileWatcher has been implemented.
Missing features, nice-to-have: