[devel] RFC: тестирование входящих пакетов полной пересборкой сизифа

Alexey Tourbin =?iso-8859-1?q?at_=CE=C1_altlinux=2Eru?=
Чт Авг 23 17:23:04 MSD 2007


On Thu, Aug 23, 2007 at 02:19:45PM +0400, Alexey Tourbin wrote:
> On Wed, Aug 22, 2007 at 01:43:21AM +0400, Alexey Tourbin wrote:
> > "Полную пересборку сизифа" следует трактовать не буквально, а вот как:
> > пересобрать все пакеты, у которых при сборке в билдрут ставится один из
> > новых пакетов.  Это означает, что, с учетом поступивших пакетов, для
> > каждого src.rpm пакета формируется список пакетов для билдрута.  Если в
> > списке пакетов для билдрута оказывается новый пакет, то этот src.rpm
> > пакет подлежит пересборке.
> 
> [...]
> 
> > Техническая проблема на подступах к определению списка пакетов, подлежащих
> > пересборке, было в том, что нужно научиться очень быстро строить список
> > пакетов в билдруте при сборке каждого src.rpm пакета.  Стандартный
> > способ (который используется в hasher, через --print-uris) занимает
> > порядка одной секунды на src.rpm пакет.  Это связано с тем, что apt всё
> > время перечитывает свой кеш.  В сизифе около 6000 src.rpm пакетов, значит,
> > определять, какие из них нужно пересобрать, можно около 2 часов.  Это
> > даже больше, чем может занять последующая пересборка обнаруженным таким
> > образом src.rpm пакетов.  У меня сейчас зреет решение, как немного
> > захачить апт и написать к нему скрипт на lua, чтобы построение списка
> > пакетов для пересборки по времени сводилось к чтению хедеров src.rpm
> > пакетов.
> 
> Я придумал решение (захачил апт, чтобы он не перечитывал кеш, написал
> скрипт на lua и кое-что ещё), при котором скорость --print-uris на моей
> машине сейчас около 5 src.rpm пакетов в секунду.  Получается всё равно
> достаточно много -- выяснять, какие из 6000 src.rpm пакетов нужно
> пересобирать, придётся минут 20.  Боюсь, что намного быстрее уже не
> получится.
> 
> Опубликую и напишу в ближайшее время.

git.alt:/people/at/packages/query-rebuild.git

Суть дела в следующем.

apt-get.cc модифицируется в двух местах.

1) Пишем обёртку для DoInstall и добавляем DoInstall в число функций,
доступных из lua скриптов:
@@ -3173,6 +3219,7 @@ bool DoScript(CommandLine &CmdL)
       _config->Set("Scripts::AptGet::Script::", *I);
 
    _lua->SetGlobal("commit_ask", 1);
+   _lua->SetGlobal("DoInstall", lua_DoInstall);
    _lua->RunScripts("Scripts::AptGet::Script");
    double Ask = _lua->GetGlobalNum("commit_ask");
    _lua->ResetGlobals();

2) Делаем так, чтобы DoInstall не перечитывал свой кеш.
Для этого вводится статическая локальная переменная.
@@ -1967,10 +1967,22 @@ bool DoUpgrade(CommandLine &CmdL)
 /* Install named packages */
 bool DoInstall(CommandLine &CmdL)
 {
+#if 1
+   static CacheFile *GCache = 0;
+   if (!GCache) {
+      GCache = new CacheFile;
+      if (GCache->OpenForInstall() == false)
+	 return false;
+   }
+   CacheFile &Cache = *GCache;
+   if (Cache.CheckDeps(CmdL.FileSize() != 1) == false)
+      return false;
+#else
    CacheFile Cache;
    if (Cache.OpenForInstall() == false || 
        Cache.CheckDeps(CmdL.FileSize() != 1) == false)
       return false;
+#endif
    
    // Enter the special broken fixing mode if the user specified arguments
    bool BrokenFix = false;

3) Пишется вспомогательный скрипт, который очень быстро "опрашивает"
BuildRequires пакетов, примерно так же, как это делается в hasher.
Формат вывода скрипта:
<src-rpm-basename> <deps>+
Суть скрипта такая

	deps=$(rpmquery -pR "$f") ||
		{ echo >&2 "${0##*/}: failed to query $f"; return 1; }
	deps="$(printf %s "$deps" |grep -v '^rpmlib(' |LC_ALL=C tr -d [[:blank:]])"
	[ -z "$deps" ] || printf "%s %s\n" "${f##*/}" "$(printf %s "$deps" |tr -s '[:space:]' ' ')"

Я написал полностью аналогичный скрипт на перле, который работает в 100
раз быстрее шелловского.

$ time ./query-pR.pl /ALT/Sisyphus/files/SRPMS >.pR      
./query-pR.pl /ALT/Sisyphus/files/SRPMS > .pR  3.53s user 1.38s system 79% cpu 6.170 total
$ head -2 .pR
7colors-0.80-alt5.src.rpm ORBit-devel XFree86-devel XFree86-libs esound-devel glib-devel gnome-libs-devel gtk+-devel imlib-devel libaudiofile-devel libdb1-devel xpm-devel
a2ps-4.13-alt3.src.rpm ImageMagick flex ghostscript-common ghostscript-utils groff-base gv gzip-utils psutils tetex-core tetex-dvips tetex-latex xorg-x11-devel
$

4) Пишется скрипт print-uris.lua который будет вызывать DoInstall и
вычислять содержимое билдрута для каждого src.rpm пакета (из предыдущего
файла .pR, который будет подключен к stdin).  Суть скрипта в следущем:

	print_uris("basesystem", {"basesystem"}) -- initialize cache
	print_uris("rpm-build", {"rpm-build"})

Теперь в аптовском кеше сидит "установленный" basesystem+rpm-build.
На каждый src.rpm пакет lua будет форкаться (чтобы сохранить кеш).

	for line in io.lines() do
		...
		fork_print_uris(rpm, deps)
	end

В вывод print_uris добавлены строчки-маркеры BEGIN и END.
Вот как это работает.

$ hsh --init $TMPDIR/build
$ chmod -w $TMPDIR/build/aptbox/var/lib/rpm		# НУЖЕН ЧМОД
$ ls ./apt-get
./apt-get						# МОДИФИЦИРОВАННЫЙ
$ PATH=$PWD:$PATH $TMPDIR/build/aptbox/apt-get -qq -y script ./print-uris.lua <.pR
BEGIN basesystem
END basesystem true
BEGIN rpm-build
END rpm-build true
BEGIN 7colors-0.80-alt5.src.rpm
'file:/ALT/Sisyphus/i586/RPMS.classic/glib-1.2.10-alt12.i586.rpm' glib_1.2.10-alt12_i586.rpm 81314 6cb31aaa2875a1f0d0768d1435a4a435
'file:/ALT/Sisyphus/i586/RPMS.classic/libORBit-0.5.17-alt3.i586.rpm' libORBit_0.5.17-alt3_i586.rpm 169128 1097a7e5b1ccaa786e27271b7155be1a
'file:/ALT/Sisyphus/i586/RPMS.classic/ORBit-0.5.17-alt3.i586.rpm' ORBit_0.5.17-alt3_i586.rpm 127941 5f49b6b61338887fed13f2de967c00fe
'file:/ALT/Sisyphus/i586/RPMS.classic/libfontenc-1.0.4-alt1.i586.rpm' libfontenc_1.0.4-alt1_i586.rpm 13013 d5d031c9741e3de1e08b2dcd21dd26a5
'file:/ALT/Sisyphus/i586/RPMS.classic/libfreetype-2.3.5-alt2.i586.rpm' libfreetype_2.3.5-alt2_i586.rpm 315157 7447bc73a08199e18da1c49dad5fd21
...
END 7colors-0.80-alt5.src.rpm true
BEGIN a2ps-4.13-alt3.src.rpm
'file:/ALT/Sisyphus/i586/RPMS.classic/libfontenc-1.0.4-alt1.i586.rpm' libfontenc_1.0.4-alt1_i586.rpm 13013 d5d031c9741e3de1e08b2dcd21dd26a5
'file:/ALT/Sisyphus/i586/RPMS.classic/libfreetype-2.3.5-alt2.i586.rpm' libfreetype_2.3.5-alt2_i586.rpm 315157 7447bc73a08199e18da1c49dad5fd21
...
END a2ps-4.13-alt3.src.rpm true
BEGIN a52dec-0.7.4-alt5.src.rpm
END a52dec-0.7.4-alt5.src.rpm true
BEGIN aalib-1.4-alt2rc5.src.rpm
'file:/ALT/Sisyphus/i586/RPMS.classic/libX11-locales-1.1.3-alt3.i586.rpm' libX11-locales_3%3a1.1.3-alt3_i586.rpm 186817 19f61bc3fbf7c8248e43287d8ac653e1
'file:/ALT/Sisyphus/i586/RPMS.classic/libgpm-devel-1.20.1-alt8.i586.rpm' libgpm-devel_1.20.1-alt8_i586.rpm 11727 016186297ea138acd158f8ccd4b95347
...
END aalib-1.4-alt2rc5.src.rpm true
BEGIN abinit-4.6.5-alt1.src.rpm
...
$

То есть это обычный вывод apt-get install --print-uris, только сделанный
в цикле и дополненный маркерами 
	BEGIN <src-rpm-basename>
	END <src-rpm-basename> <true|false>

5) Теперь этот вывод несложно обработать скриптом print-uris-filter.awk,
чтобы на выходе получить таблицу
<src-rpm-basename> <inst-rpm-basename>
Эта таблица означает, что для src.rpm пакета <src-rpm-basename>
в билдрут будет ставиться собранный rpm пакет <inst-rpm-basename>.

$ head .pR >.pR1
$ PATH=$PWD:$PATH $TMPDIR/build/aptbox/apt-get -qq -y script ./print-uris.lua <.pR1 >.uris
$ awk -f ./print-uris-filter.awk .uris |head    
7colors-0.80-alt5.src.rpm       glib-1.2.10-alt12.i586.rpm
7colors-0.80-alt5.src.rpm       libORBit-0.5.17-alt3.i586.rpm
7colors-0.80-alt5.src.rpm       ORBit-0.5.17-alt3.i586.rpm
7colors-0.80-alt5.src.rpm       libfontenc-1.0.4-alt1.i586.rpm
7colors-0.80-alt5.src.rpm       libfreetype-2.3.5-alt2.i586.rpm
7colors-0.80-alt5.src.rpm       libXfont-1.2.8-alt2.i586.rpm
7colors-0.80-alt5.src.rpm       bdftopcf-1.0.1-alt1.i586.rpm
7colors-0.80-alt5.src.rpm       libdb1-1.85-alt5.i586.rpm
7colors-0.80-alt5.src.rpm       db1-utils-1.85-alt5.i586.rpm
7colors-0.80-alt5.src.rpm       libaudiofile-0.2.6-alt2.i586.rpm
$ awk -f ./print-uris-filter.awk .uris |sort -u -k1,1
7colors-0.80-alt5.src.rpm       glib-1.2.10-alt12.i586.rpm
a2ps-4.13-alt3.src.rpm  libfontenc-1.0.4-alt1.i586.rpm
aalib-1.4-alt2rc5.src.rpm       libX11-locales-1.1.3-alt3.i586.rpm
abinit-4.6.5-alt1.src.rpm       gcc-fortran-common-1.4.10-alt2.i586.rpm
abiword-2.4.6-alt2.src.rpm      libIDL-0.8.8-alt1.i586.rpm
abook-0.5.6-alt1.src.rpm        libtinfo-devel-5.6-alt3.i586.rpm
abuse_sdl-0.7.0-alt4.src.rpm    ca-certificates-2007.02.06-alt1.noarch.rpm
acidrip-0.14-alt1.src.rpm       ca-certificates-2007.02.06-alt1.noarch.rpm
acl-2.2.39-alt1.0.src.rpm       libattr-devel-2.4.32-alt1.0.i586.rpm
$

Теперь задача почти решена.  Мы имеем вновь пришедшие пакеты
<inst-rpm-basename>, и хотим узнать, какие <src-rpm-basename>
подлежат пересборке.  Это тривиальный join по этой таблице.
----------- следующая часть -----------
Было удалено вложение не в текстовом формате...
Имя     : =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Тип     : application/pgp-signature
Размер  : 189 байтов
Описание: =?iso-8859-1?q?=CF=D4=D3=D5=D4=D3=D4=D7=D5=C5=D4?=
Url     : <http://lists.altlinux.org/pipermail/devel/attachments/20070823/b33cb4ab/attachment-0001.bin>


Подробная информация о списке рассылки Devel