Subject: pkg/36300: improvements of pkgtools/pkg_chk
To: None <pkg-manager@netbsd.org, gnats-admin@netbsd.org,>
From: None <cheusov@tut.by>
List: pkgsrc-bugs
Date: 05/09/2007 10:55:00
>Number:         36300
>Category:       pkg
>Synopsis:       improvements for pkgtools/pkg_chk
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Wed May 09 10:55:00 +0000 2007
>Originator:     cheusov@tut.by
>Release:        NetBSD 4.0_BETA2
>Organization:
Best regards, Aleksey Cheusov.
>Environment:
	
	
System: NetBSD chen.chizhovka.net 4.0_BETA2 NetBSD 4.0_BETA2 (GENERIC) #15: Sat Apr 28 23:42:26 EEST 2007 cheusov@chen.chizhovka.net:/srv/src/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
Fixes:
1) pkg_chk -L /dev/null
   or
   pkg_chk -L /dev/stderr
   or something similar
   run with root priviledges may completely break the system
2) check for mktemp result
3) scanning $PACKAGES/All needs too many fork(2) and this may significantly
   slow down the pkg_chk especially on platforms with slow fork(2)
   such as Interix. Even on NetBSD/i386 that has very fast fork
   xargs saves about 15% of the total time.

  test: pkg_chk-1.85 -abn on my old system (884 .tbz packages in PACKAGES/All/)
  101.00s real    81.27s user    32.00s system

  pkg_chk -abn with xargs
   86.88s real    69.87s user    18.64s system

4) pkg_info -B for hundreds or thousands packages is extreamly slow operation
   (see above). I suggest using cache by setting PKG_BIN_CACHE in mk.conf.

   pkg_chk -abn with xargs and cache 
    4.07s real     3.75s user     2.36s system

>Fix:

Index: files/pkg_chk.sh
===================================================================
RCS file: /cvsroot/pkgsrc/pkgtools/pkg_chk/files/pkg_chk.sh,v
retrieving revision 1.48
diff -u -r1.48 pkg_chk.sh
--- files/pkg_chk.sh	20 Apr 2007 09:50:21 -0000	1.48
+++ files/pkg_chk.sh	8 May 2007 22:43:34 -0000
@@ -176,13 +176,13 @@
 	extract_make_vars Makefile \
 		AWK GREP GZIP_CMD ID PACKAGES PKGCHK_CONF PKGCHK_NOTAGS \
 		PKGCHK_TAGS PKGCHK_UPDATE_CONF PKG_ADD PKG_DBDIR PKG_DELETE \
-		PKG_INFO PKG_SUFX SED SORT SU_CMD TSORT
+		PKG_INFO PKG_SUFX SED SORT SU_CMD TSORT PKG_BIN_CACHE
 	if [ -z "$PACKAGES" ];then
 	    PACKAGES=$PKGSRCDIR/packages
 	fi
     elif [ $MAKECONF != /dev/null ] ; then
 	extract_make_vars $MAKECONF PACKAGES PKGCHK_CONF PKGCHK_UPDATE_CONF \
-			PKGCHK_TAGS PKGCHK_NOTAGS PKG_SUFX
+			PKGCHK_TAGS PKGCHK_NOTAGS PKG_SUFX PKG_BIN_CACHE
 	if [ -z "$PACKAGES" ] ; then
 	    PACKAGES=`pwd`
 	fi
@@ -680,6 +680,9 @@
 fi
 
 MY_TMPDIR=`mktemp -d ${TMPDIR-/tmp}/${0##*/}.XXXXXX`
+if [ -z "$MY_TMPDIR" ]; then
+    exit 1
+fi
 MY_TMPFILE=$MY_TMPDIR/tmp
 
 # Hide PKG_PATH to avoid breakage in 'make' calls
@@ -726,7 +729,7 @@
 fi
 
 if [ -n "$opt_L" ] ; then
-    rm -f $opt_L
+    printf '' > $opt_L
 fi
 
 basedir=$(pwd)
@@ -741,6 +744,43 @@
     PACKAGES="$PACKAGES/All"
 fi
 
+list_bin_pkgs (){
+    ls -t $PACKAGES | grep "$PKG_SUFX_RE"'$' |
+    awk "{print \"$PACKAGES/\" \$0}"
+}
+
+bin_pkg_info_is_up_to_date (){
+    if test -f "$PKG_BIN_CACHE" && \
+	test "$PKG_BIN_CACHE" -nt "$PACKAGES"
+    then
+	return 0
+    else
+	return 1
+    fi
+}
+
+get_bin_pkg_info (){
+    if test -z "$PKG_BIN_CACHE"; then
+	list_bin_pkgs | xargs ${PKG_INFO} -. -B
+    elif bin_pkg_info_is_up_to_date; then
+	cat "$PKG_BIN_CACHE"
+    else
+	trap "rm -f $PKG_BIN_CACHE; exit 1" 0 1 2
+
+	list_bin_pkgs | xargs ${PKG_INFO} -. -B |
+	tee "$PKG_BIN_CACHE"
+
+	trap - 0 1 2
+    fi
+}
+
+bin_pkg_info2pkgdb (){
+    ${SED} -n -e "s|$PKG_SUFX_RE:*\$||" \
+	      -e 's|^PKGPATH=||p' \
+	      -e 's|^Information.* .*/||p' |
+    ${AWK} '{getline name; printf "%s:%s ", name, $0}'
+}
+
 if [ "`${ID} -u`" = 0 ] ; then
     SU_CMD=
 fi
@@ -775,12 +815,7 @@
 	*)
 	    if [ -d "$PACKAGES" ] ; then
 		msg_progress Scan $PACKAGES
-		cd $PACKAGES
-		for f in `ls -t | grep "$PKG_SUFX_RE"'$'` ; do # Sort by time to pick up newest first
-		    PKGDIR=`${PKG_INFO} -. -B $PACKAGES/$f|${AWK} -F= '$1=="PKGPATH"{print $2}'`
-		    PKGNAME=`echo $f | ${SED} "s/$PKG_SUFX"'$//'`
-		    PKGDB="${PKGDB} $PKGDIR:$PKGNAME"
-		done
+		PKGDB=$(get_bin_pkg_info | bin_pkg_info2pkgdb)
 		PKGSRCDIR=NONE
 	    fi;;
     esac

>Unformatted: