From 29e5ee67677e4ca9c40ad0a7546663ee8255fc89 Mon Sep 17 00:00:00 2001 From: baijunjie Date: Sat, 8 Apr 2023 16:54:01 +0800 Subject: [PATCH] Optimize Dir Watcher. --- libsearch/dirwatcher/dir-watcher.cpp | 18 +- libsearch/dirwatcher/dir-watcher.h | 2 + search-ukcc-plugin/search.cpp | 16 +- .../com.ukui.search.fileindex.server.xml | 7 + .../dirwatcher/config.cpp | 22 +- .../dirwatcher/dir-watcher-adaptor.cpp | 14 + .../dirwatcher/dir-watcher-adaptor.h | 9 + .../dirwatcher/dir-watcher.cpp | 667 +----------------- .../dirwatcher/dir-watcher.h | 69 +- .../dirwatcher/search-dir.cpp | 298 +++++++- .../dirwatcher/search-dir.h | 3 + .../dirwatcher/volume-manager.h | 5 + 12 files changed, 411 insertions(+), 719 deletions(-) diff --git a/libsearch/dirwatcher/dir-watcher.cpp b/libsearch/dirwatcher/dir-watcher.cpp index af6fe43..68b7a4b 100644 --- a/libsearch/dirwatcher/dir-watcher.cpp +++ b/libsearch/dirwatcher/dir-watcher.cpp @@ -101,9 +101,25 @@ QStringList DirWatcher::searchableDirForSearchApplication() return reply.value(); } +void DirWatcher::appendSearchDir(const QString &path) +{ + QDBusReply reply = m_dbusInterface->call("appendSearchDir", path); + if (!reply.isValid()) { + qCritical() << "appendSearchDir call filed!"; + } +} + +void DirWatcher::removeSearchDir(const QString &path) +{ + QDBusReply reply = m_dbusInterface->call("removeSearchDir", path); + if (!reply.isValid()) { + qCritical() << "removeSearchDir call filed!"; + } +} + void DirWatcher::appendIndexableListItem(const QString &path) { - QDBusReply reply = m_dbusInterface->call("appendIndexableListItem", path); + QDBusReply reply = m_dbusInterface->call("appendIndexableListItem", path); if (!reply.isValid()) { qCritical() << "appendIndexableListItem call filed!"; } diff --git a/libsearch/dirwatcher/dir-watcher.h b/libsearch/dirwatcher/dir-watcher.h index 9536c33..7042992 100644 --- a/libsearch/dirwatcher/dir-watcher.h +++ b/libsearch/dirwatcher/dir-watcher.h @@ -21,6 +21,8 @@ public Q_SLOTS: QStringList searchableDirForSearchApplication(); QStringList blackListOfDir(const QString &dirPath); + void appendSearchDir(const QString &path); + void removeSearchDir(const QString &path); void appendIndexableListItem(const QString &path); void removeIndexableListItem(const QString &path); void sendAppendSignal(const QString &path, const QStringList &blockList); diff --git a/search-ukcc-plugin/search.cpp b/search-ukcc-plugin/search.cpp index bcb33bf..4f471eb 100644 --- a/search-ukcc-plugin/search.cpp +++ b/search-ukcc-plugin/search.cpp @@ -469,22 +469,22 @@ void Search::initFileDialog() qDebug() << "Selected a folder in onAddSearchDirBtnClicked(): " << selectedDir; int returnCode = setSearchDir(selectedDir, true); switch (returnCode) { - case 1: + case 0: qDebug() << "Add search folder succeed! path = " << selectedDir; break; - case -1: + case 1: QMessageBox::warning(m_pluginWidget, tr("Warning"), tr("Add search folder failed, choosen path or its parent dir has been added!")); break; - case -2: + case 2: QMessageBox::warning(m_pluginWidget, tr("Warning"), tr("Add search folder failed, choosen path is not supported currently!")); break; - case -3: + case 3: QMessageBox::warning(m_pluginWidget, tr("Warning"), tr("Add search folder failed, choosen path is in repeat mounted devices and another path which is in the same device has been added!")); break; - case -4: + case 4: QMessageBox::warning(m_pluginWidget, tr("Warning"), tr("Add search folder failed, another path which is in the same device has been added!")); break; - case -5: + case 5: QMessageBox::warning(m_pluginWidget, tr("Warning"), tr("Add search folder failed, choosen path is not exists!")); break; default: @@ -581,7 +581,7 @@ void Search::initSearchDirs() int Search::setSearchDir(const QString &dirPath, const bool isAdd) { if (!m_setSearchDirInterface->isValid()) { - return 0; + return -1; } if (isAdd) { @@ -593,7 +593,7 @@ int Search::setSearchDir(const QString &dirPath, const bool isAdd) QDBusReply appendIndexRpl = m_setSearchDirInterface->call("appendIndexableListItem", dirPath); if (appendIndexRpl.isValid()) { - if (appendIndexRpl.value() == 1) { + if (appendIndexRpl.value() == 0) { this->appendSearchDirToList(dirPath); if (!indexDirs.isEmpty()) { indexDirsRpl = m_interface->call("currentIndexableDir"); diff --git a/ukui-search-service-dir-manager/dirwatcher/com.ukui.search.fileindex.server.xml b/ukui-search-service-dir-manager/dirwatcher/com.ukui.search.fileindex.server.xml index 014cdfc..7bce4ea 100644 --- a/ukui-search-service-dir-manager/dirwatcher/com.ukui.search.fileindex.server.xml +++ b/ukui-search-service-dir-manager/dirwatcher/com.ukui.search.fileindex.server.xml @@ -9,5 +9,12 @@ + + + + + + + diff --git a/ukui-search-service-dir-manager/dirwatcher/config.cpp b/ukui-search-service-dir-manager/dirwatcher/config.cpp index c68f241..c8f3857 100644 --- a/ukui-search-service-dir-manager/dirwatcher/config.cpp +++ b/ukui-search-service-dir-manager/dirwatcher/config.cpp @@ -14,7 +14,6 @@ static const QStringList GLOBAL_BLACK_LIST{"/proc", "/sys", "/dev", "/tmp", "/ru static const QString GLOBAL_SETTINGS_GROUP = "GlobalSettings"; static const QString SEARCH_DIRS_GROUP = "SearchDirs"; - static std::once_flag flag; static Config *global_instance = nullptr; Config *Config::self() @@ -95,7 +94,7 @@ QVector Config::searchDirObjects() Config::Config() { m_settings = new QSettings(CURRENT_INDEXABLE_DIR_SETTINGS, QSettings::IniFormat); - if(!(m_settings->value(CONFIG_VERSION_KEY).toString() == CONFIG_VERSION)) { + if(!(m_settings->value(GLOBAL_SETTINGS_GROUP + "/" + CONFIG_VERSION_KEY).toString() == CONFIG_VERSION)) { m_compatibilityMode = true; for(const QString& path : m_settings->value(INDEXABLE_DIR_KEY + "/" + INDEXABLE_DIR_KEY).toStringList()) { if(QFile::exists(path)) { @@ -121,6 +120,7 @@ Config::Config() } m_settings->endGroup(); } + m_settings->beginGroup(GLOBAL_SETTINGS_GROUP); if(m_settings->value(GLOBAL_BLACK_LIST_KEY).isNull()) { m_settings->setValue(GLOBAL_BLACK_LIST_KEY, GLOBAL_BLACK_LIST); @@ -142,11 +142,19 @@ void Config::processCompatibleCache() { if(this->isCompatibilityMode()) { m_settings->beginGroup(SEARCH_DIRS_GROUP); - for(SearchDir dir : m_compatibleCache) { - dir.generateBlackList(); - if(dir.error() == SearchDir::ErrorInfo::Successful) { - m_searchDirs.append(dir); - m_settings->setValue(QUrl::fromLocalFile(dir.getPath()).toString(), dir.getBlackList()); + if (m_compatibleCache.isEmpty()) { + SearchDir defaultDir(QDir::homePath()); + if (defaultDir.error() == SearchDir::ErrorInfo::Successful) { + m_searchDirs.append(defaultDir); + m_settings->setValue(QUrl::fromLocalFile(defaultDir.getPath()).toString(), defaultDir.getBlackList()); + } + } else { + for (SearchDir dir : m_compatibleCache) { + dir.generateBlackList(); + if (dir.error() == SearchDir::ErrorInfo::Successful) { + m_searchDirs.append(dir); + m_settings->setValue(QUrl::fromLocalFile(dir.getPath()).toString(), dir.getBlackList()); + } } } m_settings->endGroup(); diff --git a/ukui-search-service-dir-manager/dirwatcher/dir-watcher-adaptor.cpp b/ukui-search-service-dir-manager/dirwatcher/dir-watcher-adaptor.cpp index ae5b25e..b6a0fc0 100644 --- a/ukui-search-service-dir-manager/dirwatcher/dir-watcher-adaptor.cpp +++ b/ukui-search-service-dir-manager/dirwatcher/dir-watcher-adaptor.cpp @@ -41,6 +41,14 @@ int DirWatcherAdaptor::appendIndexableListItem(const QString &path) return out0; } +int DirWatcherAdaptor::appendSearchDir(const QString &path) +{ + // handle method call org.ukui.search.fileindex.appendSearchDir + int out0; + QMetaObject::invokeMethod(parent(), "appendSearchDir", Q_RETURN_ARG(int, out0), Q_ARG(QString, path)); + return out0; +} + bool DirWatcherAdaptor::removeIndexableListItem(const QString &path) { // handle method call org.ukui.search.fileindex.removeIndexableListItem @@ -49,3 +57,9 @@ bool DirWatcherAdaptor::removeIndexableListItem(const QString &path) return out0; } +void DirWatcherAdaptor::removeSearchDir(const QString &path) +{ + // handle method call org.ukui.search.fileindex.removeSearchDir + QMetaObject::invokeMethod(parent(), "removeSearchDir", Q_ARG(QString, path)); +} + diff --git a/ukui-search-service-dir-manager/dirwatcher/dir-watcher-adaptor.h b/ukui-search-service-dir-manager/dirwatcher/dir-watcher-adaptor.h index be4c3d8..0150fea 100644 --- a/ukui-search-service-dir-manager/dirwatcher/dir-watcher-adaptor.h +++ b/ukui-search-service-dir-manager/dirwatcher/dir-watcher-adaptor.h @@ -40,6 +40,13 @@ class DirWatcherAdaptor: public QDBusAbstractAdaptor " \n" " \n" " \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" " \n" "") public: @@ -49,7 +56,9 @@ public: public: // PROPERTIES public Q_SLOTS: // METHODS int appendIndexableListItem(const QString &path); + int appendSearchDir(const QString &path); bool removeIndexableListItem(const QString &path); + void removeSearchDir(const QString &path); Q_SIGNALS: // SIGNALS }; diff --git a/ukui-search-service-dir-manager/dirwatcher/dir-watcher.cpp b/ukui-search-service-dir-manager/dirwatcher/dir-watcher.cpp index 2734583..e749698 100644 --- a/ukui-search-service-dir-manager/dirwatcher/dir-watcher.cpp +++ b/ukui-search-service-dir-manager/dirwatcher/dir-watcher.cpp @@ -15,38 +15,18 @@ static std::once_flag flag; static DirWatcher *global_intance = nullptr; -QMutex DirWatcher::s_mutex; DirWatcher::DirWatcher(QObject *parent) : QObject(parent) { //兼容旧版配置 -// Config::self()->processCompatibleCache(); + Config::self()->processCompatibleCache(); - m_qSettings = new QSettings(CURRENT_INDEXABLE_DIR_SETTINGS, QSettings::IniFormat); - this->currentIndexableDir(); - if (m_indexableDirList.isEmpty()) { - qDebug() << QString("use the path: %1 as default indexable dir.").arg(DEFAULT_INDEXABLE_DIR); - m_qSettings->beginGroup(INDEXABLE_DIR_VALUE); - m_qSettings->setValue(INDEXABLE_DIR_VALUE, DEFAULT_INDEXABLE_DIR); - m_qSettings->endGroup(); - } - - initDiskWatcher(); - initData(); m_adaptor = new DirWatcherAdaptor(this); } DirWatcher::~DirWatcher() { - if (m_volumeMonitor) { - g_signal_handler_disconnect(m_volumeMonitor, m_mountAddHandle); - g_signal_handler_disconnect(m_volumeMonitor, m_mountRemoveHandle); - m_volumeMonitor = nullptr; - } - if(m_qSettings){ - delete m_qSettings; - } - m_qSettings = nullptr; + } DirWatcher *DirWatcher::getDirWatcher() @@ -59,90 +39,13 @@ DirWatcher *DirWatcher::getDirWatcher() QStringList DirWatcher::currentIndexableDir() { - QMutexLocker locker(&s_mutex); - this->updateIndexableDirs(); - return m_indexableDirList; + return currentSearchDirs(); } -void DirWatcher::updateIndexableDirs() -{ - m_qSettings->beginGroup(INDEXABLE_DIR_VALUE); - m_indexableDirList = m_qSettings->value(INDEXABLE_DIR_VALUE).toStringList(); - m_qSettings->endGroup(); - QStringList indexableDirs = m_indexableDirList; - bool changed(false); - for (const QString& dir : m_indexableDirList) { - if (!QFileInfo(dir).isDir()) { - indexableDirs.removeAll(dir); - changed = true; - } - } - - if (changed) { - m_qSettings->beginGroup(INDEXABLE_DIR_VALUE); - m_qSettings->setValue(INDEXABLE_DIR_VALUE, indexableDirs); - m_qSettings->endGroup(); - m_indexableDirList = indexableDirs; - Q_EMIT this->indexDirsChanged(); - } -} QStringList DirWatcher::currentBlackListOfIndex() { - QMutexLocker locker(&s_mutex); - QStringList blackListOfIndex = m_blackListOfIndex; - return blackListOfIndex; -} - -bool DirWatcher::handleIndexItemAppend(const QString &path, QStringList &blackList) -{ - //排除要添加的路径已被索引的情况 - if (m_indexableDirList.contains(path)) { - qDebug() << QString("index path %1 is already added.").arg(path); - return false; - } - - //处理添加路径非根目录时,要添加索引的路径与已索引路径为父子关系的情况 - if (path != "/") { - QString indexablePath; - QStringList tmp = m_indexableDirList; - for (int i = 0; i < m_indexableDirList.length(); i++) { - indexablePath = m_indexableDirList.at(i); - if (path.startsWith(indexablePath + "/")) { - qCritical() << QString("The parent of the path:%1 has been added.").arg(path); - return false; - } - if (indexablePath.startsWith(path + "/")) { - tmp.removeAll(indexablePath); - blackList.append(indexablePath); - } - } - m_indexableDirList = tmp; - } - - m_indexableDirList << path; - m_qSettings->beginGroup(INDEXABLE_DIR_VALUE); - m_qSettings->setValue(INDEXABLE_DIR_VALUE, m_indexableDirList); - m_qSettings->endGroup(); - blackList.removeDuplicates(); - Q_EMIT this->appendIndexItem(path, blackList); - qDebug() << "index path:" << path << "blacklist:" << blackList; - return true; -} - -bool DirWatcher::handleIndexItemRemove(const QString &path) -{ - this->currentIndexableDir(); - QMutexLocker locker(&s_mutex); - if (!m_indexableDirList.contains(path)) { - qWarning() << QString("The path: %1 is not indexed").arg(path); - return false; - } - m_indexableDirList.removeAll(path); - m_qSettings->beginGroup(INDEXABLE_DIR_VALUE); - m_qSettings->setValue(INDEXABLE_DIR_VALUE, m_indexableDirList); - m_qSettings->endGroup(); - return true; + return currentBlackList(); } /** @@ -151,67 +54,7 @@ bool DirWatcher::handleIndexItemRemove(const QString &path) */ QStringList DirWatcher::blackListOfDir(const QString &dirPath) { - //new TODO: Optimize the search algorithm. - //There is no processing for the subvolumes.May be a bug. - QStringList blackListOfDir; - QMutexLocker locker(&s_mutex); - for (auto t = m_repeatedlyMountedDeviceInfo.constBegin(); t != m_repeatedlyMountedDeviceInfo.constEnd(); t++) { - QString topRepeatedMountPoint; - for (QString mountPoint: t.value()) { - if (mountPoint.startsWith(dirPath)) { - if (topRepeatedMountPoint.isEmpty()) { - topRepeatedMountPoint = mountPoint; - continue; - } else if (topRepeatedMountPoint.startsWith(mountPoint)) { - blackListOfDir.append(topRepeatedMountPoint); - topRepeatedMountPoint = mountPoint; - } else { - blackListOfDir.append(mountPoint); - } - } - } - } - for (auto i = m_infoOfSubvolume.constBegin(); i != m_infoOfSubvolume.constEnd(); i++) { - QString mountPoint = i.value(); - QString spec = i.key(); - //排除搜索列表指定多个目录时子卷会重复包含的情况,比如同时指定/home和/data/home - QString tmp = dirPath; - if (dirPath.startsWith(mountPoint)) { - blackListOfDir.append(tmp.replace(0, mountPoint.length(), spec)); - } - if (dirPath.startsWith(spec)) { - blackListOfDir.append(tmp.replace(0, spec.length(), mountPoint)); - } - } - return blackListOfDir; -} - -void DirWatcher::appendBlackListItemOfIndex(const QString &path) -{ - QMutexLocker locker(&s_mutex); - m_blackListOfIndex.append(path); - m_blackListOfIndex = m_blackListOfIndex.toSet().toList(); -} - -void DirWatcher::appendBlackListItemOfIndex(const QStringList &pathList) -{ - QMutexLocker locker(&s_mutex); - m_blackListOfIndex.append(pathList); - m_blackListOfIndex = m_blackListOfIndex.toSet().toList(); -} - -void DirWatcher::removeBlackListItemOfIndex(const QString &path) -{ - QMutexLocker locker(&s_mutex); - m_blackListOfIndex.removeAll(path); -} - -void DirWatcher::removeBlackListItemOfIndex(const QStringList &pathList) -{ - QMutexLocker locker(&s_mutex); - for (QString path: pathList) { - m_blackListOfIndex.removeAll(path); - } + return SearchDir::blackListOfDir(dirPath); } void DirWatcher::initDbusService() @@ -224,323 +67,58 @@ void DirWatcher::initDbusService() QStringList DirWatcher::currentSearchableDir() { - QMutexLocker locker(&s_mutex); - return m_searchableDirList; + return currentSearchDirs(); } QStringList DirWatcher::searchableDirForSearchApplication() { - QMutexLocker locker(&s_mutex); - return m_searchableListForApplication; -} - -void DirWatcher::mountAddCallback(GVolumeMonitor *monitor, GMount *gmount, DirWatcher *pThis) -{ - qDebug() << "Mount Added"; - GMount* mount = (GMount*)g_object_ref(gmount); - GVolume* volume = g_mount_get_volume(mount); - if (volume) { - bool canEject = g_volume_can_eject(volume); - QString devName = g_volume_get_identifier(volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); - if (canEject and devName.contains(QRegExp("/nvme[0-9]+n[0-9]+p[0-9]+|/sd[a-z][0-9]+"))) { - QMutexLocker locker(&s_mutex); - pThis->m_currentUDiskDeviceList.append(devName.section("/", -1)); - } - qDebug() << "added device name:" << devName.section("/", -1); - g_object_unref(volume); - } else { - qWarning() << "GVolume(add) is NULL."; - } - pThis->handleDisk(); -} - -void DirWatcher::mountRemoveCallback(GVolumeMonitor *monitor, GMount *gmount, DirWatcher *pThis) -{ - qDebug() << "Mount Removed"; - pThis->handleDisk(); - QMutexLocker locker(&s_mutex); - //处理u盘设备 - if (pThis->m_removedUDiskDevice != NULL) { - pThis->updateIndexableDirs();//更新索引名单,排除失效目录 - pThis->m_currentUDiskDeviceInfo.remove(pThis->m_removedUDiskDevice); - qDebug() << "m_currentUDiskDeviceInfo(after remove):" << pThis->m_currentUDiskDeviceInfo; - pThis->m_removedUDiskDevice = ""; - return; - } - - GMount* mount = (GMount*)g_object_ref(gmount); - GFile* rootFile; - rootFile = g_mount_get_root(mount); - if (!rootFile) { - return; - } - QString removedUri = g_file_get_uri(rootFile); - if (removedUri.isEmpty()) { - return; - } - //处理uri转码 - if (removedUri.startsWith("file:///")) { - QString removedMountPoint = g_filename_from_uri(removedUri.toUtf8().constData(), nullptr, nullptr); - pThis->m_blackListOfIndex.removeAll(removedMountPoint); - locker.unlock(); - QStringList indexableDirList = pThis->currentIndexableDir(); - //卸载目录下存在已索引目录时,通知索引服务删除对应目录 - for (const QString &indexableDir : indexableDirList) { - if (indexableDir.startsWith(removedMountPoint + "/") or !indexableDir.compare(removedMountPoint)) { - Q_EMIT pThis->removeIndexItem(indexableDir); - } - } - //处理子卷情况 - locker.relock(); - for (auto t = pThis->m_infoOfSubvolume.constBegin(); t != pThis->m_infoOfSubvolume.constEnd(); t++) { - if (removedMountPoint.startsWith(t.value() + "/")) { - pThis->m_blackListOfIndex.removeAll(removedMountPoint.replace(t.value(), t.key())); - } - if (removedMountPoint.startsWith(t.key() + "/")) { - pThis->m_blackListOfIndex.removeAll(removedMountPoint.replace(t.key(), t.value())); - } - } - qDebug() << "m_blackListOfIndex(after remove):" << pThis->m_blackListOfIndex; - } else { - qWarning() << QString("Removed uri:%1 is not starts with 'file:///', there's no handling of it.").arg(removedUri); - } - g_object_unref(rootFile); + return currentSearchDirs(); } int DirWatcher::appendIndexableListItem(const QString &path) { - int resultCode = 1; + return appendSearchDir(path); /* code: - * 1: successful - * -1: path or its parent dir has been added - * -2: path is or under blacklist - * -3: path is in repeat mounted devices and another path which is in the same device has been indexed - * -4: another path which is in the same device has been indexed - * -5: path is not exists + * 0: successful + * 1: path or its parent dir has been added + * 2: path is or under blacklist + * 3: path is in repeat mounted devices and another path which is in the same device has been indexed + * 4: another path which is in the same device has been indexed + * 5: path is not exists */ - - //排除path不存在的情况 - QFile file(path); - if (!file.exists()) { - qWarning() << QString("target path:%1 is not exists!").arg(path); - resultCode = -5; - return resultCode; - } - - //同步配置文件中的已索引目录 - this->currentIndexableDir(); - qDebug() << "current indexable dirs:" << m_indexableDirList; - - QStringList blackList; - QMutexLocker locker(&s_mutex); - - //根目录特殊处理 - if (path == "/") { - if (!this->handleIndexItemAppend(path, m_blackListOfIndex)) { - resultCode = -1; - } - return resultCode; - } - - //处理要添加索引的路径与索引黑名单中路径为父子关系的情况 - for (const QString& blackListPath : m_blackListOfIndex) { - if (path.startsWith(blackListPath + "/") or path == blackListPath) { - qCritical() << QString("path:%1 is or under the blacklistpath:%2.").arg(path, blackListPath); - resultCode = -2; - return resultCode; - } - - if (blackListPath.startsWith(path + "/")) { - blackList.append(blackListPath); - } - } - - //排除要添加的目录为某设备的重复挂载目录,并且之前已索引过该设备其他挂载目录或其父目录的情况 - for (auto i = m_repeatedlyMountedDeviceInfo.constBegin(); i != m_repeatedlyMountedDeviceInfo.constEnd(); i++) { - bool pathToBeAddedIsRepeatedDevice = false; - bool pathToBeAddedHasRepeatedDevice = false; - bool addedPathIsRepeatedDevice = false; - bool addedPathHasRepeatedDevice = false; - QString addedRelativeDir; - QString repeatedDir; - for (const QString &addedPath : m_indexableDirList) { - for (const QString &mountPoint : i.value()) { - - //要添加索引路径在重复挂载设备路径下(1) - if (path.startsWith(mountPoint + "/") or mountPoint == path) { - repeatedDir = mountPoint; - pathToBeAddedIsRepeatedDevice = true; - } - //重复挂载设备路径在要添加索引路径下(2) - if (mountPoint.startsWith(path + "/")) { - repeatedDir = mountPoint; - pathToBeAddedHasRepeatedDevice = true; - } - - //已索引路径在重复挂载设备路径下(3) - if (addedPath.startsWith(mountPoint + "/") or mountPoint == addedPath) { - addedRelativeDir = addedPath; - addedRelativeDir.remove(mountPoint); - addedPathIsRepeatedDevice = true; - } - //重复挂载设备路径在已索引路径下(4) - if (mountPoint.startsWith(addedPath + "/")) { - addedPathHasRepeatedDevice = true; - } - - //(1)(4)直接返回 - if (pathToBeAddedIsRepeatedDevice and addedPathHasRepeatedDevice) { - qCritical() << "current path is in repeat mounted devices and another path which is in the same device has been indexed!"; - resultCode = -3; - return resultCode; - } - //(2)(4)将要添加索引目录相应的重复挂载路径添加到黑名单 - if (pathToBeAddedHasRepeatedDevice and addedPathHasRepeatedDevice) { - blackList.append(repeatedDir); - break; - } - //(1)(3)将已索引路径的前缀替换为要添加路径的前缀(前缀为mountPoint),判断替换后路径是否在要索引路径下,如果是则返回,否则将替换后路径添加到黑名单 - if (pathToBeAddedIsRepeatedDevice and addedPathIsRepeatedDevice) { - QString pathAfterReplace = repeatedDir + addedRelativeDir; - if (path.startsWith(pathAfterReplace) or path == pathAfterReplace) { - qCritical() << QString("another path:%1 which is in the same device has been indexed").arg(pathAfterReplace); - resultCode = -4; - return resultCode; - } else { - blackList.append(pathAfterReplace); - break; - } - } - //(2)(3)将替换前缀后的已索引路径添加到黑名单 - if (pathToBeAddedHasRepeatedDevice and addedPathIsRepeatedDevice) { - blackList.append(repeatedDir + addedRelativeDir); - break; - } - } - } - } - - //排除重复挂载设备的目录 - for (auto i = m_repeatedlyMountedDeviceInfo.constBegin(); i != m_repeatedlyMountedDeviceInfo.constEnd(); i++) { - QString topRepeatedMountPoint; - for (const QString &mountPoint : i.value()) { - if (mountPoint.startsWith(path + "/") or mountPoint == path) { - if (topRepeatedMountPoint.isEmpty()) { - topRepeatedMountPoint = mountPoint; - continue; - } else if (topRepeatedMountPoint.startsWith(mountPoint)) { - blackList.append(topRepeatedMountPoint); - topRepeatedMountPoint = mountPoint; - } else { - blackList.append(mountPoint); - } - } - } - } - - //处理自动挂载子卷下的目录 - for (auto t = m_infoOfSubvolume.constBegin(); t != m_infoOfSubvolume.constEnd(); t++) { - QString mountPoint = t.value(); - QString spec = t.key(); - //要添加目录下存在子卷(要添加/data,但挂到/home的/data/home是子卷),若添加了/home则将/data/home排除 - if (spec.startsWith(path + "/")) { - for (QString &indexDir : m_indexableDirList) { - if (indexDir == mountPoint || mountPoint.startsWith(indexDir + "/")) { - blackList << spec; - } - if (indexDir.startsWith(mountPoint + "/")) { - blackList << indexDir.replace(0, mountPoint.length(), spec); - } - } - - } - //要添加目录下存在子卷挂载点,同上 - if (mountPoint.startsWith(path + "/")) { - - for (QString &indexDir : m_indexableDirList) { - if (indexDir == spec || spec.startsWith(indexDir + "/")) { - blackList << mountPoint; - } - if (indexDir.startsWith(spec + "/")) { - blackList << indexDir.replace(0, spec.length(), mountPoint); - } - } - } - - //要添加的目录是子卷或在子卷下(/data/home or /data/home/xxx) - if (path.startsWith(spec + "/") || path == spec) { - for (QString &indexDir : m_indexableDirList) { - //已添加挂载点或其上层目录 - if (mountPoint.startsWith(indexDir + "/") || indexDir == mountPoint) { - qCritical() << "Fail to add" << path << "The mount point or its father:" << indexDir << "has been added"; - resultCode = -3; - return resultCode; - } - //已添加挂载点下其他目录 - if (indexDir.startsWith(mountPoint + "/")) { - - QString tmp = indexDir; - tmp.replace(0, mountPoint.length(), spec); - if (tmp == path) { - qCritical() << "Fail to add" << path << "The same path which is in the subvolume has been added."; - resultCode = -4; - return resultCode; - } else if (tmp.startsWith(path + "/")) {//已添加的子卷子目录替换前缀后在要添加目录下 - blackList << tmp; - } - } - } - } - - //要添加的目录是挂载点或在挂载点下(/home or /home/xxx) - if (path.startsWith(mountPoint + "/") || path == mountPoint) { - for (QString &indexDir : m_indexableDirList) { - //已添加子卷或其上层目录 - if (spec.startsWith(indexDir + "/") || indexDir == spec) { - qCritical() << "Fail to add" << path << "The subvolume or its father:" << indexDir << "has been added"; - resultCode = -3; - return resultCode; - } - //已添加子卷下其他目录 - if (indexDir.startsWith(spec + "/")) { - QString tmp = indexDir; - tmp.replace(0, spec.length(), mountPoint); - if (tmp == path) { - qCritical() << "Fail to add" << path << "The same path which is in the mount point has been added."; - resultCode = -4; - return resultCode; - } else if (tmp.startsWith(path + "/")) {//已添加的子卷子目录替换前缀后在要添加目录下 - blackList << tmp; - } - } - } - } - } - - if (!this->handleIndexItemAppend(path, blackList)) { - resultCode = -1; - } - return resultCode; } bool DirWatcher::removeIndexableListItem(const QString &path) { - bool res = this->handleIndexItemRemove(path); - Q_EMIT this->removeIndexItem(path); - return res; + removeSearchDir(path); + return true; } int DirWatcher::appendSearchDir(const QString &path) { SearchDir dir(path); - Config::self()->addDir(dir); - return 0; + if (dir.error() == SearchDir::Successful) { + Q_EMIT this->appendIndexItem(path, dir.getBlackList()); + qDebug() << "Add search dir:" << path << "blacklist:" << dir.getBlackList(); + //要添加已索引目录的父目录,先添加索引,再同步配置文件,从而使得下次读取配置文件时不会将子目录排除掉 + for (const QString &searchDir : Config::self()->searchDirs()) { + if (searchDir.startsWith(path + "/") || path == "/") { + SearchDir subDir(searchDir); + Config::self()->removeDir(subDir); + } + } + dir.generateBlackList(); + Config::self()->addDir(dir); + } + qWarning() << dir.getPath() << dir.errorString(); + return dir.error(); } void DirWatcher::removeSearchDir(const QString &path) { SearchDir dir(path, false); Config::self()->removeDir(dir); + Q_EMIT this->removeIndexItem(path); return; } @@ -553,184 +131,3 @@ QStringList DirWatcher::currentBlackList() { return Config::self()->blackDirs(); } - -void DirWatcher::initData() -{ - //适配需求,可索引目录为用户指定。 -// m_indexableDirList << "/data" << QDir::homePath(); - /* boot里面存放Linux核心文件,开机选单与开机所需配置文件等 - * backup里面是系统备份文件 - * bin放置的是在单人维护模式下还能够被操作的指令,在bin底下的指令可以被root与一般账号所使用。 - * dev里面存放设备文件 - * etc里面存放了几乎所有的系统主要配置文件,包括人员的账号密码文件,各种服务的起始档等 - * lib放置最基本的共享库和内核模块,lib32,lib64,libx32分别面向32位,64位以及x32 ABI。他们都分别连接到usr下的lib*中 - * media一般放置可移除的装置,包括软盘,光盘和一些移动存储设备都自动挂载到这里 - * mnt原本和media用途相同,现用来放置暂时挂载一些额外装置 - * usr是Unix操作系统软件资源所放置的目录,所有系统默认的软件(distribution发布者提供的软件)都会放置到usr底下 - * var目录主要针对常态性变动的文件,包括缓存(cache)、登录档(log file)以及某些软件运作所产生的文件,包括程序文件(lock file, run file),或者如MySQL数据库的文件等 - */ - //将磁盘分区后其他分区都会挂载到media下,多块硬盘也会挂到media,因此media放开,mnt同理; - //backup是备份文件,tmp是临时文件,也都放开 -// m_blackListOfIndex << "/boot" << "/bin" << "/dev" << "/etc" << "/usr" << "/var" -// << "/lib" << "/lib32" << "/lib64" << "/libx32" << "/cdrom" -// << "/sys" << "/proc" << "/srv" << "/sbin" << "/run" << "/opt"; - //专用机需求:只屏蔽/proc, /sys, /dev, /tmp, /run - m_blackListOfIndex << "/proc" << "/sys" << "/dev" << "/tmp" << "/run"; - - //目前方案:可搜索目录(服务)默认根目录,可搜索目录(应用)默认家目录和/data目录 - QDir dir("/data"); - if (dir.exists()) { - m_searchableListForApplication << "/data"; - } - m_searchableListForApplication << QDir::homePath(); - - m_searchableDirList << "/"; - - //init auto mounted device list - setfsent(); - while (1) { - fstab *myFstab = getfsent(); - if (!myFstab) { - endfsent(); - break; - } - QString automaticMountPoint = myFstab->fs_file; - QString spec = myFstab->fs_spec; - - //目前只索引data和home,因此只存这两个文件夹下的挂载点 - if (automaticMountPoint.contains("/data") || automaticMountPoint.contains("/home")) { - m_autoMountList.append(automaticMountPoint); - } - //存储所有子卷自动挂载 - if (!spec.startsWith("UUID")) { - m_infoOfSubvolume.insert(spec, automaticMountPoint); - } - } - - GList *list = g_volume_monitor_get_volumes(m_volumeMonitor); - if (!list) { - qDebug() << "Fail to init glist of volume monitor!"; - handleDisk(); - return; - } - for (guint i = 0; i < g_list_length(list); i++) { - GVolume *volume = (GVolume*)g_list_nth_data(list, i); - QString udiskDevName = g_volume_get_identifier(volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); - bool canEject = g_volume_can_eject(volume); - if (canEject and udiskDevName.contains(QRegExp("/nvme[0-9]+n[0-9]+p[0-9]+|/sd[a-z][0-9]+"))) { - qDebug() << "udiskDevName:" << udiskDevName.section("/",-1); - m_currentUDiskDeviceList.append(udiskDevName.section("/",-1)); - } - } - - //init disk data, refresh the black list - handleDisk(); -} - -void DirWatcher::initDiskWatcher() -{ - //use Dbus to monitor the hot plug of Udisk. - - - QDBusConnection dbc = QDBusConnection::systemBus(); - - qDebug() << "Connect The Signal:InterfacesAdded" << dbc.connect("org.freedesktop.UDisks2", - "/org/freedesktop/UDisks2", - "org.freedesktop.DBus.ObjectManager", - "InterfacesAdded", - this, SLOT(handleAddedUDiskDevice(QDBusMessage))); - qDebug() << dbc.lastError(); - qDebug() << "Connect The Signal:InterfacesRemove" << dbc.connect("org.freedesktop.UDisks2", - "/org/freedesktop/UDisks2", - "org.freedesktop.DBus.ObjectManager", - "InterfacesRemoved", - this, SLOT(handleRemovedUDiskDevice(QDBusMessage))); - - m_volumeMonitor = g_volume_monitor_get(); - if (!m_volumeMonitor) { - qDebug() << "Fail to init volume monitor"; - return; - } - m_mountAddHandle = g_signal_connect(m_volumeMonitor, "mount-added", G_CALLBACK(mountAddCallback), this); - m_mountRemoveHandle = g_signal_connect(m_volumeMonitor, "mount-removed", G_CALLBACK(mountRemoveCallback), this); -} - -void DirWatcher::handleDisk() -{ - //init current mounted device info - QMutexLocker locker(&s_mutex); - m_currentMountedDeviceInfo.clear(); - m_repeatedlyMountedDeviceInfo.clear(); - for (QStorageInfo &storage: QStorageInfo::mountedVolumes()) { - //遍历当前系统所有挂载的,且以sd*和nvme开头的存储设备 - if (storage.isValid() and storage.isReady() and QString(storage.device()).contains(QRegExp("/nvme[0-9]+n[0-9]+p[0-9]+|/sd[a-z][0-9]+"))) { - m_currentMountedDeviceInfo[storage.device()].append(storage.rootPath()); - //存储非子卷的重复挂载设备 - if (m_currentMountedDeviceInfo.value(storage.device()).length() > 1 and storage.subvolume().isEmpty()) { - m_repeatedlyMountedDeviceInfo.insert(storage.device(), m_currentMountedDeviceInfo.value(storage.device())); - } - //排除挂载到data和home下挂载的所有其他设备,后面需要修改 -// if (storage.rootPath().startsWith("/data") || storage.rootPath().startsWith("/home")) { -// m_blackListOfIndex.append(storage.rootPath()); -// } - } - } - - //根据设备号(key)更新u盘信息 - if (!m_currentUDiskDeviceList.isEmpty()) { - for (const QString &udiskDevice: m_currentUDiskDeviceList) { - QStringList udiskMountPointList = m_currentMountedDeviceInfo.value("/dev/" + udiskDevice); - if (udiskMountPointList.isEmpty()) { - m_currentUDiskDeviceInfo.remove(udiskDevice); - } else { - m_currentUDiskDeviceInfo.insert(udiskDevice, udiskMountPointList); - } - - } - } - - //将u盘设备添加到索引黑名单 - if (!m_currentUDiskDeviceInfo.isEmpty()) { - for (auto t = m_currentUDiskDeviceInfo.constBegin(); t != m_currentUDiskDeviceInfo.constEnd(); t++) { - for (QString udiskDevice: t.value()) { -// if (udiskDevice.startsWith("/data") || udiskDevice.startsWith("/home")) { -// m_blackListOfIndex.append(udiskDevice); -// } - } - } - } - - //从索引黑名单中移除所有自动挂载设备(目前只包含自动挂载到/data和/home目录下的设备),m_infoOfSubvolume存储全部fstab文件中的子卷自动挂载 - for (const QString &autoMountDevice: m_autoMountList) { - m_blackListOfIndex.removeAll(autoMountDevice); - } - m_blackListOfIndex.removeDuplicates(); - - qDebug() << "m_infoOfSubvolume" << m_infoOfSubvolume; - qDebug() << "m_currentMountedDeviceInfo:" << m_currentMountedDeviceInfo; - qDebug() << "m_repeatedlyMountedDeviceInfo:" << m_repeatedlyMountedDeviceInfo; - qDebug() << "m_currentUDiskDeviceInfo:" << m_currentUDiskDeviceInfo; - qDebug() << "m_blackListOfIndex:" << m_blackListOfIndex; - -} - -void DirWatcher::handleAddedUDiskDevice(QDBusMessage msg) -{ - QDBusObjectPath objPath = msg.arguments().at(0).value(); - if (objPath.path().contains(QRegExp("/nvme[0-9]+n[0-9]+p[0-9]+|/sd[a-z][0-9]+"))) { - QMutexLocker locker(&s_mutex); - m_currentUDiskDeviceList.append(objPath.path().section("/",-1)); - qDebug() << "Add Udisk:" << m_currentUDiskDeviceList; - } -} - -void DirWatcher::handleRemovedUDiskDevice(QDBusMessage msg) -{ - Q_EMIT this->udiskRemoved(); - QDBusObjectPath objPath = msg.arguments().at(0).value(); - if (objPath.path().contains(QRegExp("/nvme[0-9]+n[0-9]+p[0-9]+|/sd[a-z][0-9]+"))) { - QMutexLocker locker(&s_mutex); - m_removedUDiskDevice = objPath.path().section("/",-1); - m_currentUDiskDeviceList.removeAll(m_removedUDiskDevice); - } -} diff --git a/ukui-search-service-dir-manager/dirwatcher/dir-watcher.h b/ukui-search-service-dir-manager/dirwatcher/dir-watcher.h index 992ff59..bc6326b 100644 --- a/ukui-search-service-dir-manager/dirwatcher/dir-watcher.h +++ b/ukui-search-service-dir-manager/dirwatcher/dir-watcher.h @@ -4,23 +4,13 @@ #include "dir-watcher-adaptor.h" #include -#include -#include +#include #include #include -#include -#include #include #include #include -#undef slots -#undef signals -#undef emit - -#include -#include - class DirWatcher : public QObject { Q_OBJECT @@ -29,13 +19,6 @@ class DirWatcher : public QObject public: static DirWatcher *getDirWatcher(); - static void mountAddCallback(GVolumeMonitor *monitor, GMount *gmount, DirWatcher *pThis); - static void mountRemoveCallback(GVolumeMonitor *monitor, GMount *gmount, DirWatcher *pThis); - - void appendBlackListItemOfIndex(const QString &path); - void appendBlackListItemOfIndex(const QStringList &pathList); - void removeBlackListItemOfIndex(const QString &path); - void removeBlackListItemOfIndex(const QStringList &pathList); public Q_SLOTS: @@ -53,19 +36,19 @@ public Q_SLOTS: * add a item to indexable dirs * @param path: the path to be added to the index dirs list * @return int: the result code - * 1: successful - * -1: path or its parent dir has been added - * -2: path is or under blacklist - * -3: path is in repeat mounted devices and another path which is in the same device has been indexed - * -4: another path which is in the same device has been indexed - * -5: path is not exists + * 0: successful + * 1: path or its parent dir has been added + * 2: path is or under blacklist + * 3: path is in repeat mounted devices and another path which is in the same device has been indexed + * 4: another path which is in the same device has been indexed + * 5: path is not exists */ Q_SCRIPTABLE int appendIndexableListItem(const QString &path); Q_SCRIPTABLE bool removeIndexableListItem(const QString &path); //新接口 - int appendSearchDir(const QString &path); - void removeSearchDir(const QString &path); + Q_SCRIPTABLE int appendSearchDir(const QString &path); + Q_SCRIPTABLE void removeSearchDir(const QString &path); QStringList currentSearchDirs(); QStringList currentBlackList(); @@ -74,46 +57,16 @@ public Q_SLOTS: private: DirWatcher(QObject *parent = nullptr); ~DirWatcher(); - void initData(); - void initDiskWatcher(); - void updateIndexableDirs(); - - void handleDisk(); - - bool handleIndexItemAppend(const QString &path, QStringList &blackList); - bool handleIndexItemRemove(const QString &path); static QMutex s_mutex; DirWatcherAdaptor *m_adaptor = nullptr; - GVolumeMonitor *m_volumeMonitor = nullptr; - quint64 m_mountAddHandle; - quint64 m_mountRemoveHandle; - - QSettings *m_qSettings = nullptr; - QStringList m_blackListOfIndex; - QStringList m_indexableDirList; - - QStringList m_searchableDirList; - QStringList m_searchableListForApplication; - QStringList m_autoMountList; - QMultiMap m_infoOfSubvolume; - QMap m_currentMountedDeviceInfo; - QMap m_repeatedlyMountedDeviceInfo; - - QStringList m_currentUDiskDeviceList; - QString m_removedUDiskDevice; - QMap m_currentUDiskDeviceInfo; - -private Q_SLOTS: - void handleAddedUDiskDevice(QDBusMessage msg); - void handleRemovedUDiskDevice(QDBusMessage msg); - Q_SIGNALS: - void udiskRemoved(); void appendIndexItem(const QString&, const QStringList&); void removeIndexItem(const QString&); + //abondoned + void udiskRemoved(); void indexDirsChanged(); }; diff --git a/ukui-search-service-dir-manager/dirwatcher/search-dir.cpp b/ukui-search-service-dir-manager/dirwatcher/search-dir.cpp index a14c6b2..0068baa 100644 --- a/ukui-search-service-dir-manager/dirwatcher/search-dir.cpp +++ b/ukui-search-service-dir-manager/dirwatcher/search-dir.cpp @@ -1,10 +1,17 @@ #include "search-dir.h" +#include "config.h" +#include "volume-manager.h" +#include SearchDir::SearchDir(const QString &path, bool generateBlackList) { - m_path = path; - if(generateBlackList) { - //根据VulumeManager和Congig的数据计算黑名单here + if (!QFile::exists(path)) { + m_error = NotExists; + } else { + m_path = path; + if(generateBlackList) { + this->handleBlackListGenerate(); + } } } @@ -22,18 +29,19 @@ QString SearchDir::errorString() { switch (m_error) { case ErrorInfo::Successful: - return ""; + return "Add search dir successful"; case ErrorInfo::Duplicated: - return ""; + return "Path or its parent dir has been added"; case ErrorInfo::UnderBlackList: - return ""; + return "Path is or under blacklist"; case ErrorInfo::RepeatMount1: - return ""; + return "Path is in repeat mounted devices and another path which is in the same device has been indexed"; case ErrorInfo::RepeatMount2: - return ""; + return "Another path which is in the same device has been indexed"; case ErrorInfo::NotExists: - return ""; + return "Path is not exists"; } + return QString(); } QString SearchDir::getPath() const @@ -53,5 +61,275 @@ QStringList SearchDir::getBlackList() const void SearchDir::generateBlackList() { - //生成黑名单 + m_blackList.clear(); + this->handleBlackListGenerate(); +} + +QStringList SearchDir::blackListOfDir(const QString &dirPath) +{ + QStringList blackListOfDir; + for (const QStringList & mountPoints: VolumeManager::self()->getDuplicates()) { + QString topRepeatedMountPoint; + for (const QString &mountPoint : mountPoints) { + //该目录下是否有两个文件夹(有可能为父子关系)是重复挂载的关系 + if (mountPoint.startsWith(dirPath + "/") or mountPoint == dirPath) { + if (topRepeatedMountPoint.isEmpty()) { + topRepeatedMountPoint = mountPoint; + continue; + } + //重复挂载时保留最上层的挂载点 + if (topRepeatedMountPoint.startsWith(mountPoint + "/")) { + blackListOfDir.append(topRepeatedMountPoint); + topRepeatedMountPoint = mountPoint; + } else { + blackListOfDir.append(mountPoint); + } + } + } + } + + for (const Volume &volume : VolumeManager::self()->volumesHaveSubVolumes()) { + for (const QString &duplicateMountPoint : volume.mountPoints()) { + QMap subVolumeInfo = volume.subVolumes(); + if (subVolumeInfo.keys().contains(duplicateMountPoint)) { + continue; + } + for (auto it = subVolumeInfo.constBegin(); it != subVolumeInfo.constEnd(); it++) { + QString spec = it.key(); + QString subMountPoint = duplicateMountPoint + it.value(); + //排除搜索列表指定多个目录时子卷会重复包含的情况,比如同时指定/home和/data/home + QString tmp = dirPath; + if (dirPath.startsWith(subMountPoint)) { + blackListOfDir.append(tmp.replace(0, subMountPoint.length(), spec)); + } + if (dirPath.startsWith(spec)) { + blackListOfDir.append(tmp.replace(0, spec.length(), subMountPoint)); + } + } + } + } + return blackListOfDir; +} + +void SearchDir::handleBlackListGenerate() +{ + QStringList searchDirs = Config::self()->searchDirs(); + + //目录已被索引 + if (searchDirs.contains(m_path)) { + m_error = Duplicated; + return; + } + + //根目录特殊处理 + if (m_path == "/") { + m_blackList << Config::self()->globalBlackList() << searchDirs; + for (const QStringList &mountPoints: VolumeManager::self()->getDuplicates()) { + QStringList repeatMountPoints = mountPoints; + if (mountPoints.contains("/")) { + repeatMountPoints.removeAll("/"); + m_blackList << repeatMountPoints; + continue; + } + bool excludeAll(false); + for (const QString &mountPoint : mountPoints) { + for (const QString &searchDir : searchDirs) { + //之前已索引重复挂载设备挂载点或其子目录,则排除其他目录 + if (searchDir.startsWith(mountPoint + "/") || searchDir == mountPoint) { + repeatMountPoints.removeAll(mountPoint); + break; + } + //重复挂载点在已索引目录下,该挂载点全排除 + if (mountPoint.startsWith(searchDir + "/")) { + excludeAll = true; + break; + } + } + if (excludeAll) { + m_blackList << repeatMountPoints; + break; + } + } + //不需要全排除且没有需要特别保留的挂载点,默认留第一个 + if (!excludeAll && repeatMountPoints == mountPoints) { + repeatMountPoints.removeFirst(); + } + m_blackList << repeatMountPoints; + } + m_blackList.removeDuplicates(); + return; + } + + //处理要添加索引的路径与全局黑名单中路径为父子关系的情况 + for (const QString& blackListPath : Config::self()->globalBlackList()) { + if (m_path.startsWith(blackListPath + "/") or m_path == blackListPath) { + m_error = UnderBlackList; + return; + } + if (blackListPath.startsWith(m_path + "/")) { + m_blackList.append(blackListPath); + } + } + + //重复挂载情况 + for (const QStringList & mountPoints: VolumeManager::self()->getDuplicates()) { + QString topRepeatedMountPoint; + for (const QString &mountPoint : mountPoints) { + if (mountPoint.startsWith(m_path + "/") or mountPoint == m_path) { + if (topRepeatedMountPoint.isEmpty()) { + topRepeatedMountPoint = mountPoint; + continue; + } else if (topRepeatedMountPoint.startsWith(mountPoint)) { + m_blackList.append(topRepeatedMountPoint); + topRepeatedMountPoint = mountPoint; + } else { + m_blackList.append(mountPoint); + } + } + } + + //排除要添加的目录为某设备的重复挂载目录,并且之前已索引过该设备其他挂载目录或其父目录的情况 + bool pathToBeAddedIsRepeatedDevice = false; + bool pathToBeAddedHasRepeatedDevice = false; + bool addedPathIsRepeatedDevice = false; + bool addedPathHasRepeatedDevice = false; + QString addedRelativeDir; + QString repeatedDir; + for (const QString &addedPath : searchDirs) { + for (const QString &mountPoint : mountPoints) { + + //要添加索引路径在重复挂载设备路径下(1) + if (m_path.startsWith(mountPoint + "/") or mountPoint == m_path) { + repeatedDir = mountPoint; + pathToBeAddedIsRepeatedDevice = true; + } + //重复挂载设备路径在要添加索引路径下(2) + if (mountPoint.startsWith(m_path + "/")) { + repeatedDir = mountPoint; + pathToBeAddedHasRepeatedDevice = true; + } + + //已索引路径在重复挂载设备路径下(3) + if (addedPath.startsWith(mountPoint + "/") or mountPoint == addedPath) { + addedRelativeDir = addedPath; + addedRelativeDir.remove(0, mountPoint.length()); + addedPathIsRepeatedDevice = true; + } + //重复挂载设备路径在已索引路径下(4) + if (mountPoint.startsWith(addedPath + "/")) { + addedPathHasRepeatedDevice = true; + } + + //(1)(4)直接返回 + if (pathToBeAddedIsRepeatedDevice and addedPathHasRepeatedDevice) { + m_error = RepeatMount1; + return; + } + //(2)(4)将要添加索引目录相应的重复挂载路径添加到黑名单 + if (pathToBeAddedHasRepeatedDevice and addedPathHasRepeatedDevice) { + m_blackList.append(repeatedDir); + break; + } + //(1)(3)将已索引路径的前缀替换为要添加路径的前缀(前缀为mountPoint),判断替换后路径是否在要索引路径下,如果是则返回,否则将替换后路径添加到黑名单 + if (pathToBeAddedIsRepeatedDevice and addedPathIsRepeatedDevice) { + QString pathAfterReplace = repeatedDir + addedRelativeDir; + if (m_path.startsWith(pathAfterReplace) or m_path == pathAfterReplace) { + m_error = RepeatMount2; + return; + } else { + m_blackList.append(pathAfterReplace); + break; + } + } + //(2)(3)将替换前缀后的已索引路径添加到黑名单 + if (pathToBeAddedHasRepeatedDevice and addedPathIsRepeatedDevice) { + m_blackList.append(repeatedDir + addedRelativeDir); + break; + } + } + } + } + + //处理自动挂载子卷下的目录 + for (const Volume &volume : VolumeManager::self()->volumesHaveSubVolumes()) { + QMap subVolumeInfo = volume.subVolumes(); + for (auto it = subVolumeInfo.constBegin(); it != subVolumeInfo.constEnd(); it++) { + QString subMountPoint = it.key(); + for (const QString &duplicateMountPoint : volume.mountPoints()) { + if (subVolumeInfo.keys().contains(duplicateMountPoint)) { + continue; + } + QString spec = duplicateMountPoint + it.value(); //子卷对应目录 + //要添加目录下存在子卷(要添加/data,但挂到/home的/data/home是子卷),若添加了/home则将/data/home排除 + if (spec.startsWith(m_path + "/")) { + for (QString &searchDir : searchDirs) { + if (searchDir == subMountPoint || subMountPoint.startsWith(searchDir + "/")) { + m_blackList << spec; + } + if (searchDir.startsWith(subMountPoint + "/")) { + m_blackList << searchDir.replace(0, subMountPoint.length(), spec); + } + } + + } + + //要添加的目录是子卷或在子卷下(/data/home or /data/home/xxx) + if (m_path.startsWith(spec + "/") || m_path == spec) { + for (QString &searchDir : searchDirs) { + //已添加挂载点或其上层目录 + if (subMountPoint.startsWith(searchDir + "/") || searchDir == subMountPoint) { + m_error = RepeatMount1; + return; + } + //已添加挂载点下其他目录 + if (searchDir.startsWith(subMountPoint + "/")) { + QString tmp = searchDir; + tmp.replace(0, subMountPoint.length(), spec); + if (tmp == m_path) { + m_error = RepeatMount2; + return; + } else if (tmp.startsWith(m_path + "/")) {//已添加的子卷子目录替换前缀后在要添加目录下 + m_blackList << tmp; + } + } + } + } + + //要添加的目录是挂载点或在挂载点下(/home or /home/xxx) + if (m_path.startsWith(subMountPoint + "/") || m_path == subMountPoint) { + for (QString &searchDir : searchDirs) { + //已添加子卷或其上层目录 + if (spec.startsWith(searchDir + "/") || searchDir == spec) { + m_error = RepeatMount1; + return; + } + //已添加子卷下其他目录 + if (searchDir.startsWith(spec + "/")) { + QString tmp = searchDir; + tmp.replace(0, spec.length(), subMountPoint); + if (tmp == m_path) { + m_error = RepeatMount2; + return; + } else if (tmp.startsWith(m_path + "/")) {//已添加的子卷子目录替换前缀后在要添加目录下 + m_blackList << tmp; + } + } + } + } + } + } + + } + + //要添加目录下存在已索引目录 + for (const QString &searchDir : searchDirs) { + if (m_path.startsWith(searchDir + "/")) { + m_error = Duplicated; + return; + } + if (searchDir.startsWith(m_path + "/")) { + m_blackList.append(searchDir); + } + } + m_blackList.removeDuplicates(); } diff --git a/ukui-search-service-dir-manager/dirwatcher/search-dir.h b/ukui-search-service-dir-manager/dirwatcher/search-dir.h index f645713..7e81377 100644 --- a/ukui-search-service-dir-manager/dirwatcher/search-dir.h +++ b/ukui-search-service-dir-manager/dirwatcher/search-dir.h @@ -12,6 +12,7 @@ public: RepeatMount2, NotExists }; + SearchDir() = default; SearchDir(const QString& path, bool generateBlackList = true); bool operator == (const SearchDir& rhs) const; ErrorInfo error(); @@ -23,7 +24,9 @@ public: * @brief 重新生成黑名单 */ void generateBlackList(); + static QStringList blackListOfDir(const QString &dirPath); private: + void handleBlackListGenerate(); QString m_path; QStringList m_blackList; ErrorInfo m_error = ErrorInfo::Successful; diff --git a/ukui-search-service-dir-manager/dirwatcher/volume-manager.h b/ukui-search-service-dir-manager/dirwatcher/volume-manager.h index 88e50ee..c87ac9d 100644 --- a/ukui-search-service-dir-manager/dirwatcher/volume-manager.h +++ b/ukui-search-service-dir-manager/dirwatcher/volume-manager.h @@ -1,5 +1,10 @@ #ifndef VOLUMEMANAGER_H #define VOLUMEMANAGER_H + +#undef slots +#undef signals +#undef emit + #include #include #include