Implement DirectoryWatcher.
This commit is contained in:
parent
12daa5c575
commit
568ccb7127
|
@ -319,8 +319,7 @@ int delegate(scope int delegate(ref FileInfo)) iterateDirectory(string path)
|
|||
*/
|
||||
DirectoryWatcher watchDirectory(Path path, bool recursive = true)
|
||||
{
|
||||
assert(false);
|
||||
//return eventDriver.watchDirectory(path, recursive);
|
||||
return DirectoryWatcher(path, recursive);
|
||||
}
|
||||
// ditto
|
||||
DirectoryWatcher watchDirectory(string path, bool recursive = true)
|
||||
|
@ -520,12 +519,40 @@ private void writeDefault(OutputStream, InputStream)(ref OutputStream dst, Input
|
|||
Directory watchers monitor the contents of a directory (wither recursively or non-recursively)
|
||||
for changes, such as file additions, deletions or modifications.
|
||||
*/
|
||||
interface DirectoryWatcher {
|
||||
struct DirectoryWatcher { // TODO: avoid all those heap allocations!
|
||||
import std.array : Appender, appender;
|
||||
import vibe.core.sync : ManualEvent;
|
||||
|
||||
@safe:
|
||||
|
||||
private struct Context {
|
||||
Path path;
|
||||
bool recursive;
|
||||
Appender!(DirectoryChange[]) changes;
|
||||
ManualEvent changeEvent;
|
||||
}
|
||||
|
||||
private {
|
||||
WatcherID m_watcher;
|
||||
Context m_context;
|
||||
}
|
||||
|
||||
private this(Path path, bool recursive)
|
||||
{
|
||||
m_watcher = eventDriver.watchers.watchDirectory(path.toNativeString, recursive, &onChange);
|
||||
m_context.path = path;
|
||||
m_context.recursive = recursive;
|
||||
m_context.changes = appender!(DirectoryChange[]);
|
||||
}
|
||||
|
||||
this(this) nothrow { if (m_watcher != WatcherID.invalid) eventDriver.watchers.addRef(m_watcher); }
|
||||
~this() nothrow { if (m_watcher != WatcherID.invalid) eventDriver.watchers.releaseRef(m_watcher); }
|
||||
|
||||
/// The path of the watched directory
|
||||
@property Path path() const;
|
||||
@property Path path() const nothrow { return m_context.path; }
|
||||
|
||||
/// Indicates if the directory is watched recursively
|
||||
@property bool recursive() const;
|
||||
@property bool recursive() const nothrow { return m_context.recursive; }
|
||||
|
||||
/** Fills the destination array with all changes that occurred since the last call.
|
||||
|
||||
|
@ -535,12 +562,39 @@ interface DirectoryWatcher {
|
|||
|
||||
Params:
|
||||
dst = The destination array to which the changes will be appended
|
||||
timeout = Optional timeout for the read operation
|
||||
timeout = Optional timeout for the read operation. A value of
|
||||
`Duration.max` will wait indefinitely.
|
||||
|
||||
Returns:
|
||||
If the call completed successfully, true is returned.
|
||||
*/
|
||||
bool readChanges(ref DirectoryChange[] dst, Duration timeout = dur!"seconds"(-1));
|
||||
bool readChanges(ref DirectoryChange[] dst, Duration timeout = Duration.max)
|
||||
{
|
||||
SysTime now = Clock.currTime(UTC());
|
||||
SysTime final_time = now + timeout;
|
||||
while (!m_context.changes.data.length) {
|
||||
m_context.changeEvent.wait(final_time - now, m_context.changeEvent.emitCount);
|
||||
if (m_context.changes.data.length) break;
|
||||
else now = Clock.currTime(UTC());
|
||||
}
|
||||
|
||||
if (!m_context.changes.data.length) return false;
|
||||
dst = m_context.changes.data;
|
||||
m_context.changes = appender!(DirectoryChange[]);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onChange(WatcherID, in ref FileChange change)
|
||||
nothrow {
|
||||
DirectoryChangeType ct;
|
||||
final switch (change.kind) {
|
||||
case FileChangeKind.added: ct = DirectoryChangeType.added; break;
|
||||
case FileChangeKind.removed: ct = DirectoryChangeType.removed; break;
|
||||
case FileChangeKind.modified: ct = DirectoryChangeType.modified; break;
|
||||
}
|
||||
m_context.changes ~= DirectoryChange(ct, Path(change.directory) ~ change.name.idup);
|
||||
m_context.changeEvent.emit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue