forked from openkylin/ukui-search
Add file system watcher(Encapsulate inotify).
This commit is contained in:
parent
e0aac07c9b
commit
ad3d677aa8
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022, KylinSoft Co., Ltd.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: iaom <zhangpengfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef FILESYSTEMWATCHERPRIVATE_H
|
||||||
|
#define FILESYSTEMWATCHERPRIVATE_H
|
||||||
|
|
||||||
|
#endif // FILESYSTEMWATCHERPRIVATE_H
|
||||||
|
#include "file-system-watcher.h"
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QSocketNotifier>
|
||||||
|
#include <QThreadPool>
|
||||||
|
|
||||||
|
#include "traverse-bfs.h"
|
||||||
|
|
||||||
|
namespace UkuiSearch {
|
||||||
|
class FileSystemWatcherPrivate
|
||||||
|
{
|
||||||
|
friend class FileSystemWatcher;
|
||||||
|
public:
|
||||||
|
FileSystemWatcherPrivate(FileSystemWatcher *parent);
|
||||||
|
~FileSystemWatcherPrivate();
|
||||||
|
|
||||||
|
void addWatch(const QStringList &pathList);
|
||||||
|
QStringList removeWatch(const QString &path);
|
||||||
|
QString removeWatch(int wd);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
|
void traverse(QStringList pathList);
|
||||||
|
void addWatch(const QString &path);
|
||||||
|
|
||||||
|
FileSystemWatcher::WatchEvents m_watchEvents;
|
||||||
|
FileSystemWatcher::WatchFlags m_watchFlags;
|
||||||
|
|
||||||
|
int m_inotifyFd = -1;
|
||||||
|
QSocketNotifier* m_notifier = nullptr;
|
||||||
|
// wd -> url
|
||||||
|
QHash<int, QString> m_watchPathHash;
|
||||||
|
|
||||||
|
QThreadPool *m_pool = nullptr;
|
||||||
|
FileSystemWatcher *q = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,304 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022, KylinSoft Co., Ltd.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: iaom <zhangpengfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "file-system-watcher-private.h"
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QQueue>
|
||||||
|
#include <QtConcurrentRun>
|
||||||
|
|
||||||
|
#include "ukui-search-qdbus.h"
|
||||||
|
#include "file-utils.h"
|
||||||
|
using namespace UkuiSearch;
|
||||||
|
|
||||||
|
FileSystemWatcherPrivate::FileSystemWatcherPrivate(FileSystemWatcher *parent) : q(parent)
|
||||||
|
{
|
||||||
|
qDebug() << "setInotifyMaxUserWatches start";
|
||||||
|
UkuiSearchQDBus usQDBus;
|
||||||
|
usQDBus.setInotifyMaxUserWatches();
|
||||||
|
qDebug() << "setInotifyMaxUserWatches end";
|
||||||
|
|
||||||
|
init();
|
||||||
|
m_pool = new QThreadPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileSystemWatcherPrivate::~FileSystemWatcherPrivate()
|
||||||
|
{
|
||||||
|
if(m_notifier) {
|
||||||
|
delete m_notifier;
|
||||||
|
m_notifier = nullptr;
|
||||||
|
}
|
||||||
|
if(m_pool) {
|
||||||
|
delete m_pool;
|
||||||
|
m_pool = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSystemWatcherPrivate::traverse(QStringList pathList)
|
||||||
|
{
|
||||||
|
QQueue<QString> queue;
|
||||||
|
for(QString path : pathList) {
|
||||||
|
addWatch(path);
|
||||||
|
queue.enqueue(path);
|
||||||
|
}
|
||||||
|
QFileInfoList list;
|
||||||
|
QDir dir;
|
||||||
|
dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
|
||||||
|
dir.setSorting(QDir::DirsFirst);
|
||||||
|
while(!queue.empty()) {
|
||||||
|
dir.setPath(queue.dequeue());
|
||||||
|
list = dir.entryInfoList();
|
||||||
|
for(auto i : list) {
|
||||||
|
if(i.isDir() && (!(i.isSymLink()))) {
|
||||||
|
queue.enqueue(i.absoluteFilePath());
|
||||||
|
addWatch(i.absoluteFilePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSystemWatcherPrivate::addWatch(const QString &path)
|
||||||
|
{
|
||||||
|
int wd = inotify_add_watch(m_inotifyFd, path.toStdString().c_str(), m_watchEvents | m_watchFlags);
|
||||||
|
if(wd > 0) {
|
||||||
|
m_watchPathHash[wd] = path;
|
||||||
|
} else {
|
||||||
|
qWarning() << "AddWatch error:" << path << strerror(errno);
|
||||||
|
if (errno == ENOSPC) {
|
||||||
|
qWarning() << "User limit reached. Count: " << m_watchPathHash.count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSystemWatcherPrivate::addWatch(const QStringList &pathList)
|
||||||
|
{
|
||||||
|
QtConcurrent::run(m_pool, [ = ](){
|
||||||
|
traverse(pathList);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList FileSystemWatcherPrivate::removeWatch(const QString &path)
|
||||||
|
{
|
||||||
|
m_pool->waitForDone();
|
||||||
|
QStringList paths;
|
||||||
|
for(QHash<int, QString>::Iterator i = m_watchPathHash.begin(); i != m_watchPathHash.end();) {
|
||||||
|
if(i.value().length() > path.length()) {
|
||||||
|
if(FileUtils::isOrUnder(i.value(), path)) {
|
||||||
|
//fix me:This function can be slow (O(n))
|
||||||
|
paths.append(removeWatch(m_watchPathHash.key(path)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileSystemWatcherPrivate::removeWatch(int wd)
|
||||||
|
{
|
||||||
|
inotify_rm_watch(m_inotifyFd, wd);
|
||||||
|
return m_watchPathHash.take(wd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSystemWatcherPrivate::init()
|
||||||
|
{
|
||||||
|
if(m_inotifyFd < 0) {
|
||||||
|
m_inotifyFd = inotify_init();
|
||||||
|
|
||||||
|
if (m_inotifyFd > 0) {
|
||||||
|
qDebug()<<"Inotify init success!";
|
||||||
|
} else {
|
||||||
|
qWarning() << "Inotify init fail! Now try add inotify_user_instances.";
|
||||||
|
UkuiSearchQDBus usQDBus;
|
||||||
|
usQDBus.addInotifyUserInstances(128);
|
||||||
|
m_inotifyFd = inotify_init();
|
||||||
|
if (m_inotifyFd > 0) {
|
||||||
|
qDebug()<<"Inotify init success!";
|
||||||
|
} else {
|
||||||
|
printf("errno=%d\n",errno);
|
||||||
|
printf("Mesg:%s\n",strerror(errno));
|
||||||
|
Q_ASSERT_X(0, "InotifyWatch", "Failed to initialize inotify");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fcntl(m_inotifyFd, F_SETFD, FD_CLOEXEC);
|
||||||
|
m_notifier = new QSocketNotifier(m_inotifyFd, QSocketNotifier::Read);
|
||||||
|
QObject::connect(m_notifier, &QSocketNotifier::activated, q, &FileSystemWatcher::eventProcess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileSystemWatcher::FileSystemWatcher(WatchEvents events, WatchFlags flags, QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, d(new FileSystemWatcherPrivate(this))
|
||||||
|
{
|
||||||
|
d->m_watchEvents = events;
|
||||||
|
d->m_watchFlags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileSystemWatcher::~FileSystemWatcher()
|
||||||
|
{
|
||||||
|
if(d) {
|
||||||
|
delete d;
|
||||||
|
d = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSystemWatcher::addWatch(const QStringList &pathList)
|
||||||
|
{
|
||||||
|
d->addWatch(pathList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSystemWatcher::addWatch(const QString &path)
|
||||||
|
{
|
||||||
|
d->addWatch(QStringList(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList FileSystemWatcher::removeWatch(const QString &path)
|
||||||
|
{
|
||||||
|
return d->removeWatch(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSystemWatcher::eventProcess(int socket)
|
||||||
|
{
|
||||||
|
qDebug() << "-----begin event process-----";
|
||||||
|
int avail;
|
||||||
|
if (ioctl(socket, FIONREAD, &avail) == EINVAL) {
|
||||||
|
qWarning() << "Did not receive an entire inotify event.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* buf = (char*)malloc(avail);
|
||||||
|
memset(buf, 0x00, avail);
|
||||||
|
|
||||||
|
const ssize_t len = read(socket, buf, avail);
|
||||||
|
|
||||||
|
if(len != avail) {
|
||||||
|
qWarning()<<"read event error";
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (i < len) {
|
||||||
|
const struct inotify_event* event = (struct inotify_event*)&buf[i];
|
||||||
|
|
||||||
|
if(event->name[0] == '.') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (event->wd < 0 && (event->mask & EventQueueOverflow)) {
|
||||||
|
qWarning() << "Inotify Event queued overflowed";
|
||||||
|
free(buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "event mask:" << event->mask;
|
||||||
|
QString path;
|
||||||
|
|
||||||
|
if (event->mask & (EventDeleteSelf | EventMoveSelf)) {
|
||||||
|
path = d->m_watchPathHash.value(event->wd);
|
||||||
|
} else {
|
||||||
|
path = d->m_watchPathHash[event->wd] + '/' + event->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(event->mask & EventCreate) {
|
||||||
|
qDebug() << path << "--EventCreate";
|
||||||
|
Q_EMIT created(path, event->mask & IN_ISDIR);
|
||||||
|
if(event->mask & IN_ISDIR) {
|
||||||
|
if(!QFileInfo(path).isSymLink()){
|
||||||
|
addWatch(QStringList(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (event->mask & EventDeleteSelf) {
|
||||||
|
qDebug() << path << "--EventDeleteSelf";
|
||||||
|
d->removeWatch(event->wd);
|
||||||
|
Q_EMIT deleted(path, true);
|
||||||
|
}
|
||||||
|
if (event->mask & EventDelete) {
|
||||||
|
qDebug() << path << "--EventDelete";
|
||||||
|
// we watch all folders recursively. Thus, folder removing is reported in DeleteSelf.
|
||||||
|
if (!(event->mask & IN_ISDIR)) {
|
||||||
|
Q_EMIT deleted(path, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (event->mask & EventModify) {
|
||||||
|
qDebug() << path << "--EventModify";
|
||||||
|
Q_EMIT modified(path);
|
||||||
|
}
|
||||||
|
if (event->mask & EventMoveSelf) {
|
||||||
|
qDebug() << path << "--EventMoveSelf";
|
||||||
|
d->removeWatch(event->wd);
|
||||||
|
Q_EMIT moved(path, true);
|
||||||
|
}
|
||||||
|
if (event->mask & EventMoveFrom) {
|
||||||
|
qDebug() << path << "--EventMoveFrom";
|
||||||
|
if (!(event->mask & IN_ISDIR)) {
|
||||||
|
Q_EMIT moved(path, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (event->mask & EventMoveTo) {
|
||||||
|
qDebug() << path << "--EventMoveTo";
|
||||||
|
Q_EMIT created(path, event->mask & IN_ISDIR);
|
||||||
|
if (event->mask & IN_ISDIR) {
|
||||||
|
addWatch(QStringList(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (event->mask & EventOpen) {
|
||||||
|
qDebug() << path << "--EventOpen";
|
||||||
|
Q_EMIT opened(path);
|
||||||
|
}
|
||||||
|
if (event->mask & EventUnmount) {
|
||||||
|
qDebug() << path << "--EventUnmount";
|
||||||
|
if (event->mask & IN_ISDIR) {
|
||||||
|
d->removeWatch(event->wd);
|
||||||
|
}
|
||||||
|
// This is present because a unmount event is sent by inotify after unmounting, by
|
||||||
|
// which time the watches have already been removed.
|
||||||
|
if (path != "/") {
|
||||||
|
Q_EMIT unmounted(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (event->mask & EventAttributeChange) {
|
||||||
|
qDebug() << path << "--EventAttributeChange";
|
||||||
|
Q_EMIT attributeChanged(path);
|
||||||
|
}
|
||||||
|
if (event->mask & EventAccess) {
|
||||||
|
qDebug() << path << "--EventAccess";
|
||||||
|
Q_EMIT accessed(path);
|
||||||
|
}
|
||||||
|
if (event->mask & EventCloseWrite) {
|
||||||
|
qDebug() << path << "--EventCloseWrite";
|
||||||
|
Q_EMIT closedWrite(path);
|
||||||
|
}
|
||||||
|
if (event->mask & EventCloseRead) {
|
||||||
|
qDebug() << path << "--EventCloseRead";
|
||||||
|
Q_EMIT closedRead(path);
|
||||||
|
}
|
||||||
|
if (event->mask & EventIgnored) {
|
||||||
|
qDebug() << path << "--EventIgnored";
|
||||||
|
}
|
||||||
|
i += sizeof(struct inotify_event) + event->len;
|
||||||
|
}
|
||||||
|
if (len < 0) {
|
||||||
|
qWarning() << "Failed to read event.";
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
}
|
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022, KylinSoft Co., Ltd.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Authors: iaom <zhangpengfei@kylinos.cn>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef FILESYSTEMWATCHER_H
|
||||||
|
#define FILESYSTEMWATCHER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
namespace UkuiSearch {
|
||||||
|
class FileSystemWatcherPrivate;
|
||||||
|
class FileSystemWatcher : public QObject
|
||||||
|
{
|
||||||
|
friend class FileSystemWatcherPrivate;
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum WatchEvent {
|
||||||
|
EventAccess = 0x00000001, /**< File was accessed (read, compare inotify's IN_ACCESS) */
|
||||||
|
EventModify = 0x00000002, /**< File was modified (compare inotify's IN_MODIFY) */
|
||||||
|
EventAttributeChange = 0x00000004, /**< Metadata changed (permissions, timestamps, extended attributes, etc., compare inotify's IN_ATTRIB) */
|
||||||
|
EventCloseWrite = 0x00000008, /**< File opened for writing was closed (compare inotify's IN_CLOSE_WRITE) */
|
||||||
|
EventCloseRead = 0x00000010, /**< File not opened for writing was closed (compare inotify's IN_CLOSE_NOWRITE) */
|
||||||
|
EventClose = (EventCloseWrite | EventCloseRead),
|
||||||
|
EventOpen = 0x00000020, /**< File was opened (compare inotify's IN_OPEN) */
|
||||||
|
EventMoveFrom = 0x00000040, /**< File moved out of watched directory (compare inotify's IN_MOVED_FROM) */
|
||||||
|
EventMoveTo = 0x00000080, /**< File moved into watched directory (compare inotify's IN_MOVED_TO) */
|
||||||
|
EventMove = (EventMoveFrom | EventMoveTo),
|
||||||
|
EventCreate = 0x00000100, /** File/directory created in watched directory (compare inotify's IN_CREATE) */
|
||||||
|
EventDelete = 0x00000200, /**< File/directory deleted from watched directory (compare inotify's IN_DELETE) */
|
||||||
|
EventDeleteSelf = 0x00000400, /**< Watched file/directory was itself deleted (compare inotify's IN_DELETE_SELF) */
|
||||||
|
EventMoveSelf = 0x00000800, /**< Watched file/directory was itself moved (compare inotify's IN_MOVE_SELF) */
|
||||||
|
EventUnmount = 0x00002000, /**< Backing fs was unmounted (compare inotify's IN_UNMOUNT) */
|
||||||
|
EventQueueOverflow = 0x00004000, /**< Event queued overflowed (compare inotify's IN_Q_OVERFLOW) */
|
||||||
|
EventIgnored = 0x00008000, /**< File was ignored (compare inotify's IN_IGNORED) */
|
||||||
|
EventAll = (EventAccess |
|
||||||
|
EventAttributeChange |
|
||||||
|
EventCloseWrite |
|
||||||
|
EventCloseRead |
|
||||||
|
EventCreate |
|
||||||
|
EventDelete |
|
||||||
|
EventDeleteSelf |
|
||||||
|
EventModify |
|
||||||
|
EventMoveSelf |
|
||||||
|
EventMoveFrom |
|
||||||
|
EventMoveTo |
|
||||||
|
EventOpen),
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(WatchEvents, WatchEvent)
|
||||||
|
/**
|
||||||
|
* Watch flags
|
||||||
|
*
|
||||||
|
* These flags correspond to the native Linux inotify flags.
|
||||||
|
*/
|
||||||
|
enum WatchFlag {
|
||||||
|
FlagOnlyDir = 0x01000000, /**< Only watch the path if it is a directory (IN_ONLYDIR) */
|
||||||
|
FlagDoNotFollow = 0x02000000, /**< Don't follow a sym link (IN_DONT_FOLLOW) */
|
||||||
|
FlagOneShot = 0x80000000, /**< Only send event once (IN_ONESHOT) */
|
||||||
|
FlagExclUnlink = 0x04000000, /**< Do not generate events for unlinked files (IN_EXCL_UNLINK) */
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(WatchFlags, WatchFlag)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief FileSystemWatcher
|
||||||
|
* @param events Events that shoude be concerned,default: FileSystemWatcher::EventMove | FileSystemWatcher::EventMoveSelf |
|
||||||
|
FileSystemWatcher::EventCreate | FileSystemWatcher::EventDelete |
|
||||||
|
FileSystemWatcher::EventDeleteSelf | FileSystemWatcher::EventUnmount |
|
||||||
|
FileSystemWatcher::EventModify | FileSystemWatcher::EventAttributeChange
|
||||||
|
* @param flags Watch flags.
|
||||||
|
* @param parent
|
||||||
|
*/
|
||||||
|
explicit FileSystemWatcher(WatchEvents events = WatchEvents(FileSystemWatcher::EventMove | FileSystemWatcher::EventMoveSelf |
|
||||||
|
FileSystemWatcher::EventCreate | FileSystemWatcher::EventDelete |
|
||||||
|
FileSystemWatcher::EventDeleteSelf | FileSystemWatcher::EventUnmount |
|
||||||
|
FileSystemWatcher::EventModify),
|
||||||
|
WatchFlags flags = WatchFlags(),
|
||||||
|
QObject *parent = nullptr);
|
||||||
|
|
||||||
|
~FileSystemWatcher();
|
||||||
|
|
||||||
|
FileSystemWatcher(FileSystemWatcher &) = delete;
|
||||||
|
FileSystemWatcher &operator =(const FileSystemWatcher &) = delete;
|
||||||
|
|
||||||
|
bool isWatchingPath(const QString& path) const;
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void addWatch(const QStringList &pathList);
|
||||||
|
void addWatch(const QString &path);
|
||||||
|
QStringList removeWatch(const QString &path);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted if a file is accessed (FileSystemWatcher::EventAccess)
|
||||||
|
*/
|
||||||
|
void accessed(const QString& path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted if a watched file is modified (FileSystemWatcher::EventModify)
|
||||||
|
*/
|
||||||
|
void modified(const QString& path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted if file attributes are changed (FileSystemWatcher::EventAttributeChange)
|
||||||
|
*/
|
||||||
|
void attributeChanged(const QString& path);
|
||||||
|
|
||||||
|
void closedWrite(const QString& path);
|
||||||
|
|
||||||
|
void closedRead(const QString& path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted if a new file has been created in one of the watched
|
||||||
|
* folders (FileSystemWatcher::EventCreate)
|
||||||
|
*/
|
||||||
|
void created(const QString& path, bool isDir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted if a watched file or folder has been deleted.
|
||||||
|
* This includes files in watched folders (FileSystemWatcher::EventDelete and FileSystemWatcher::EventDeleteSelf)
|
||||||
|
*/
|
||||||
|
void deleted(const QString& path, bool isDir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted if a file or folder has been moved or renamed.
|
||||||
|
*/
|
||||||
|
void moved(const QString& path, bool isDir);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted if a file is opened (FileSystemWatcher::EventOpen)
|
||||||
|
*/
|
||||||
|
void opened(const QString& path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted if a watched path has been unmounted (FileSystemWatcher::EventUnmount)
|
||||||
|
*/
|
||||||
|
void unmounted(const QString& path);
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void eventProcess(int socket);
|
||||||
|
private:
|
||||||
|
|
||||||
|
FileSystemWatcherPrivate* d = nullptr;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // FILESYSTEMWATCHER_H
|
|
@ -0,0 +1,9 @@
|
||||||
|
INCLUDEPATH += $$PWD
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/file-system-watcher-private.h \
|
||||||
|
$$PWD/file-system-watcher.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/file-system-watcher.cpp
|
||||||
|
|
|
@ -36,13 +36,13 @@
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include "traverse_bfs.h"
|
#include "traverse-bfs.h"
|
||||||
#include "index-status-recorder.h"
|
#include "index-status-recorder.h"
|
||||||
#include "index-generator.h"
|
#include "index-generator.h"
|
||||||
#include "file-utils.h"
|
#include "file-utils.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
namespace UkuiSearch {
|
namespace UkuiSearch {
|
||||||
class FirstIndex : public QThread, public Traverse_BFS
|
class FirstIndex : public QThread, public TraverseBFS
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -14,7 +14,7 @@ HEADERS += \
|
||||||
$$PWD/pending-file.h \
|
$$PWD/pending-file.h \
|
||||||
$$PWD/search-manager.h \
|
$$PWD/search-manager.h \
|
||||||
$$PWD/file-index-manager.h \
|
$$PWD/file-index-manager.h \
|
||||||
$$PWD/traverse_bfs.h \
|
$$PWD/traverse-bfs.h \
|
||||||
$$PWD/ukui-search-qdbus.h
|
$$PWD/ukui-search-qdbus.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
@ -31,6 +31,6 @@ SOURCES += \
|
||||||
$$PWD/pending-file-queue.cpp \
|
$$PWD/pending-file-queue.cpp \
|
||||||
$$PWD/pending-file.cpp \
|
$$PWD/pending-file.cpp \
|
||||||
$$PWD/search-manager.cpp \
|
$$PWD/search-manager.cpp \
|
||||||
$$PWD/traverse_bfs.cpp \
|
$$PWD/traverse-bfs.cpp \
|
||||||
$$PWD/ukui-search-qdbus.cpp
|
$$PWD/ukui-search-qdbus.cpp
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ UkuiSearch::InotifyWatch *UkuiSearch::InotifyWatch::getInstance()
|
||||||
return global_instance_InotifyWatch;
|
return global_instance_InotifyWatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
UkuiSearch::InotifyWatch::InotifyWatch(): Traverse_BFS(), m_semaphore(INDEX_SEM, 0, QSystemSemaphore::AccessMode::Open)
|
UkuiSearch::InotifyWatch::InotifyWatch(): TraverseBFS(), m_semaphore(INDEX_SEM, 0, QSystemSemaphore::AccessMode::Open)
|
||||||
{
|
{
|
||||||
qDebug() << "setInotifyMaxUserWatches start";
|
qDebug() << "setInotifyMaxUserWatches start";
|
||||||
UkuiSearchQDBus usQDBus;
|
UkuiSearchQDBus usQDBus;
|
||||||
|
|
|
@ -13,14 +13,14 @@
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "traverse_bfs.h"
|
#include "traverse-bfs.h"
|
||||||
#include "ukui-search-qdbus.h"
|
#include "ukui-search-qdbus.h"
|
||||||
#include "index-status-recorder.h"
|
#include "index-status-recorder.h"
|
||||||
#include "file-utils.h"
|
#include "file-utils.h"
|
||||||
#include "pending-file-queue.h"
|
#include "pending-file-queue.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
namespace UkuiSearch {
|
namespace UkuiSearch {
|
||||||
class InotifyWatch : public QThread, public Traverse_BFS
|
class InotifyWatch : public QThread, public TraverseBFS
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -17,15 +17,15 @@
|
||||||
* Authors: zhangzihao <zhangzihao@kylinos.cn>
|
* Authors: zhangzihao <zhangzihao@kylinos.cn>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "traverse_bfs.h"
|
#include "traverse-bfs.h"
|
||||||
#include "file-utils.h"
|
#include "file-utils.h"
|
||||||
using namespace UkuiSearch;
|
using namespace UkuiSearch;
|
||||||
Traverse_BFS::Traverse_BFS(const QStringList &path) {
|
TraverseBFS::TraverseBFS(const QStringList &path) {
|
||||||
Q_ASSERT('/' == path.at(0));
|
Q_ASSERT('/' == path.at(0));
|
||||||
m_pathList = path;
|
m_pathList = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Traverse_BFS::Traverse() {
|
void TraverseBFS::Traverse() {
|
||||||
QQueue<QString> bfs;
|
QQueue<QString> bfs;
|
||||||
for(QString blockPath : m_blockList) {
|
for(QString blockPath : m_blockList) {
|
||||||
for(QString path : m_pathList) {
|
for(QString path : m_pathList) {
|
||||||
|
@ -68,11 +68,11 @@ void Traverse_BFS::Traverse() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Traverse_BFS::setPath(const QStringList &pathList) {
|
void TraverseBFS::setPath(const QStringList &pathList) {
|
||||||
m_pathList = pathList;
|
m_pathList = pathList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Traverse_BFS::setBlockPath(const QStringList &pathList)
|
void TraverseBFS::setBlockPath(const QStringList &pathList)
|
||||||
{
|
{
|
||||||
m_blockList =pathList;
|
m_blockList =pathList;
|
||||||
}
|
}
|
|
@ -25,21 +25,21 @@
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QQueue>
|
#include <QQueue>
|
||||||
namespace UkuiSearch {
|
namespace UkuiSearch {
|
||||||
class Traverse_BFS {
|
class TraverseBFS {
|
||||||
public:
|
public:
|
||||||
Traverse_BFS() = default;
|
TraverseBFS() = default;
|
||||||
void Traverse();
|
void Traverse();
|
||||||
virtual ~Traverse_BFS() = default;
|
virtual ~TraverseBFS() = default;
|
||||||
virtual void work(const QFileInfo&) = 0;
|
virtual void work(const QFileInfo&) = 0;
|
||||||
void setPath(const QStringList&);
|
void setPath(const QStringList&);
|
||||||
void setBlockPath(const QStringList &pathList);
|
void setBlockPath(const QStringList &pathList);
|
||||||
protected:
|
protected:
|
||||||
Traverse_BFS(const QStringList&);
|
TraverseBFS(const QStringList&);
|
||||||
QStringList m_pathList;
|
QStringList m_pathList;
|
||||||
QStringList m_blockList;
|
QStringList m_blockList;
|
||||||
private:
|
private:
|
||||||
Traverse_BFS(const Traverse_BFS&) = delete;
|
TraverseBFS(const TraverseBFS&) = delete;
|
||||||
void operator=(const Traverse_BFS&) = delete;
|
void operator=(const TraverseBFS&) = delete;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ QMAKE_CXXFLAGS += -execution-charset:utf-8
|
||||||
# In order to do so, uncomment the following line.
|
# In order to do so, uncomment the following line.
|
||||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
include(filesystemwatcher/file-system-watcher.pri)
|
||||||
include(pluginmanage/plugin-manager.pri)
|
include(pluginmanage/plugin-manager.pri)
|
||||||
include(plugininterface/plugin-interface.pri)
|
include(plugininterface/plugin-interface.pri)
|
||||||
include(index/index.pri)
|
include(index/index.pri)
|
||||||
|
@ -57,8 +58,7 @@ HEADERS += \
|
||||||
global-settings.h \
|
global-settings.h \
|
||||||
gobject-template.h \
|
gobject-template.h \
|
||||||
libsearch_global.h \
|
libsearch_global.h \
|
||||||
libsearch.h \
|
libsearch.h
|
||||||
../ukui-search-app-data-service/app-db-common-defines.h
|
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resource1.qrc \
|
resource1.qrc \
|
||||||
|
|
|
@ -7,4 +7,5 @@ INCLUDEPATH += $$PWD/settingsearch
|
||||||
INCLUDEPATH += $$PWD/appsearch
|
INCLUDEPATH += $$PWD/appsearch
|
||||||
INCLUDEPATH += $$PWD/searchinterface
|
INCLUDEPATH += $$PWD/searchinterface
|
||||||
INCLUDEPATH += $$PWD/dirwatcher
|
INCLUDEPATH += $$PWD/dirwatcher
|
||||||
|
INCLUDEPATH += $$PWD/filesystemwatcher
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "file-system-watcher-test.h"
|
||||||
|
#include <QDebug>
|
||||||
|
using namespace UkuiSearch;
|
||||||
|
FileSystemWatcherTest::FileSystemWatcherTest(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
m_watcher = new FileSystemWatcher(FileSystemWatcher::WatchEvents(FileSystemWatcher::EventMove | FileSystemWatcher::EventMoveSelf |
|
||||||
|
FileSystemWatcher::EventCreate | FileSystemWatcher::EventDelete |
|
||||||
|
FileSystemWatcher::EventDeleteSelf | FileSystemWatcher::EventUnmount |
|
||||||
|
FileSystemWatcher::EventModify | FileSystemWatcher::EventAttributeChange));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSystemWatcherTest::beginSignalTest()
|
||||||
|
{
|
||||||
|
m_watcher->addWatch("/home/zpf/图片");
|
||||||
|
|
||||||
|
connect(m_watcher, &FileSystemWatcher::attributeChanged,
|
||||||
|
[](const QString& fileUrl) { qDebug() << "AttrbuteChanged:" << fileUrl; });
|
||||||
|
connect(m_watcher, &FileSystemWatcher::created,
|
||||||
|
[](const QString& fileUrl, bool isDir) { qDebug() << "Created:" << fileUrl << isDir; });
|
||||||
|
connect(m_watcher, &FileSystemWatcher::deleted,
|
||||||
|
[](const QString& fileUrl, bool isDir) { qDebug() << "Deleted:" << fileUrl << isDir; });
|
||||||
|
connect(m_watcher, &FileSystemWatcher::modified,
|
||||||
|
[](const QString& fileUrl) { qDebug() << "Modified:" << fileUrl; });
|
||||||
|
connect(m_watcher, &FileSystemWatcher::moved,
|
||||||
|
[](const QString& fileUrl, bool isDir) { qDebug() << "Modified:" << fileUrl << isDir; });
|
||||||
|
connect(m_watcher, &FileSystemWatcher::closedWrite,
|
||||||
|
[](const QString& fileUrl) { qDebug() << "ClosedWrite:" << fileUrl; });
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef FILESYSTEMWATCHERTEST_H
|
||||||
|
#define FILESYSTEMWATCHERTEST_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include "file-system-watcher.h"
|
||||||
|
|
||||||
|
class FileSystemWatcherTest : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FileSystemWatcherTest(QObject *parent = nullptr);
|
||||||
|
void beginSignalTest();
|
||||||
|
|
||||||
|
private:
|
||||||
|
UkuiSearch::FileSystemWatcher *m_watcher = nullptr;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FILESYSTEMWATCHERTEST_H
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include "file-system-watcher-test.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication a(argc, argv);
|
||||||
|
FileSystemWatcherTest test;
|
||||||
|
test.beginSignalTest();
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
QT -= gui
|
||||||
|
|
||||||
|
CONFIG += c++11
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
|
||||||
|
# The following define makes your compiler emit warnings if you use
|
||||||
|
# any Qt feature that has been marked deprecated (the exact warnings
|
||||||
|
# depend on your compiler). Please consult the documentation of the
|
||||||
|
# deprecated API in order to know how to port your code away from it.
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS
|
||||||
|
|
||||||
|
# You can also make your code fail to compile if it uses deprecated APIs.
|
||||||
|
# In order to do so, uncomment the following line.
|
||||||
|
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||||
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
|
||||||
|
include(../libsearch/libukui-search-headers.pri)
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
file-system-watcher-test.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
main.cpp \
|
||||||
|
file-system-watcher-test.cpp
|
||||||
|
|
||||||
|
LIBS += -L$$OUT_PWD/../libsearch/ -lukui-search
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD/../libsearch
|
||||||
|
DEPENDPATH += $$PWD/../libsearch
|
|
@ -8,6 +8,8 @@ SUBDIRS += $$PWD/libchinese-segmentation \
|
||||||
$$PWD/ukui-search-app-data-service \
|
$$PWD/ukui-search-app-data-service \
|
||||||
$$PWD/ukui-search-service-dir-manager
|
$$PWD/ukui-search-service-dir-manager
|
||||||
|
|
||||||
|
#SUBDIRS += tests
|
||||||
|
|
||||||
# The following define makes your compiler emit warnings if you use
|
# The following define makes your compiler emit warnings if you use
|
||||||
# any Qt feature that has been marked deprecated (the exact warnings
|
# any Qt feature that has been marked deprecated (the exact warnings
|
||||||
# depend on your compiler). Please consult the documentation of the
|
# depend on your compiler). Please consult the documentation of the
|
||||||
|
|
Loading…
Reference in New Issue