1 |
commit: f855d0f4f7c3e6e570a1ad3dc98d737e78996e4a |
2 |
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
3 |
AuthorDate: Fri May 10 15:23:25 2019 +0000 |
4 |
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
5 |
CommitDate: Fri May 10 15:23:25 2019 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=f855d0f4 |
7 |
|
8 |
libq/tree: make pkg sorting based on atom_compare |
9 |
|
10 |
Using alphasort on pkgs makes little sense because they include version |
11 |
information that needs careful extraction and matching rules as |
12 |
implemented by atom_compare. |
13 |
|
14 |
In order to use atom_compare efficiently, that is, reusing the |
15 |
atom_explode work done for the elements while running qsort, use |
16 |
tree_get_atom, which caches the retrieved atom. Extra bonus is that any |
17 |
function that retrieves the atom afterwards gets it for free. This |
18 |
speeds up significantly apps that need to construct atoms, such as |
19 |
qkeywords. |
20 |
|
21 |
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org> |
22 |
|
23 |
libq/tree.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++-------------- |
24 |
libq/tree.h | 2 +- |
25 |
2 files changed, 51 insertions(+), 16 deletions(-) |
26 |
|
27 |
diff --git a/libq/tree.c b/libq/tree.c |
28 |
index c8b4b5e..86dd18f 100644 |
29 |
--- a/libq/tree.c |
30 |
+++ b/libq/tree.c |
31 |
@@ -25,6 +25,8 @@ |
32 |
#include <ctype.h> |
33 |
#include <xalloc.h> |
34 |
|
35 |
+static int tree_pkg_compar(const void *l, const void *r); |
36 |
+ |
37 |
static tree_ctx * |
38 |
tree_open_int(const char *sroot, const char *tdir, bool quiet) |
39 |
{ |
40 |
@@ -56,7 +58,7 @@ tree_open_int(const char *sroot, const char *tdir, bool quiet) |
41 |
ctx->do_sort = false; |
42 |
ctx->cat_de = NULL; |
43 |
ctx->catsortfunc = alphasort; |
44 |
- ctx->pkgsortfunc = alphasort; |
45 |
+ ctx->pkgsortfunc = tree_pkg_compar; |
46 |
ctx->repo = NULL; |
47 |
ctx->ebuilddir_ctx = NULL; |
48 |
ctx->ebuilddir_pkg_ctx = NULL; |
49 |
@@ -208,7 +210,7 @@ tree_open_cat(tree_ctx *ctx, const char *name) |
50 |
cat_ctx->fd = fd; |
51 |
cat_ctx->dir = dir; |
52 |
cat_ctx->ctx = ctx; |
53 |
- cat_ctx->pkg_de = NULL; |
54 |
+ cat_ctx->pkg_ctxs = NULL; |
55 |
return cat_ctx; |
56 |
} |
57 |
|
58 |
@@ -260,7 +262,7 @@ tree_close_cat(tree_cat_ctx *cat_ctx) |
59 |
/* closedir() above does this for us: */ |
60 |
/* close(ctx->fd); */ |
61 |
if (cat_ctx->ctx->do_sort) |
62 |
- scandir_free(cat_ctx->pkg_de, cat_ctx->pkg_cnt); |
63 |
+ free(cat_ctx->pkg_ctxs); |
64 |
free(cat_ctx); |
65 |
} |
66 |
|
67 |
@@ -309,30 +311,63 @@ tree_open_pkg(tree_cat_ctx *cat_ctx, const char *name) |
68 |
return pkg_ctx; |
69 |
} |
70 |
|
71 |
+static int |
72 |
+tree_pkg_compar(const void *l, const void *r) |
73 |
+{ |
74 |
+ tree_pkg_ctx *pl = *(tree_pkg_ctx **)l; |
75 |
+ tree_pkg_ctx *pr = *(tree_pkg_ctx **)r; |
76 |
+ depend_atom *al = tree_get_atom(pl, false); |
77 |
+ depend_atom *ar = tree_get_atom(pr, false); |
78 |
+ |
79 |
+ switch (atom_compare(al, ar)) { |
80 |
+ case EQUAL: return 0; |
81 |
+ case NEWER: return -1; |
82 |
+ case OLDER: return 1; |
83 |
+ default: return strcmp(al->PN, ar->PN); |
84 |
+ } |
85 |
+ |
86 |
+ /* unreachable */ |
87 |
+} |
88 |
+ |
89 |
static tree_pkg_ctx * |
90 |
tree_next_pkg_int(tree_cat_ctx *cat_ctx); |
91 |
static tree_pkg_ctx * |
92 |
tree_next_pkg_int(tree_cat_ctx *cat_ctx) |
93 |
{ |
94 |
tree_pkg_ctx *pkg_ctx = NULL; |
95 |
+ const struct dirent *de; |
96 |
|
97 |
if (cat_ctx->ctx->do_sort) { |
98 |
- if (cat_ctx->pkg_de == NULL) { |
99 |
- cat_ctx->pkg_cnt = scandirat(cat_ctx->fd, ".", &cat_ctx->pkg_de, |
100 |
- tree_filter_pkg, cat_ctx->ctx->pkgsortfunc); |
101 |
+ if (cat_ctx->pkg_ctxs == NULL) { |
102 |
+ size_t pkg_size = 0; |
103 |
+ cat_ctx->pkg_ctxs = NULL; |
104 |
+ cat_ctx->pkg_cnt = 0; |
105 |
cat_ctx->pkg_cur = 0; |
106 |
- } |
107 |
+ while ((de = readdir(cat_ctx->dir)) != NULL) { |
108 |
+ if (tree_filter_pkg(de) == 0) |
109 |
+ continue; |
110 |
+ |
111 |
+ if (cat_ctx->pkg_cnt == pkg_size) { |
112 |
+ pkg_size += 256; |
113 |
+ cat_ctx->pkg_ctxs = xrealloc(cat_ctx->pkg_ctxs, |
114 |
+ sizeof(*cat_ctx->pkg_ctxs) * pkg_size); |
115 |
+ } |
116 |
+ pkg_ctx = cat_ctx->pkg_ctxs[cat_ctx->pkg_cnt++] = |
117 |
+ tree_open_pkg(cat_ctx, de->d_name); |
118 |
+ if (pkg_ctx == NULL) |
119 |
+ cat_ctx->pkg_cnt--; |
120 |
+ } |
121 |
|
122 |
- while (cat_ctx->pkg_cur < cat_ctx->pkg_cnt) { |
123 |
- pkg_ctx = |
124 |
- tree_open_pkg(cat_ctx, |
125 |
- cat_ctx->pkg_de[cat_ctx->pkg_cur++]->d_name); |
126 |
- if (!pkg_ctx) |
127 |
- continue; |
128 |
- break; |
129 |
+ if (cat_ctx->ctx->pkgsortfunc != NULL) { |
130 |
+ qsort(cat_ctx->pkg_ctxs, cat_ctx->pkg_cnt, |
131 |
+ sizeof(*cat_ctx->pkg_ctxs), cat_ctx->ctx->pkgsortfunc); |
132 |
+ } |
133 |
} |
134 |
+ |
135 |
+ pkg_ctx = NULL; |
136 |
+ if (cat_ctx->pkg_cur < cat_ctx->pkg_cnt) |
137 |
+ pkg_ctx = cat_ctx->pkg_ctxs[cat_ctx->pkg_cur++]; |
138 |
} else { |
139 |
- const struct dirent *de; |
140 |
do { |
141 |
de = readdir(cat_ctx->dir); |
142 |
if (!de) |
143 |
|
144 |
diff --git a/libq/tree.h b/libq/tree.h |
145 |
index 7f05819..36554be 100644 |
146 |
--- a/libq/tree.h |
147 |
+++ b/libq/tree.h |
148 |
@@ -48,7 +48,7 @@ struct tree_cat_ctx { |
149 |
int fd; |
150 |
DIR *dir; |
151 |
tree_ctx *ctx; |
152 |
- struct dirent **pkg_de; |
153 |
+ tree_pkg_ctx **pkg_ctxs; |
154 |
size_t pkg_cnt; |
155 |
size_t pkg_cur; |
156 |
}; |