summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2012-07-23 07:59:11 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2012-07-29 10:16:15 +0100
commit20ad566d609bccdadf871dab1bc31a0e243f8710 (patch)
treefaea9496677371ab81ea2704183c01ce54d088df
parent98b0f956e7d16c2791cc00dbb75187b886e4cbcd (diff)
downloadpoky-20ad566d609bccdadf871dab1bc31a0e243f8710.tar.gz
buildhistory: improve performance of image info collection
Reduce the number of calls to the packaging tool, especially in the case of rpm, using helper utilities to gather the required information more efficiently where possible. (From OE-Core rev: d0b8a98c5b46c305afd389fc862b3bf0c6f1eaab) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/classes/buildhistory.bbclass51
-rw-r--r--meta/classes/rootfs_deb.bbclass28
-rw-r--r--meta/classes/rootfs_ipk.bbclass34
-rw-r--r--meta/classes/rootfs_rpm.bbclass33
-rw-r--r--meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c117
5 files changed, 162 insertions, 101 deletions
diff --git a/meta/classes/buildhistory.bbclass b/meta/classes/buildhistory.bbclass
index f0bf849860..ddb76e8771 100644
--- a/meta/classes/buildhistory.bbclass
+++ b/meta/classes/buildhistory.bbclass
@@ -285,48 +285,43 @@ buildhistory_get_image_installed() {
285 mkdir -p ${BUILDHISTORY_DIR_IMAGE} 285 mkdir -p ${BUILDHISTORY_DIR_IMAGE}
286 286
287 # Get list of installed packages 287 # Get list of installed packages
288 list_installed_packages | sort > ${BUILDHISTORY_DIR_IMAGE}/installed-package-names.txt 288 pkgcache="${BUILDHISTORY_DIR_IMAGE}/installed-packages.tmp"
289 INSTALLED_PKGS=`cat ${BUILDHISTORY_DIR_IMAGE}/installed-package-names.txt` 289 list_installed_packages file | sort > $pkgcache
290
291 cat $pkgcache | awk '{ print $1 }' > ${BUILDHISTORY_DIR_IMAGE}/installed-package-names.txt
292 cat $pkgcache | awk '{ print $2 }' | xargs -n1 basename > ${BUILDHISTORY_DIR_IMAGE}/installed-packages.txt
293
294 # Produce dependency graph
295 # First, filter out characters that cause issues for dot
296 rootfs_list_installed_depends | sed -e 's:-:_:g' -e 's:\.:_:g' -e 's:+::g' > ${BUILDHISTORY_DIR_IMAGE}/depends.tmp
297 # Change delimiter from pipe to -> and set style for recommend lines
298 sed -i -e 's:|: -> :' -e 's:\[REC\]:[style=dotted]:' -e 's:$:;:' ${BUILDHISTORY_DIR_IMAGE}/depends.tmp
299 # Add header, sorted and de-duped contents and footer and then delete the temp file
300 echo -e "digraph depends {\n node [shape=plaintext]" > ${BUILDHISTORY_DIR_IMAGE}/depends.dot
301 cat ${BUILDHISTORY_DIR_IMAGE}/depends.tmp | sort | uniq >> ${BUILDHISTORY_DIR_IMAGE}/depends.dot
302 echo "}" >> ${BUILDHISTORY_DIR_IMAGE}/depends.dot
303 rm ${BUILDHISTORY_DIR_IMAGE}/depends.tmp
290 304
291 # Produce installed package file and size lists and dependency graph 305 # Produce installed package sizes list
292 echo -n > ${BUILDHISTORY_DIR_IMAGE}/installed-packages.txt
293 echo -n > ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.tmp 306 echo -n > ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.tmp
294 echo -e "digraph depends {\n node [shape=plaintext]" > ${BUILDHISTORY_DIR_IMAGE}/depends.dot 307 cat $pkgcache | while read pkg pkgfile
295 for pkg in $INSTALLED_PKGS; do 308 do
296 pkgfile=`get_package_filename $pkg`
297 echo `basename $pkgfile` >> ${BUILDHISTORY_DIR_IMAGE}/installed-packages.txt
298 if [ -f $pkgfile ] ; then 309 if [ -f $pkgfile ] ; then
299 pkgsize=`du -k $pkgfile | head -n1 | awk '{ print $1 }'` 310 pkgsize=`du -k $pkgfile | head -n1 | awk '{ print $1 }'`
300 echo $pkgsize $pkg >> ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.tmp 311 echo $pkgsize $pkg >> ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.tmp
301 fi 312 fi
302 313 done
303 deps=`list_package_depends $pkg`
304 for dep in $deps ; do
305 echo "$pkg OPP $dep;" | sed -e 's:-:_:g' -e 's:\.:_:g' -e 's:+::g' | sed 's:OPP:->:g'
306 done
307
308 recs=`list_package_recommends $pkg`
309 for rec in $recs ; do
310 echo "$pkg OPP $rec [style=dotted];" | sed -e 's:-:_:g' -e 's:\.:_:g' -e 's:+::g' | sed 's:OPP:->:g'
311 done
312 done | sort | uniq >> ${BUILDHISTORY_DIR_IMAGE}/depends.dot
313 echo "}" >> ${BUILDHISTORY_DIR_IMAGE}/depends.dot
314
315 cat ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.tmp | sort -n -r | awk '{print $1 "\tKiB " $2}' > ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.txt 314 cat ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.tmp | sort -n -r | awk '{print $1 "\tKiB " $2}' > ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.txt
316 rm ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.tmp 315 rm ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.tmp
317 316
317 # We're now done with the cache, delete it
318 rm $pkgcache
319
318 # Produce some cut-down graphs (for readability) 320 # Produce some cut-down graphs (for readability)
319 grep -v kernel_image ${BUILDHISTORY_DIR_IMAGE}/depends.dot | grep -v kernel_2 | grep -v kernel_3 > ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel.dot 321 grep -v kernel_image ${BUILDHISTORY_DIR_IMAGE}/depends.dot | grep -v kernel_2 | grep -v kernel_3 > ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel.dot
320 grep -v libc6 ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel.dot | grep -v libgcc > ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel-nolibc.dot 322 grep -v libc6 ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel.dot | grep -v libgcc > ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel-nolibc.dot
321 grep -v update_ ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel-nolibc.dot > ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel-nolibc-noupdate.dot 323 grep -v update_ ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel-nolibc.dot > ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel-nolibc-noupdate.dot
322 grep -v kernel_module ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel-nolibc-noupdate.dot > ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel-nolibc-noupdate-nomodules.dot 324 grep -v kernel_module ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel-nolibc-noupdate.dot > ${BUILDHISTORY_DIR_IMAGE}/depends-nokernel-nolibc-noupdate-nomodules.dot
323
324 # Workaround for broken shell function dependencies
325 if false ; then
326 get_package_filename
327 list_package_depends
328 list_package_recommends
329 fi
330} 325}
331 326
332buildhistory_get_imageinfo() { 327buildhistory_get_imageinfo() {
diff --git a/meta/classes/rootfs_deb.bbclass b/meta/classes/rootfs_deb.bbclass
index a002b1ec02..750a8ca082 100644
--- a/meta/classes/rootfs_deb.bbclass
+++ b/meta/classes/rootfs_deb.bbclass
@@ -96,26 +96,24 @@ list_installed_packages() {
96 if [ "$1" = "arch" ] ; then 96 if [ "$1" = "arch" ] ; then
97 # Here we want the PACKAGE_ARCH not the deb architecture 97 # Here we want the PACKAGE_ARCH not the deb architecture
98 ${DPKG_QUERY_COMMAND} -W -f='${Package} ${PackageArch}\n' 98 ${DPKG_QUERY_COMMAND} -W -f='${Package} ${PackageArch}\n'
99 elif [ "$1" = "file" ] ; then
100 ${DPKG_QUERY_COMMAND} -W -f='${Package} ${Package}_${Version}_${Architecture}.deb\n' | while read pkg pkgfile
101 do
102 fullpath=`find ${DEPLOY_DIR_DEB} -name "$pkgfile" || true`
103 if [ "$fullpath" = "" ] ; then
104 echo "$pkg $pkgfile"
105 else
106 echo "$pkg $fullpath"
107 fi
108 done
99 else 109 else
100 ${DPKG_QUERY_COMMAND} -W -f='${Package}\n' 110 ${DPKG_QUERY_COMMAND} -W -f='${Package}\n'
101 fi 111 fi
102} 112}
103 113
104get_package_filename() { 114rootfs_list_installed_depends() {
105 fullname=`find ${DEPLOY_DIR_DEB} -name "$1_*.deb" || true` 115 # Cheat here a little bit by using the opkg query helper util
106 if [ "$fullname" = "" ] ; then 116 ${DPKG_QUERY_COMMAND} -W -f='Package: ${Package}\nDepends: ${Depends}\nRecommends: ${Recommends}\n\n' | opkg-query-helper.py
107 echo $name
108 else
109 echo $fullname
110 fi
111}
112
113list_package_depends() {
114 ${DPKG_QUERY_COMMAND} -s $1 | grep ^Depends | sed -e 's/^Depends: //' -e 's/,//g' -e 's:([=<>]* [^ )]*)::g'
115}
116
117list_package_recommends() {
118 ${DPKG_QUERY_COMMAND} -s $1 | grep ^Recommends | sed -e 's/^Recommends: //' -e 's/,//g' -e 's:([=<>]* [^ )]*)::g'
119} 117}
120 118
121rootfs_install_packages() { 119rootfs_install_packages() {
diff --git a/meta/classes/rootfs_ipk.bbclass b/meta/classes/rootfs_ipk.bbclass
index 7df97a014b..6cdd8f6062 100644
--- a/meta/classes/rootfs_ipk.bbclass
+++ b/meta/classes/rootfs_ipk.bbclass
@@ -131,33 +131,23 @@ remove_packaging_data_files() {
131list_installed_packages() { 131list_installed_packages() {
132 if [ "$1" = "arch" ] ; then 132 if [ "$1" = "arch" ] ; then
133 opkg-cl ${IPKG_ARGS_POST} status | opkg-query-helper.py -a 133 opkg-cl ${IPKG_ARGS_POST} status | opkg-query-helper.py -a
134 elif [ "$1" = "file" ] ; then
135 opkg-cl ${IPKG_ARGS_POST} status | opkg-query-helper.py -f | while read pkg pkgfile
136 do
137 fullpath=`find ${DEPLOY_DIR_IPK} -name "$pkgfile" || true`
138 if [ "$fullpath" = "" ] ; then
139 echo "$pkg $pkgfile"
140 else
141 echo "$pkg $fullpath"
142 fi
143 done
134 else 144 else
135 opkg-cl ${IPKG_ARGS_POST} list_installed | awk '{ print $1 }' 145 opkg-cl ${IPKG_ARGS_POST} list_installed | awk '{ print $1 }'
136 fi 146 fi
137} 147}
138 148
139get_package_filename() { 149rootfs_list_installed_depends() {
140 set +x 150 opkg-cl ${IPKG_ARGS_POST} status | opkg-query-helper.py
141 info=`opkg-cl ${IPKG_ARGS_POST} info $1 | grep -B 7 -A 7 "^Status.* \(\(installed\)\|\(unpacked\)\)" || true`
142 name=`echo "${info}" | awk '/^Package/ {printf $2"_"}'`
143 name=$name`echo "${info}" | awk -F: '/^Version/ {printf $NF"_"}' | sed 's/^\s*//g'`
144 name=$name`echo "${info}" | awk '/^Archi/ {print $2".ipk"}'`
145 set -x
146
147 fullname=`find ${DEPLOY_DIR_IPK} -name "$name" || true`
148 if [ "$fullname" = "" ] ; then
149 echo $name
150 else
151 echo $fullname
152 fi
153}
154
155list_package_depends() {
156 opkg-cl ${IPKG_ARGS_POST} info $1 | grep ^Depends | sed -e 's/^Depends: //' -e 's/,//g' -e 's:([=<>]* [^ )]*)::g'
157}
158
159list_package_recommends() {
160 opkg-cl ${IPKG_ARGS_POST} info $1 | grep ^Recommends | sed -e 's/^Recommends: //' -e 's/,//g' -e 's:([=<>]* [^ )]*)::g'
161} 151}
162 152
163rootfs_install_packages() { 153rootfs_install_packages() {
diff --git a/meta/classes/rootfs_rpm.bbclass b/meta/classes/rootfs_rpm.bbclass
index 1cc4a84495..c9258dfe39 100644
--- a/meta/classes/rootfs_rpm.bbclass
+++ b/meta/classes/rootfs_rpm.bbclass
@@ -143,40 +143,15 @@ RPM_QUERY_CMD = '${RPM} --root $INSTALL_ROOTFS_RPM -D "_dbpath ${rpmlibdir}" \
143list_installed_packages() { 143list_installed_packages() {
144 if [ "$1" = "arch" ] ; then 144 if [ "$1" = "arch" ] ; then
145 ${RPM_QUERY_CMD} -qa --qf "[%{NAME} %{ARCH}\n]" 145 ${RPM_QUERY_CMD} -qa --qf "[%{NAME} %{ARCH}\n]"
146 elif [ "$1" = "file" ] ; then
147 ${RPM_QUERY_CMD} -qa --qf "[%{NAME} %{PACKAGEORIGIN}\n]"
146 else 148 else
147 ${RPM_QUERY_CMD} -qa --qf "[%{NAME}\n]" 149 ${RPM_QUERY_CMD} -qa --qf "[%{NAME}\n]"
148 fi 150 fi
149} 151}
150 152
151get_package_filename() { 153rootfs_list_installed_depends() {
152 resolve_package_rpm ${RPMCONF_TARGET_BASE}-base_archs.conf $1 154 rpmresolve -d $INSTALL_ROOTFS_RPM/${rpmlibdir}
153}
154
155list_package_depends() {
156 pkglist=`list_installed_packages`
157
158 # REQUIRE* lists "soft" requirements (which we know as recommends and RPM refers to
159 # as "suggests") so filter these out with the help of awk
160 for req in `${RPM_QUERY_CMD} -q --qf "[%{REQUIRENAME} %{REQUIREFLAGS}\n]" $1 | awk '{ if( and($2, 0x80000) == 0) print $1 }'`; do
161 if echo "$req" | grep -q "^rpmlib" ; then continue ; fi
162
163 realpkg=""
164 for dep in $pkglist; do
165 if [ "$dep" = "$req" ] ; then
166 realpkg="1"
167 echo $req
168 break
169 fi
170 done
171
172 if [ "$realdep" = "" ] ; then
173 ${RPM_QUERY_CMD} -q --whatprovides $req --qf "%{NAME}\n"
174 fi
175 done
176}
177
178list_package_recommends() {
179 ${RPM_QUERY_CMD} -q --suggests $1
180} 155}
181 156
182rootfs_install_packages() { 157rootfs_install_packages() {
diff --git a/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c b/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c
index 9f6cdf28b8..2d9ed141f4 100644
--- a/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c
+++ b/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c
@@ -204,10 +204,104 @@ int processPackages(rpmts *ts, int tscount, const char *packagelistfn, int ignor
204 return rc; 204 return rc;
205} 205}
206 206
207int lookupProvider(rpmts ts, const char *req, char **provider)
208{
209 int rc = 0;
210 rpmmi provmi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, req, 0);
211 if(provmi) {
212 Header h;
213 if ((h = rpmmiNext(provmi)) != NULL) {
214 HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
215 he->tag = RPMTAG_NAME;
216 rc = (headerGet(h, he, 0) != 1);
217 if(rc==0)
218 *provider = strdup((char *)he->p.ptr);
219 }
220 (void)rpmmiFree(provmi);
221 }
222 else {
223 rc = -1;
224 }
225 return rc;
226}
227
228int printDepList(rpmts *ts, int tscount)
229{
230 int rc = 0;
231
232 if( tscount > 1 )
233 printf(">1 database specified with dependency list, using first only\n");
234
235 /* Get list of names */
236 rpmdb db = rpmtsGetRdb(ts[0]);
237 ARGV_t names = NULL;
238 rc = rpmdbMireApply(db, RPMTAG_NAME,
239 RPMMIRE_STRCMP, NULL, &names);
240 int nnames = argvCount(names);
241
242 /* Get list of NVRAs */
243 ARGV_t keys = NULL;
244 rc = rpmdbMireApply(db, RPMTAG_NVRA,
245 RPMMIRE_STRCMP, NULL, &keys);
246 if (keys) {
247 int i, j;
248 HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
249 int nkeys = argvCount(keys);
250 for(i=0; i<nkeys; i++) {
251 rpmmi mi = rpmtsInitIterator(ts[0], RPMTAG_NVRA, keys[i], 0);
252 Header h;
253 if ((h = rpmmiNext(mi)) != NULL) {
254 /* Get name of package */
255 he->tag = RPMTAG_NAME;
256 rc = (headerGet(h, he, 0) != 1);
257 char *name = strdup((char *)he->p.ptr);
258 /* Get its requires */
259 he->tag = RPMTAG_REQUIRENAME;
260 rc = (headerGet(h, he, 0) != 1);
261 ARGV_t reqs = (ARGV_t)he->p.ptr;
262 /* Get its requireflags */
263 he->tag = RPMTAG_REQUIREFLAGS;
264 rc = (headerGet(h, he, 0) != 1);
265 rpmuint32_t *reqflags = (rpmuint32_t *)he->p.ui32p;
266 for(j=0; j<he->c; j++) {
267 int k;
268 char *prov = NULL;
269 for(k=0; k<nnames; k++) {
270 if(strcmp(names[k], reqs[j]) == 0) {
271 prov = names[k];
272 break;
273 }
274 }
275 if(prov) {
276 if((int)reqflags[j] & 0x80000)
277 printf("%s|%s [REC]\n", name, prov);
278 else
279 printf("%s|%s\n", name, prov);
280 }
281 else {
282 rc = lookupProvider(ts[0], reqs[j], &prov);
283 if(rc==0 && prov) {
284 if((int)reqflags[j] & 0x80000)
285 printf("%s|%s [REC]\n", name, prov);
286 else
287 printf("%s|%s\n", name, prov);
288 free(prov);
289 }
290 }
291 }
292 free(name);
293 }
294 (void)rpmmiFree(mi);
295 }
296 }
297
298 return rc;
299}
300
207void usage() 301void usage()
208{ 302{
209 fprintf(stderr, "OpenEmbedded rpm resolver utility\n"); 303 fprintf(stderr, "OpenEmbedded rpm resolver utility\n");
210 fprintf(stderr, "syntax: rpmresolve [-i] <dblistfile> <packagelistfile>\n"); 304 fprintf(stderr, "syntax: rpmresolve [-i] [-d] <dblistfile> <packagelistfile>\n");
211} 305}
212 306
213int main(int argc, char **argv) 307int main(int argc, char **argv)
@@ -218,13 +312,17 @@ int main(int argc, char **argv)
218 int i; 312 int i;
219 int c; 313 int c;
220 int ignoremissing = 0; 314 int ignoremissing = 0;
315 int deplistmode = 0;
221 316
222 opterr = 0; 317 opterr = 0;
223 while ((c = getopt (argc, argv, "i")) != -1) { 318 while ((c = getopt (argc, argv, "id")) != -1) {
224 switch (c) { 319 switch (c) {
225 case 'i': 320 case 'i':
226 ignoremissing = 1; 321 ignoremissing = 1;
227 break; 322 break;
323 case 'd':
324 deplistmode = 1;
325 break;
228 case '?': 326 case '?':
229 if(isprint(optopt)) 327 if(isprint(optopt))
230 fprintf(stderr, "Unknown option `-%c'.\n", optopt); 328 fprintf(stderr, "Unknown option `-%c'.\n", optopt);
@@ -258,12 +356,17 @@ int main(int argc, char **argv)
258 return 1; 356 return 1;
259 } 357 }
260 358
261 if( argc - optind < 2 ) { 359 if(deplistmode) {
262 fprintf(stderr, "Please specify package list file\n"); 360 rc = printDepList(ts, tscount);
263 return 1; 361 }
362 else {
363 if( argc - optind < 2 ) {
364 fprintf(stderr, "Please specify package list file\n");
365 return 1;
366 }
367 const char *pkglistfn = argv[optind+1];
368 rc = processPackages(ts, tscount, pkglistfn, ignoremissing);
264 } 369 }
265 const char *pkglistfn = argv[optind+1];
266 rc = processPackages(ts, tscount, pkglistfn, ignoremissing);
267 370
268 for(i=0; i<tscount; i++) 371 for(i=0; i<tscount; i++)
269 (void) rpmtsCloseDB(ts[i]); 372 (void) rpmtsCloseDB(ts[i]);