Пример #1
0
void FileSystemWatcher::pathsRemoved(const Set<Path>& paths)
{
    for (const Path& path : paths) {
        //printf("really removed %s\n", path.constData());
        mRemoved(path);
    }
}
Пример #2
0
void FileSystemWatcher::pathsRemoved(const Set<Path>& paths)
{
    for (const Path& path : paths) {
        mRemoved(path);
    }
}
Пример #3
0
void FileSystemWatcher::notifyReadyRead()
{
    FSUserData data;
    {
        enum { MaxEvents = 5 };
        struct kevent events[MaxEvents];
        struct timespec nullts = { 0, 0 };
        int ret;
        for (;;) {
            ret = ::kevent(mFd, 0, 0, events, MaxEvents, &nullts);
            if (ret == 0) {
                break;
            } else if (ret == -1) {
                error("FileSystemWatcher::notifyReadyRead() kevent failed (%d) %s",
                      errno, Rct::strerror().constData());
                break;
            }
            assert(ret > 0 && ret <= MaxEvents);
            for (int i = 0; i < ret; ++i) {
                std::unique_lock<std::mutex> lock(mMutex);
                const struct kevent& event = events[i];
                const Path p = mWatchedById.value(event.ident);
                if (event.flags & EV_ERROR) {
                    error("FileSystemWatcher::notifyReadyRead() kevent element failed for '%s' (%ld) %s",
                          p.constData(), event.data, Rct::strerror(event.data).constData());
                    continue;
                }
                if (p.isEmpty()) {
                    warning() << "FileSystemWatcher::notifyReadyRead() We don't seem to be watching " << p;
                    continue;
                }
                if (event.fflags & (NOTE_DELETE|NOTE_REVOKE|NOTE_RENAME)) {
                    // our path has been removed
                    const int wd = event.ident;
                    mWatchedById.remove(wd);
                    mWatchedByPath.remove(p);

                    data.all.clear();
                    Map<Path, uint64_t>::iterator it = mTimes.lower_bound(p);
                    while (it != mTimes.end() && it->first.startsWith(p)) {
                        data.all.insert(it->first);
                        mTimes.erase(it++);
                    }

                    struct kevent change;
                    struct timespec nullts = { 0, 0 };
                    EV_SET(&change, wd, EVFILT_VNODE, EV_DELETE, 0, 0, 0);
                    ::kevent(mFd, &change, 1, 0, 0, &nullts);
                    ::close(wd);
                } else if (p.exists()) {
                    // Figure out what has been changed
                    data.watcher = this;
                    data.added.clear();
                    data.modified.clear();
                    data.all.clear();
                    Map<Path, uint64_t>::iterator it = mTimes.lower_bound(p);
                    while (it != mTimes.end() && it->first.startsWith(p)) {
                        data.all.insert(it->first);
                        ++it;
                    }
                    //printf("before updateFiles, path %s, all %d\n", p.nullTerminated(), data.all.size());
                    p.visit([&data](const Path &p) {
                            return updateFiles(p, &data);
                            });
                    //printf("after updateFiles, added %d, modified %d, removed %d\n",
                    //       data.added.size(), data.modified.size(), data.all.size());

                    lock.unlock();
                    struct {
                        Signal<std::function<void(const Path&)> > &signal;
                        const Set<Path> &paths;
                    } signals[] = {
                        { mModified, data.modified },
                        { mAdded, data.added }
                    };
                    const unsigned int count = sizeof(signals) / sizeof(signals[0]);
                    for (unsigned i=0; i<count; ++i) {
                        for (Set<Path>::const_iterator it = signals[i].paths.begin(); it != signals[i].paths.end(); ++it) {
                            signals[i].signal(*it);
                        }
                    }
                }

                if (lock.owns_lock())
                    lock.unlock();
                for (Set<Path>::const_iterator it = data.all.begin(); it != data.all.end(); ++it) {
                    mRemoved(*it);
                }
            }
        }
    }
}