Skip to content

Commit

Permalink
feat: Support segmentation search
Browse files Browse the repository at this point in the history
Change-Id: Iaf4e55fe41ab44d4540d4172745aeec900101974
  • Loading branch information
zccrs committed Mar 8, 2019
1 parent 9fabe04 commit 4a5d8f6
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 15 deletions.
6 changes: 4 additions & 2 deletions library/inc/fs_buf.h
Expand Up @@ -43,8 +43,10 @@ int rename_path(fs_buf* fsbuf, const char* src_path, const char* dst_path, fs_ch
void get_path_range(fs_buf *fsbuf, const char *path, uint32_t *path_off, uint32_t *start_off, uint32_t *end_off);

// do not check null pointer.
void search_files(fs_buf* fsbuf, uint32_t* start_off, uint32_t end_off, void* param, int (*comparator)(const char*, void*), uint32_t* results, uint32_t* count);

typedef int (*progress_fn)(uint32_t count, const char* cur_file, void* param);
typedef int (*comparator_fn)(const char *file_name, void* param);
void search_files(fs_buf* fsbuf, uint32_t* start_off, uint32_t end_off, uint32_t* results, uint32_t* count,
comparator_fn comparator, void *comparator_param, progress_fn pcf, void *pcf_param);

// functions below are used internally
void set_kids_off(fs_buf* fsbuf, uint32_t name_off, uint32_t kids_off);
Expand Down
10 changes: 8 additions & 2 deletions library/src/fs_buf.c
Expand Up @@ -846,7 +846,8 @@ __attribute__((visibility("default"))) int rename_path(fs_buf *fsbuf, const char
return r;
}

__attribute__((visibility("default"))) void search_files(fs_buf *fsbuf, uint32_t *start_off, uint32_t end_off, void *param, int (*comparator)(const char *, void *), uint32_t *results, uint32_t *count)
__attribute__((visibility("default"))) void search_files(fs_buf *fsbuf, uint32_t *start_off, uint32_t end_off, uint32_t *results, uint32_t *count,
comparator_fn comparator, void *comparator_param, progress_fn pcf, void *pcf_param)
{
uint32_t size = *count;
*count = 0;
Expand All @@ -856,7 +857,12 @@ __attribute__((visibility("default"))) void search_files(fs_buf *fsbuf, uint32_t
while (name_off < min_off && *count < size)
{
char *name = fsbuf->head + name_off;
if (*name != 0 && (*comparator)(name, param) != 0)

if (pcf && (*pcf)(*count, name, pcf_param) != 0) {
break;
}

if (*name != 0 && (*comparator)(name, comparator_param) == 0)
{
results[*count] = name_off;
*count = *count + 1;
Expand Down
62 changes: 52 additions & 10 deletions server/lib/lftmanager.cpp
Expand Up @@ -660,19 +660,38 @@ QStringList LFTManager::sync(const QString &mountPoint)

static int compareString(const char *string, void *keyword)
{
return QString::fromLocal8Bit(string).indexOf(*static_cast<const QString*>(keyword), 0, Qt::CaseInsensitive) >= 0;
return QString::fromLocal8Bit(string).indexOf(*static_cast<const QString*>(keyword), 0, Qt::CaseInsensitive) < 0;
}

static int compareStringRegExp(const char *string, void *re)
{
auto match = static_cast<QRegularExpression*>(re)->match(QString::fromLocal8Bit(string));

return match.hasMatch();
return !match.hasMatch();
}

QStringList LFTManager::search(const QString &path, const QString keyword, bool useRegExp) const
static int timeoutGuard(uint32_t count, const char* cur_file, void* param)
{
nDebug() << path << keyword << useRegExp;
Q_UNUSED(count)
Q_UNUSED(cur_file)

QPair<QElapsedTimer*, qint64> *data = static_cast<QPair<QElapsedTimer*, qint64>*>(param);

return data->first->elapsed() >= data->second; // 返回false时表示不终端搜索
}

QStringList LFTManager::search(const QString &path, const QString &keyword, bool useRegExp) const
{
quint32 start, end;

return search(-1, -1, 0, 0, path, keyword, useRegExp, start, end);
}

QStringList LFTManager::search(int maxCount, qint64 maxTime, quint32 startOffset, quint32 endOffset,
const QString &path, const QString &keyword, bool useRegExp,
quint32 &startOffsetReturn, quint32 &endOffsetReturn) const
{
nDebug() << maxCount << maxTime << startOffset << endOffset << path << keyword << useRegExp;

auto buf_list = getFsBufByPath(path);

Expand All @@ -692,11 +711,15 @@ QStringList LFTManager::search(const QString &path, const QString keyword, bool

// new_path 为path在fs_buf中对应的路径
const QString &new_path = buf_list.first().first;
uint32_t path_offset = 0, start_offset = 0, end_offset = 0;
get_path_range(buf, new_path.toLocal8Bit().constData(), &path_offset, &start_offset, &end_offset);

if (startOffset == 0 || endOffset == 0) {
// 未指定有效的搜索区间时, 根据路径获取
uint32_t path_offset = 0;
get_path_range(buf, new_path.toLocal8Bit().constData(), &path_offset, &startOffset, &endOffset);
}

// 说明目录为空
if (start_offset == 0) {
if (startOffset == 0) {
nDebug() << "Empty directory:" << new_path;

return QStringList();
Expand All @@ -705,7 +728,7 @@ QStringList LFTManager::search(const QString &path, const QString keyword, bool
QRegularExpression re(keyword);

void *compare_param = nullptr;
int (*compare)(const char *, void *) = nullptr;
comparator_fn compare = nullptr;

if (useRegExp) {
if (!re.isValid()) {
Expand All @@ -725,7 +748,7 @@ QStringList LFTManager::search(const QString &path, const QString keyword, bool
compare = compareString;
}

#define MAX_RESULT_COUNT 1000
#define MAX_RESULT_COUNT 100

uint32_t name_offsets[MAX_RESULT_COUNT];
uint32_t count = MAX_RESULT_COUNT;
Expand All @@ -735,8 +758,20 @@ QStringList LFTManager::search(const QString &path, const QString keyword, bool
// root_path 以/结尾,所以此处需要多忽略一个字符
bool need_reset_root_path = path != new_path;

QElapsedTimer et;
progress_fn progress = nullptr;
QPair<QElapsedTimer*, qint64> progress_param;

if (maxTime >= 0) {
et.start();
progress = timeoutGuard;
progress_param.first = &et;
progress_param.second = maxTime;
}

do {
search_files(buf, &start_offset, end_offset, compare_param, compare, name_offsets, &count);
count = qMin(MAX_RESULT_COUNT, maxCount - list.count());
search_files(buf, &startOffset, endOffset, name_offsets, &count, compare, compare_param, progress, &progress_param);

for (uint32_t i = 0; i < count; ++i) {
const char *result = get_path_by_name_off(buf, name_offsets[i], tmp_path, sizeof(tmp_path));
Expand All @@ -749,8 +784,15 @@ QStringList LFTManager::search(const QString &path, const QString keyword, bool
list << origin_path;
}
}

if (maxTime >= 0 && et.elapsed() >= maxTime) {
break;
}
} while (count == MAX_RESULT_COUNT);

startOffsetReturn = startOffset;
endOffsetReturn = endOffset;

return list;
}

Expand Down
5 changes: 4 additions & 1 deletion server/lib/lftmanager.h
Expand Up @@ -52,7 +52,10 @@ class LFTManager : public QObject, protected QDBusContext
QStringList refresh(const QByteArray &serialUriFilter = QByteArray());
QStringList sync(const QString &mountPoint = QString());

QStringList search(const QString &path, const QString keyword, bool useRegExp = false) const;
QStringList search(const QString &path, const QString &keyword, bool useRegExp = false) const;
QStringList search(int maxCount, qint64 maxTime, quint32 startOffset, quint32 endOffset,
const QString &path, const QString &keyword, bool useRegExp,
quint32 &startOffsetReturn, quint32 &endOffsetReturn) const;

QStringList insertFileToLFTBuf(const QByteArray &file);
QStringList removeFileFromLFTBuf(const QByteArray &file);
Expand Down
12 changes: 12 additions & 0 deletions server/tool/com.deepin.anything.xml
Expand Up @@ -50,6 +50,18 @@
<arg type='b' name='useRegExp' direction='in'/>
<arg type='as' name='results' direction='out'/>
</method>
<method name='search'>
<arg type='i' name='maxCount' direction='in'/>
<arg type='x' name='maxTime' direction='in'/>
<arg type='u' name='startOffset' direction='in'/>
<arg type='u' name='endOffset' direction='in'/>
<arg type='s' name='path' direction='in'/>
<arg type='s' name='keyword' direction='in'/>
<arg type='b' name='useRegExp' direction='in'/>
<arg type='as' name='results' direction='out'/>
<arg type='u' name='startOffset' direction='out'/>
<arg type='u' name='endOffset' direction='out'/>
</method>
<method name='insertFileToLFTBuf'>
<arg type='ay' name='filePath' direction='in'/>
<arg type='as' name='bufRootPathList' direction='out'/>
Expand Down

0 comments on commit 4a5d8f6

Please sign in to comment.