summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2011-01-22 21:29:02 +0100
committerDan McGee <dan@archlinux.org>2011-01-22 23:34:42 +0100
commit27e8f06e0335ca560a3d0a261cc1979dbc1caad9 (patch)
tree20493b902d45af7c0cb6ec269d21fc3adb70e9af
parent4d291508c2c24d058d0e00ca9588c6c81b24bc92 (diff)
downloadpacman-27e8f06e0335ca560a3d0a261cc1979dbc1caad9.tar.gz
pacman-27e8f06e0335ca560a3d0a261cc1979dbc1caad9.tar.xz
Query fileowner performance improvements
Clean up some of the code by doing less string copying and printing. This is accomplished by either doing it after we know we need it, or taking advantage of the fact that some strings never change such as the root directory prefix. Also, fix an issue where a file at the root level (e.g. /foobar) could not be queried. End result is a much faster user experience when combined with the mbasename() changes. These timings are for looking up 113 files in /etc/, some of which are owned and some which are not. $ find /etc -maxdepth 1 -type f | xargs time pacman -Qo >/dev/null 6.10user 0.05system 0:06.17elapsed 99%CPU (0avgtext+0avgdata 131040maxresident)k 0inputs+0outputs (0major+9436minor)pagefaults 0swaps $ find /etc -maxdepth 1 -type f | xargs time ./src/pacman/.libs/lt-pacman -Qo >/dev/null 0.86user 0.04system 0:00.92elapsed 99%CPU (0avgtext+0avgdata 131120maxresident)k 0inputs+0outputs (0major+9436minor)pagefaults 0swaps I'll take a 600% increase in speed. Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--src/pacman/query.c48
1 files changed, 33 insertions, 15 deletions
diff --git a/src/pacman/query.c b/src/pacman/query.c
index f5993609..fc6a2a56 100644
--- a/src/pacman/query.c
+++ b/src/pacman/query.c
@@ -39,11 +39,11 @@
extern pmdb_t *db_local;
-static char *resolve_path(const char* file)
+static char *resolve_path(const char *file)
{
char *str = NULL;
- str = calloc(PATH_MAX+1, sizeof(char));
+ str = calloc(PATH_MAX + 1, sizeof(char));
if(!str) {
return(NULL);
}
@@ -97,7 +97,10 @@ static int search_path(char **filename, struct stat *bufptr)
static int query_fileowner(alpm_list_t *targets)
{
int ret = 0;
- char *filename;
+ char path[PATH_MAX];
+ const char *root;
+ char *append;
+ size_t max_length;
alpm_list_t *t;
/* This code is here for safety only */
@@ -106,13 +109,22 @@ static int query_fileowner(alpm_list_t *targets)
return(1);
}
+ /* Set up our root path buffer. We only need to copy the location of root in
+ * once, then we can just overwrite whatever file was there on the previous
+ * iteration. */
+ root = alpm_option_get_root();
+ strncpy(path, root, PATH_MAX - 1);
+ append = path + strlen(path);
+ max_length = PATH_MAX - (append - path) - 1;
+
for(t = targets; t; t = alpm_list_next(t)) {
+ char *filename, *dname, *rpath;
+ const char *bname;
+ struct stat buf;
+ alpm_list_t *i;
int found = 0;
+
filename = strdup(alpm_list_getdata(t));
- char *dname, *rpath;
- const char *root, *bname;
- struct stat buf;
- alpm_list_t *i, *j;
if(lstat(filename, &buf) == -1) {
/* if it is not a path but a program name, then check in PATH */
@@ -144,32 +156,38 @@ static int query_fileowner(alpm_list_t *targets)
bname = mbasename(filename);
dname = mdirname(filename);
rpath = resolve_path(dname);
- free(dname);
- if(!rpath) {
+ /* this odd conditional is to ensure files in '/' can be checked */
+ if(!rpath && strcmp(dname, "") != 0) {
pm_fprintf(stderr, PM_LOG_ERROR, _("cannot determine real path for '%s': %s\n"),
filename, strerror(errno));
free(filename);
+ free(dname);
free(rpath);
ret++;
continue;
}
-
- root = alpm_option_get_root();
+ free(dname);
for(i = alpm_db_get_pkgcache(db_local); i && !found; i = alpm_list_next(i)) {
+ alpm_list_t *j;
pmpkg_t *info = alpm_list_getdata(i);
for(j = alpm_pkg_get_files(info); j && !found; j = alpm_list_next(j)) {
- char path[PATH_MAX], *ppath, *pdname;
- snprintf(path, PATH_MAX, "%s%s",
- root, (const char *)alpm_list_getdata(j));
+ char *ppath, *pdname;
+ const char *pkgfile = alpm_list_getdata(j);
/* avoid the costly resolve_path usage if the basenames don't match */
- if(strcmp(mbasename(path), bname) != 0) {
+ if(strcmp(mbasename(pkgfile), bname) != 0) {
continue;
}
+ if(strlen(pkgfile) > max_length) {
+ pm_fprintf(stderr, PM_LOG_ERROR, _("Path too long: %s%s\n"), root, pkgfile);
+ }
+ /* concatenate our file and the root path */
+ strcpy(append, pkgfile);
+
pdname = mdirname(path);
ppath = resolve_path(pdname);
free(pdname);