summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Schroeder <mls@suse.de>2012-11-28 17:57:10 +0100
committerMichael Schroeder <mls@suse.de>2012-11-28 17:57:10 +0100
commit67b4f920c26ba0f307b426b19426f411d11b765e (patch)
tree257450da36714d9d84e90cdfc4a94f58f770b8f5
parentf84307ce170e95d22a15c8199957b8f892a024f8 (diff)
downloadlibsolv-67b4f920c26ba0f307b426b19426f411d11b765e.tar.gz
libsolv-67b4f920c26ba0f307b426b19426f411d11b765e.tar.bz2
libsolv-67b4f920c26ba0f307b426b19426f411d11b765e.zip
speed up filelist matching by pre-matching the basename first
-rw-r--r--src/repodata.c77
1 files changed, 70 insertions, 7 deletions
diff --git a/src/repodata.c b/src/repodata.c
index 50ff1dd..6cdf17b 100644
--- a/src/repodata.c
+++ b/src/repodata.c
@@ -1061,6 +1061,28 @@ datamatcher_init(Datamatcher *ma, const char *match, int flags)
ma->flags = (flags & ~SEARCH_STRINGMASK) | SEARCH_ERROR;
}
}
+ if ((flags & SEARCH_FILES) != 0 && match)
+ {
+ /* prepare basename check */
+ if ((flags & SEARCH_STRINGMASK) == SEARCH_STRING)
+ {
+ const char *p = strrchr(match, '/');
+ ma->matchdata = (void *)(p ? p + 1 : match);
+ }
+ else if ((flags & SEARCH_STRINGMASK) == SEARCH_STRINGEND)
+ {
+ const char *p = strrchr(match, '/');
+ ma->matchdata = (void *)(p ? p + 1 : 0);
+ }
+ else if ((flags & SEARCH_STRINGMASK) == SEARCH_GLOB)
+ {
+ const char *p;
+ for (p = match + strlen(match) - 1; p >= match; p--)
+ if (*p == '[' || *p == ']' || *p == '*' || *p == '?' || *p == '/')
+ break;
+ ma->matchdata = (void *)(p + 1);
+ }
+ }
return ma->error;
}
@@ -1070,8 +1092,9 @@ datamatcher_free(Datamatcher *ma)
if ((ma->flags & SEARCH_STRINGMASK) == SEARCH_REGEX && ma->matchdata)
{
regfree(ma->matchdata);
- ma->matchdata = solv_free(ma->matchdata);
+ solv_free(ma->matchdata);
}
+ ma->matchdata = 0;
}
int
@@ -1145,6 +1168,49 @@ datamatcher_match(Datamatcher *ma, const char *str)
return 1;
}
+/* check if the matcher can match the provides basename */
+
+static int
+datamatcher_checkbasename(Datamatcher *ma, const char *basename)
+{
+ int l;
+ const char *match = ma->match;
+ switch (ma->flags & SEARCH_STRINGMASK)
+ {
+ case SEARCH_STRING:
+ match = ma->matchdata;
+ break;
+ case SEARCH_STRINGEND:
+ if (ma->matchdata)
+ {
+ match = ma->matchdata; /* have slash */
+ break;
+ }
+ l = strlen(basename) - strlen(match);
+ if (l < 0)
+ return 0;
+ basename += l;
+ break;
+ case SEARCH_GLOB:
+ match = ma->matchdata;
+ if (!match)
+ return 1;
+ l = strlen(basename) - strlen(match);
+ if (l < 0)
+ return 0;
+ basename += l;
+ break;
+ default:
+ return 1; /* maybe matches */
+ }
+ if (!match)
+ return 1;
+ if ((ma->flags & SEARCH_NOCASE) != 0)
+ return !strcasecmp(match, basename);
+ else
+ return !strcmp(match, basename);
+}
+
int
repodata_filelistfilter_matches(Repodata *data, const char *str)
{
@@ -1578,12 +1644,9 @@ dataiterator_step(Dataiterator *di)
if (di->matcher.match)
{
/* simple pre-check so that we don't need to stringify */
- if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && di->matcher.match && (di->matcher.flags & (SEARCH_FILES|SEARCH_NOCASE|SEARCH_STRINGMASK)) == (SEARCH_FILES|SEARCH_STRING))
- {
- int l = strlen(di->matcher.match) - strlen(di->kv.str);
- if (l < 0 || strcmp(di->matcher.match + l, di->kv.str))
- continue;
- }
+ if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && (di->matcher.flags & SEARCH_FILES) != 0)
+ if (!datamatcher_checkbasename(&di->matcher, di->kv.str))
+ continue;
if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
{
if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))