summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2012-07-23 10:43:22 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2012-07-29 10:16:14 +0100
commita73c25d2ded3a72159f2ce527e7307808c734686 (patch)
tree5e27f29a2b6c6b91cf20a64508878646013e2ba7
parent656726ad6044d8b7e5661251a985770c93cb9242 (diff)
downloadpoky-a73c25d2ded3a72159f2ce527e7307808c734686.tar.gz
classes/rootfs_rpm: improve speed of RPM rootfs construction
Improve the performance of the RPM backend during do_rootfs by performing most of the package name to file resolution in a separate utility written in C, processing the entire list of packages at once rather than running rpm on the command line which loads the RPM database for every package. (From OE-Core rev: 9135d351ba7cb21e50239d2b310565680bd4fdca) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/classes/package_rpm.bbclass109
-rw-r--r--meta/classes/rootfs_rpm.bbclass1
-rw-r--r--meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c273
-rw-r--r--meta/recipes-devtools/rpm/rpmresolve_1.0.bb22
4 files changed, 341 insertions, 64 deletions
diff --git a/meta/classes/package_rpm.bbclass b/meta/classes/package_rpm.bbclass
index 983be4cfd0..29018e9cca 100644
--- a/meta/classes/package_rpm.bbclass
+++ b/meta/classes/package_rpm.bbclass
@@ -197,6 +197,45 @@ rpm_update_pkg () {
197 fi 197 fi
198} 198}
199 199
200process_pkg_list_rpm() {
201 local insttype=$1
202 shift
203 local pkgs="$@"
204 local confbase=${INSTALL_CONFBASE_RPM}
205
206 echo -n > ${target_rootfs}/install/base_archs.pkglist
207 echo -n > ${target_rootfs}/install/ml_archs.pkglist
208
209 for pkg in $pkgs; do
210 echo "Processing $pkg..."
211
212 archvar=base_archs
213 ml_pkg=$pkg
214 for i in ${MULTILIB_PREFIX_LIST} ; do
215 subst=${pkg#${i}-}
216 if [ $subst != $pkg ] ; then
217 ml_pkg=$subst
218 archvar=ml_archs
219 break
220 fi
221 done
222
223 echo $ml_pkg >> ${target_rootfs}/install/$archvar.pkglist
224 done
225
226 local manifestpfx="install"
227 local extraopt=""
228 if [ "$insttype" = "attemptonly" ] ; then
229 manifestpfx="install_attemptonly"
230 extraopt="-i"
231 fi
232
233 rpmresolve $extraopt ${confbase}-base_archs.conf ${target_rootfs}/install/base_archs.pkglist >> ${target_rootfs}/install/${manifestpfx}.manifest
234 if [ -s ${target_rootfs}/install/ml_archs.pkglist ] ; then
235 rpmresolve $extraopt ${confbase}-ml_archs.conf ${target_rootfs}/install/ml_archs.pkglist >> ${target_rootfs}/install/${manifestpfx}_multilib.manifest
236 fi
237}
238
200# 239#
201# install a bunch of packages using rpm 240# install a bunch of packages using rpm
202# the following shell variables needs to be set before calling this func: 241# the following shell variables needs to be set before calling this func:
@@ -256,55 +295,12 @@ package_install_internal_rpm () {
256 # Uclibc builds don't provide this stuff... 295 # Uclibc builds don't provide this stuff...
257 if [ x${TARGET_OS} = "xlinux" ] || [ x${TARGET_OS} = "xlinux-gnueabi" ] ; then 296 if [ x${TARGET_OS} = "xlinux" ] || [ x${TARGET_OS} = "xlinux-gnueabi" ] ; then
258 if [ ! -z "${package_linguas}" ]; then 297 if [ ! -z "${package_linguas}" ]; then
259 for pkg in ${package_linguas}; do 298 process_pkg_list_rpm linguas ${package_linguas}
260 echo "Processing $pkg..."
261
262 archvar=base_archs
263 manifest=install.manifest
264 ml_prefix=`echo ${pkg} | cut -d'-' -f1`
265 ml_pkg=$pkg
266 for i in ${MULTILIB_PREFIX_LIST} ; do
267 if [ ${ml_prefix} = ${i} ]; then
268 ml_pkg=$(echo ${pkg} | sed "s,^${ml_prefix}-\(.*\),\1,")
269 archvar=ml_archs
270 manifest=install_multilib.manifest
271 break
272 fi
273 done
274
275 pkg_name=$(resolve_package_rpm ${confbase}-${archvar}.conf ${ml_pkg})
276 if [ -z "$pkg_name" ]; then
277 echo "Unable to find package $pkg ($ml_pkg)!"
278 exit 1
279 fi
280 echo $pkg_name >> ${target_rootfs}/install/${manifest}
281 done
282 fi 299 fi
283 fi 300 fi
284 if [ ! -z "${package_to_install}" ]; then
285 for pkg in ${package_to_install} ; do
286 echo "Processing $pkg..."
287 301
288 archvar=base_archs 302 if [ ! -z "${package_to_install}" ]; then
289 manifest=install.manifest 303 process_pkg_list_rpm default ${package_to_install}
290 ml_prefix=`echo ${pkg} | cut -d'-' -f1`
291 ml_pkg=$pkg
292 for i in ${MULTILIB_PREFIX_LIST} ; do
293 if [ ${ml_prefix} = ${i} ]; then
294 ml_pkg=$(echo ${pkg} | sed "s,^${ml_prefix}-\(.*\),\1,")
295 archvar=ml_archs
296 manifest=install_multilib.manifest
297 break
298 fi
299 done
300
301 pkg_name=$(resolve_package_rpm ${confbase}-${archvar}.conf ${ml_pkg})
302 if [ -z "$pkg_name" ]; then
303 echo "Unable to find package $pkg ($ml_pkg)!"
304 exit 1
305 fi
306 echo $pkg_name >> ${target_rootfs}/install/${manifest}
307 done
308 fi 304 fi
309 305
310 # Normal package installation 306 # Normal package installation
@@ -324,24 +320,9 @@ package_install_internal_rpm () {
324 320
325 if [ ! -z "${package_attemptonly}" ]; then 321 if [ ! -z "${package_attemptonly}" ]; then
326 echo "Adding attempt only packages..." 322 echo "Adding attempt only packages..."
327 for pkg in ${package_attemptonly} ; do 323 process_pkg_list_rpm attemptonly ${package_attemptonly}
328 echo "Processing $pkg..." 324 cat ${target_rootfs}/install/install_attemptonly.manifest | while read pkg_name
329 archvar=base_archs 325 do
330 ml_prefix=`echo ${pkg} | cut -d'-' -f1`
331 ml_pkg=$pkg
332 for i in ${MULTILIB_PREFIX_LIST} ; do
333 if [ ${ml_prefix} = ${i} ]; then
334 ml_pkg=$(echo ${pkg} | sed "s,^${ml_prefix}-\(.*\),\1,")
335 archvar=ml_archs
336 break
337 fi
338 done
339
340 pkg_name=$(resolve_package_rpm ${confbase}-${archvar}.conf ${ml_pkg})
341 if [ -z "$pkg_name" ]; then
342 echo "Note: Unable to find package $pkg ($ml_pkg) -- PACKAGE_INSTALL_ATTEMPTONLY"
343 continue
344 fi
345 echo "Attempting $pkg_name..." >> "`dirname ${BB_LOGFILE}`/log.do_${task}_attemptonly.${PID}" 326 echo "Attempting $pkg_name..." >> "`dirname ${BB_LOGFILE}`/log.do_${task}_attemptonly.${PID}"
346 ${RPM} --predefine "_rpmds_sysinfo_path ${target_rootfs}/etc/rpm/sysinfo" \ 327 ${RPM} --predefine "_rpmds_sysinfo_path ${target_rootfs}/etc/rpm/sysinfo" \
347 --predefine "_rpmrc_platform_path ${target_rootfs}/etc/rpm/platform" \ 328 --predefine "_rpmrc_platform_path ${target_rootfs}/etc/rpm/platform" \
diff --git a/meta/classes/rootfs_rpm.bbclass b/meta/classes/rootfs_rpm.bbclass
index 4551f7a608..cd9c5ab778 100644
--- a/meta/classes/rootfs_rpm.bbclass
+++ b/meta/classes/rootfs_rpm.bbclass
@@ -11,6 +11,7 @@ IMAGE_ROOTFS_EXTRA_SPACE_append = "${@base_contains("PACKAGE_INSTALL", "zypper",
11ROOTFS_PKGMANAGE_BOOTSTRAP = "" 11ROOTFS_PKGMANAGE_BOOTSTRAP = ""
12 12
13do_rootfs[depends] += "rpm-native:do_populate_sysroot" 13do_rootfs[depends] += "rpm-native:do_populate_sysroot"
14do_rootfs[depends] += "rpmresolve-native:do_populate_sysroot"
14 15
15# Needed for update-alternatives 16# Needed for update-alternatives
16do_rootfs[depends] += "opkg-native:do_populate_sysroot" 17do_rootfs[depends] += "opkg-native:do_populate_sysroot"
diff --git a/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c b/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c
new file mode 100644
index 0000000000..9f6cdf28b8
--- /dev/null
+++ b/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c
@@ -0,0 +1,273 @@
1/* OpenEmbedded RPM resolver utility
2
3 Written by: Paul Eggleton <paul.eggleton@linux.intel.com>
4
5 Copyright 2012 Intel Corporation
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20*/
21
22#include <ctype.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <unistd.h>
26#include <fcntl.h>
27#include <sys/stat.h>
28
29#include <rpmdb.h>
30#include <rpmtypes.h>
31#include <rpmtag.h>
32#include <rpmts.h>
33#include <rpmmacro.h>
34#include <rpmcb.h>
35#include <rpmlog.h>
36#include <argv.h>
37#include <mire.h>
38
39int getPackageStr(rpmts ts, const char *NVRA, rpmTag tag, char **value)
40{
41 int rc = -1;
42 rpmmi mi = rpmtsInitIterator(ts, RPMTAG_NVRA, NVRA, 0);
43 Header h;
44 if ((h = rpmmiNext(mi)) != NULL) {
45 HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
46 he->tag = tag;
47 rc = (headerGet(h, he, 0) != 1);
48 if(rc==0)
49 *value = strdup((char *)he->p.ptr);
50 }
51 (void)rpmmiFree(mi);
52 return rc;
53}
54
55int loadTs(rpmts **ts, int *tsct, const char *dblistfn)
56{
57 int count = 0;
58 int sz = 5;
59 int rc = 0;
60 int listfile = 1;
61 struct stat st_buf;
62
63 rc = stat(dblistfn, &st_buf);
64 if(rc != 0) {
65 perror("stat");
66 return 1;
67 }
68 if(S_ISDIR(st_buf.st_mode))
69 listfile = 0;
70
71 if(listfile) {
72 *ts = malloc(sz * sizeof(rpmts));
73 FILE *f = fopen(dblistfn, "r" );
74 if(f) {
75 char line[2048];
76 while(fgets(line, sizeof(line), f)) {
77 int len = strlen(line) - 1;
78 if(len > 0)
79 // Trim trailing whitespace
80 while(len > 0 && isspace(line[len]))
81 line[len--] = '\0';
82
83 if(len > 0) {
84 // Expand array if needed
85 if(count == sz) {
86 sz += 5;
87 *ts = (rpmts *)realloc(*ts, sz);
88 }
89
90 char *dbpathm = malloc(strlen(line) + 10);
91 sprintf(dbpathm, "_dbpath %s", line);
92 rpmDefineMacro(NULL, dbpathm, RMIL_CMDLINE);
93 free(dbpathm);
94
95 rpmts tsi = rpmtsCreate();
96 (*ts)[count] = tsi;
97 rc = rpmtsOpenDB(tsi, O_RDONLY);
98 if( rc ) {
99 fprintf(stderr, "Failed to open database %s\n", line);
100 rc = -1;
101 break;
102 }
103
104 count++;
105 }
106 }
107 fclose(f);
108 *tsct = count;
109 }
110 else {
111 perror(dblistfn);
112 rc = -1;
113 }
114 }
115 else {
116 // Load from single database
117 *ts = malloc(sizeof(rpmts));
118 char *dbpathm = malloc(strlen(dblistfn) + 10);
119 sprintf(dbpathm, "_dbpath %s", dblistfn);
120 rpmDefineMacro(NULL, dbpathm, RMIL_CMDLINE);
121 free(dbpathm);
122
123 rpmts tsi = rpmtsCreate();
124 (*ts)[0] = tsi;
125 rc = rpmtsOpenDB(tsi, O_RDONLY);
126 if( rc ) {
127 fprintf(stderr, "Failed to open database %s\n", dblistfn);
128 rc = -1;
129 }
130 *tsct = 1;
131 }
132
133 return rc;
134}
135
136int processPackages(rpmts *ts, int tscount, const char *packagelistfn, int ignoremissing)
137{
138 int rc = 0;
139 int count = 0;
140 int sz = 100;
141 int i = 0;
142 int missing = 0;
143
144 FILE *f = fopen(packagelistfn, "r" );
145 if(f) {
146 char line[255];
147 while(fgets(line, sizeof(line), f)) {
148 int len = strlen(line) - 1;
149 if(len > 0)
150 // Trim trailing whitespace
151 while(len > 0 && isspace(line[len]))
152 line[len--] = '\0';
153
154 if(len > 0) {
155 int found = 0;
156 for(i=0; i<tscount; i++) {
157 ARGV_t keys = NULL;
158 rpmdb db = rpmtsGetRdb(ts[i]);
159 rc = rpmdbMireApply(db, RPMTAG_NAME,
160 RPMMIRE_STRCMP, line, &keys);
161 if (keys) {
162 int nkeys = argvCount(keys);
163 if( nkeys == 1 ) {
164 char *value = NULL;
165 rc = getPackageStr(ts[i], keys[0], RPMTAG_PACKAGEORIGIN, &value);
166 if(rc == 0)
167 printf("%s\n", value);
168 else
169 fprintf(stderr, "Failed to get package origin for %s\n", line);
170 found = 1;
171 }
172 else if( nkeys > 1 ) {
173 fprintf(stderr, "Multiple matches for %s!\n", line);
174 }
175 }
176 if(found)
177 break;
178 }
179
180 if( !found ) {
181 if( ignoremissing ) {
182 fprintf(stderr, "unable to find package %s - ignoring\n", line);
183 }
184 else {
185 fprintf(stderr, "unable to find package %s\n", line);
186 missing = 1;
187 }
188 }
189 }
190 count++;
191 }
192 fclose(f);
193
194 if( missing ) {
195 fprintf(stderr, "ERROR: some packages were missing\n");
196 rc = 1;
197 }
198 }
199 else {
200 perror(packagelistfn);
201 rc = -1;
202 }
203
204 return rc;
205}
206
207void usage()
208{
209 fprintf(stderr, "OpenEmbedded rpm resolver utility\n");
210 fprintf(stderr, "syntax: rpmresolve [-i] <dblistfile> <packagelistfile>\n");
211}
212
213int main(int argc, char **argv)
214{
215 rpmts *ts = NULL;
216 int tscount = 0;
217 int rc = 0;
218 int i;
219 int c;
220 int ignoremissing = 0;
221
222 opterr = 0;
223 while ((c = getopt (argc, argv, "i")) != -1) {
224 switch (c) {
225 case 'i':
226 ignoremissing = 1;
227 break;
228 case '?':
229 if(isprint(optopt))
230 fprintf(stderr, "Unknown option `-%c'.\n", optopt);
231 else
232 fprintf(stderr, "Unknown option character `\\x%x'.\n",
233 optopt);
234 usage();
235 return 1;
236 default:
237 abort();
238 }
239 }
240
241 if( argc - optind < 1 ) {
242 usage();
243 return 1;
244 }
245
246 const char *dblistfn = argv[optind];
247
248 //rpmSetVerbosity(RPMLOG_DEBUG);
249
250 rpmReadConfigFiles( NULL, NULL );
251 rpmDefineMacro(NULL, "__dbi_txn create nofsync", RMIL_CMDLINE);
252
253 rc = loadTs(&ts, &tscount, dblistfn);
254 if( rc )
255 return 1;
256 if( tscount == 0 ) {
257 fprintf(stderr, "Please specify database list file or database location\n");
258 return 1;
259 }
260
261 if( argc - optind < 2 ) {
262 fprintf(stderr, "Please specify package list file\n");
263 return 1;
264 }
265 const char *pkglistfn = argv[optind+1];
266 rc = processPackages(ts, tscount, pkglistfn, ignoremissing);
267
268 for(i=0; i<tscount; i++)
269 (void) rpmtsCloseDB(ts[i]);
270 free(ts);
271
272 return rc;
273}
diff --git a/meta/recipes-devtools/rpm/rpmresolve_1.0.bb b/meta/recipes-devtools/rpm/rpmresolve_1.0.bb
new file mode 100644
index 0000000000..f8750e02ba
--- /dev/null
+++ b/meta/recipes-devtools/rpm/rpmresolve_1.0.bb
@@ -0,0 +1,22 @@
1SUMMARY = "OpenEmbedded RPM resolver utility"
2DESCRIPTION = "OpenEmbedded RPM resolver - performs RPM database lookups in batches to avoid \
3 repeated invocations of rpm on the command line."
4DEPENDS = "rpm"
5LICENSE = "GPLv2"
6LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
7PR = "r0"
8
9SRC_URI = "file://rpmresolve.c"
10
11S = "${WORKDIR}"
12
13do_compile() {
14 ${CC} ${CFLAGS} -ggdb -I${STAGING_INCDIR}/rpm ${LDFLAGS} rpmresolve.c -o rpmresolve -lrpmbuild -lrpm -lrpmio -lrpmdb -lpopt
15}
16
17do_install() {
18 install -d ${D}${bindir}
19 install -m 0755 rpmresolve ${D}${bindir}
20}
21
22BBCLASSEXTEND = "native"