ALT Linux Team development discussions
 help / color / mirror / Atom feed
From: Alexey Tourbin <at@altlinux.ru>
To: devel@lists.altlinux.org
Subject: Re: [devel] changelogs for apt repo
Date: Sun, 18 May 2008 06:07:51 +0400
Message-ID: <20080518020751.GD9319@solemn.turbinal> (raw)
In-Reply-To: <20080517190034.GA9319@solemn.turbinal> <20080517053427.GJ19126@solemn.turbinal>

[-- Attachment #1: Type: text/plain, Size: 12785 bytes --]

On Sat, May 17, 2008 at 09:34:27AM +0400, Alexey Tourbin wrote:
> Теперь остаётся выяснить, сколько это занимает места.
> 
> Обычная генерация сизифа:
> 
> $ cp -prs /ALT/Sisyphus/x86_64 /ALT/Sisyphus/noarch .
> $ rm -f x86_64/base/* noarch/base/*
> $ PATH=$PWD:$PATH genbasedir --topdir=$PWD x86_64
> $ PATH=$PWD:$PATH genbasedir --topdir=$PWD noarch
> $ du -bk x86_64/base/pkglist.classic.bz2 noarch/base/pkglist.classic.bz2 
> 2421    x86_64/base/pkglist.classic.bz2
> 1049    noarch/base/pkglist.classic.bz2
> $ 
> 
> Генерация с опцией --changelog-since=2007-01-01:
> 
> $ PATH=$PWD:$PATH genbasedir --topdir=$PWD --changelog-since=2007-01-01 x86_64
> $ PATH=$PWD:$PATH genbasedir --topdir=$PWD --changelog-since=2007-01-01 noarch
> $ du -bk x86_64/base/pkglist.classic.bz2 noarch/base/pkglist.classic.bz2
> 3536    x86_64/base/pkglist.classic.bz2
> 1302    noarch/base/pkglist.classic.bz2
> $ 
> 
> Таким образом, размер скачиваемого при 'apt-get update' заметно
> увеличивается (примерно на треть).  Я считаю это приемлемой платой
> за удовольствие просмотреть changelog пакета ДО скачивания и установки.

On Sat, May 17, 2008 at 11:00:34PM +0400, Alexey Tourbin wrote:
> Какая плата тебя бы устроила?  Думаю что плату можно будет немного
> уменьшить, если сначала отсортировать пакеты по %{SOURCERPM}, а уже
> потом выгонять хедеры.  Тогда bzip2 лучше сожмёт одинаковые changelog'и
> подряд идущих подпакетов.

Я сделал предварительную реализацию сортировки по %{SOURCERPM}.
Результаты теперь такие:

$ PATH=$PWD:$PATH genbasedir --topdir=$PWD x86_64
$ PATH=$PWD:$PATH genbasedir --topdir=$PWD noarch
$ du -bk x86_64/base/pkglist.classic.bz2 noarch/base/pkglist.classic.bz2
2384    x86_64/base/pkglist.classic.bz2
1048    noarch/base/pkglist.classic.bz2
$

$ PATH=$PWD:$PATH genbasedir --topdir=$PWD --changelog-since=2007-01-01 x86_64
$ PATH=$PWD:$PATH genbasedir --topdir=$PWD --changelog-since=2007-01-01 noarch
$ du -bk x86_64/base/pkglist.classic.bz2 noarch/base/pkglist.classic.bz2
3306    x86_64/base/pkglist.classic.bz2
1300    noarch/base/pkglist.classic.bz2
$

Из этого видно следующее: для noarch пакетов переупорядочивание
по %{SOURCERPM} почти ничего не дает.  Это связано с тем, что noarch
пакеты реже распиливают, а при распиливании названия подпакетов реже
отличаются по префиксу (то есть глобального переупорядочивания, которое
может повысить степень сжатия, как напр. в случае с lib%name и %name,
не происходит).

Для x86_64 экономия заметна даже без генерации changelog'ов (2421/2384 =
1.6%, за счёт лучшего совпадения других атрибутов подпакетов),
а особенно с changelog'ом (3536/3306 = 7%, за счёт лучшего сжатия
одинаковых changelog'ов подряд идущих подпакетов).

В принципе выгаданные несколько процентов позволяют мне с большей
уверенностью говорить о включении changelog'ов в репозитарий, хотя
общая картина остаётся скорее прежней: если включить changelog'и по
предложенной схеме, то размер скачиваемого при 'apt-get update'
увеличивается примерно на треть.

Вот патч на genpkglist.cc, я его плохо проверил, но вроде работает.
У меня уже патч на патче сидит и я пока не знаю как его лучше приложить
к тому что есть.

--- apt-0.5.15lorg2/tools/genpkglist.cc-	2008-05-18 00:48:01 +0400
+++ apt-0.5.15lorg2/tools/genpkglist.cc	2008-05-18 05:14:06 +0400
@@ -320,7 +320,7 @@ done:
 }
 
 bool copyFields(Header h, Header newHeader,
-		FILE *idxfile, const char *directory, char *filename,
+		FILE *idxfile, const char *directory, const char *filename,
 		unsigned filesize, map<string,UpdateInfo> &updateInfo,
 		bool fullFileList)
 {
@@ -460,99 +460,34 @@ void usage()
    cerr << "                 one preceding entry (if available)" <<endl;
 }
 
-
-
-#ifndef HAVE_SCANDIR
-// from glibc 1.09.1  mod'd by jmik, ins'd by asm, fix'd by sbi
-int alphasort(const void * a, const void * b)
+static void progress(int cur, int total)
 {
-  return strcmp ((*(struct dirent **) a)->d_name,
-                 (*(struct dirent **) b)->d_name);
+   if (cur > 1)
+      printf("\b\b\b\b\b\b\b\b\b\b");
+   printf(" %04i/%04i", cur, total);
+   fflush(stdout);
 }
 
-int scandir(const char * dir, struct dirent *** namelist, 
-        int (* select)(struct dirent *), 
-        int (* cmp)(const void *, const void *))
+struct rpmfile {
+   const char *basename;
+   const char *sourcerpm;
+};
 
+static
+int rpmfilecmp(const void *a, const void *b)
 {
-  DIR *dp = opendir (dir);
-  struct dirent **v = NULL;
-  size_t vsize = 0, i;
-  struct dirent *d;
-  int save;
-
-  if (dp == NULL)
-    return -1;
-
-  save = errno;
-  errno = 0;
-
-  i = 0;
-  while ((d = readdir (dp)) != NULL)
-    {
-    if (select == NULL || (*select) (d))
-      {
-        if (i == vsize)
-          {
-            struct dirent **newv;
-            if (vsize == 0)
-              vsize = 10;
-            else
-              vsize *= 2;
-            newv = (struct dirent **) realloc (v, vsize * sizeof (*v));
-            if (newv == NULL)
-              {
-              lose:
-                errno = ENOMEM;
-                break;
-              }
-            v = newv;
-          }
-
-        v[i] = (struct dirent *) malloc (d->d_reclen);
-        if (v[i] == NULL)
-          goto lose;
-
-        // *v[i++] = *d;
-	memcpy(v[i], d, d->d_reclen);
-	i++;
-      }
-    }
-
-  v[i] = NULL;
-
-  if (errno != 0)
-    {
-      save = errno;
-      (void) closedir (dp);
-      while (i > 0)
-        free (v[--i]);
-      free (v);
-      errno = save;
-      return -1;
-    }
-
-  (void) closedir (dp);
-  errno = save;
-
-  /* Sort the list if we have a comparison function to sort with.  */
-  if (cmp != NULL)
-    qsort (v, i, sizeof (struct dirent *), cmp);
-
-  *namelist = v;
-  return i;
+   const struct rpmfile *A = (struct rpmfile *)a;
+   const struct rpmfile *B = (struct rpmfile *)b;
+   int cmp = strcmp(A->sourcerpm, B->sourcerpm);
+   if (cmp)
+      return cmp;
+   return strcmp(A->basename, B->basename);
 }
-// end of new stuff from glibc
-#endif /* !HAVE_SCANDIR */
-
 
 int main(int argc, char ** argv) 
 {
    string rpmsdir;
    string pkglist_path;
-   FD_t outfd, fd;
-   struct dirent **dirEntries;
-   int entry_no, entry_cur;
    map<string,UpdateInfo> updateInfo;
    CachedMD5 *md5cache;
    char *op_dir;
@@ -561,13 +496,13 @@ int main(int argc, char ** argv) 
    char *op_update = NULL;
    long /* time_t */ changelog_since = 0;
    FILE *idxfile;
-   int i;
    bool fullFileList = false;
    bool progressBar = false;
    const char *pkgListSuffix = NULL;
    bool pkgListAppend = false;
    
    setlocale(LC_ALL, "C");
+   int i;
    for (i = 1; i < argc; i++) {
       if (strcmp(argv[i], "--index") == 0) {
 	 i++;
@@ -674,14 +609,16 @@ int main(int argc, char ** argv) 
 
    string dirtag = "RPMS." + string(op_suf);
 
-   entry_no = scandir(rpmsdir.c_str(), &dirEntries, selectDirent, alphasort);
-   if (entry_no < 0) {
-      cerr << "genpkglist: error opening directory " << rpmsdir << ":"
-	  << strerror(errno);
-      return 1;
+   if (chdir(rpmsdir.c_str())) {
+      perror(rpmsdir.c_str());
+      exit(1);
+   }
+
+   glob_t gl;
+   if (glob("*.rpm", 0, NULL, &gl)) {
+      cerr << rpmsdir << "/" << "*.rpm: glob failed" <<endl;
+      exit(1);
    }
-   
-   chdir(rpmsdir.c_str());
    
    if (pkgListSuffix != NULL)
 	   pkglist_path = pkglist_path + "/base/pkglist." + pkgListSuffix;
@@ -689,6 +626,7 @@ int main(int argc, char ** argv) 
 	   pkglist_path = pkglist_path + "/base/pkglist." + op_suf;
    
    
+   FD_t outfd;
    if (pkgListAppend == true && FileExists(pkglist_path)) {
       outfd = fdOpen(pkglist_path.c_str(), O_WRONLY|O_APPEND, 0644);
    } else {
@@ -711,30 +649,54 @@ int main(int argc, char ** argv) 
    int isSource;
 #endif   
 
-   if (!fullFileList) {
-      // ALT: file list cannot be stripped in a dumb manner -- this is going
-      // to produce unmet dependencies.  First pass is required to initialize
-      // certain data structures.
-      for (entry_cur = 0; entry_cur < entry_no; entry_cur++) {
-         if (progressBar) {
-            if (entry_cur)
-               printf("\b\b\b\b\b\b\b\b\b\b");
-            printf(" %04i/%04i", entry_cur + 1, entry_no);
-            fflush(stdout);
-         }
+   struct rpmfile *rpms = new struct rpmfile[gl.gl_pathc];
+   int ix, n = 0;
+
+   for (ix = 0; ix < gl.gl_pathc; ix++) {
+         if (progressBar)
+	    progress(ix+1, gl.gl_pathc);
+	 
+	 const char *basename = gl.gl_pathv[ix];
+         FD_t fd = Fopen(basename, "r");
+         if (!fd) {
+	    cerr << "Warning: " << basename << ": " << strerror(errno) <<endl;
+	    continue;
+	 }
 
-         fd = fdOpen(dirEntries[entry_cur]->d_name, O_RDONLY, 0666);
-         if (!fd)
-            continue;
          int rc;
          Header h;
 #if RPM_VERSION >= 0x040100
          rc = rpmReadPackageFile(ts, fd, dirEntries[entry_cur]->d_name, &h);
-         if (rc == RPMRC_OK || rc == RPMRC_NOTTRUSTED || rc == RPMRC_NOKEY) {
+         if (rc == RPMRC_OK || rc == RPMRC_NOTTRUSTED || rc == RPMRC_NOKEY)
 #else
          rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
-         if (rc == 0) {
+         if (rc == 0)
 #endif
+	 {
+	    ; // good
+	 }
+	 else {
+	    cerr << "Warning: " << basename << ": cannot read package header" <<endl;
+	    continue;
+	 }
+	 
+	 const char *sourcerpm;
+	 rc = headerGetEntry(h, RPMTAG_SOURCERPM, NULL, (void**)&sourcerpm, NULL);
+	 if (!(rc == 1)) {
+	    cerr << "Warning: " << basename << ": no SOURCERPM tag" <<endl;
+	    continue;
+	 }
+
+	 sourcerpm = strdup(sourcerpm);
+	 assert(sourcerpm);
+	 rpms[n].basename = basename;
+	 rpms[n].sourcerpm = sourcerpm;
+	 n++;
+	 
+      // ALT: file list cannot be stripped in a dumb manner -- this is going
+      // to produce unmet dependencies.  First pass is required to initialize
+      // certain data structures.
+	 if (!fullFileList) {
             // path-like Requires
             int_32 reqtype = 0;
             const char **requires = NULL;
@@ -776,37 +738,35 @@ int main(int argc, char ** argv) 
             headerFreeTag(h, dn, (rpmTagType)dnt);
             headerFreeTag(h, di, (rpmTagType)dit);
             
-            headerFree(h);
          }
+	 headerFree(h);
          Fclose(fd);
-      }
    }
-   for (entry_cur = 0; entry_cur < entry_no; entry_cur++) {
+
+   qsort(rpms, n, sizeof(struct rpmfile), rpmfilecmp);
+
+   for (ix = 0; ix < n; ix++) {
       struct stat sb;
 
-      if (progressBar) {
-         if (entry_cur)
-            printf("\b\b\b\b\b\b\b\b\b\b");
-         printf(" %04i/%04i", entry_cur + 1, entry_no);
-         fflush(stdout);
-      }
+      if (progressBar)
+	 progress(ix+1, n);
 
-      if (stat(dirEntries[entry_cur]->d_name, &sb) < 0) {
-	    cerr << "\nWarning: " << strerror(errno) << ": " << 
-		    dirEntries[entry_cur]->d_name << endl;
-	    continue;
+      const char *basename = rpms[ix].basename;
+
+      if (stat(basename, &sb) < 0) {
+	    cerr << "Fatal: " << basename << ": " << strerror(errno) <<endl;
+	    exit(1);
       }
 
       {
 	 Header h;
 	 int rc;
 	 
-	 fd = fdOpen(dirEntries[entry_cur]->d_name, O_RDONLY, 0666);
+	 FD_t fd = Fopen(basename, "r");
 
 	 if (!fd) {
-	    cerr << "\nWarning: " << strerror(errno) << ": " << 
-		    dirEntries[entry_cur]->d_name << endl;
-	    continue;
+	    cerr << "Fatal: " << basename << ": " << strerror(errno) <<endl;
+	    exit(1);
 	 }
 	 
 #if RPM_VERSION >= 0x040100
@@ -822,14 +782,13 @@ int main(int argc, char ** argv) 
 	    newHeader = headerNew();
 	    
 	    copyFields(h, newHeader, idxfile, dirtag.c_str(),
-		       dirEntries[entry_cur]->d_name,
+		       basename,
 		       sb.st_size, updateInfo, fullFileList);
 
 	    if (changelog_since > 0)
 	       copyChangelog(changelog_since, h, newHeader);
 
-	    md5cache->MD5ForFile(string(dirEntries[entry_cur]->d_name), 
-				 sb.st_mtime, md5);
+	    md5cache->MD5ForFile(string(basename), sb.st_mtime, md5);
 	    headerAddEntry(newHeader, CRPMTAG_MD5, RPM_STRING_TYPE, md5, 1);
 
 	    headerWrite(outfd, newHeader, HEADER_MAGIC_YES);
@@ -837,8 +796,8 @@ int main(int argc, char ** argv) 
 	    headerFree(newHeader);
 	    headerFree(h);
 	 } else {
-	    cerr << "\nWarning: Skipping malformed RPM: " << 
-		    dirEntries[entry_cur]->d_name << endl;
+	    cerr << "Fatal: " << basename << ": cannot read package header" <<endl;
+	    exit(1);
 	 }
 	 Fclose(fd);
       }

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

  parent reply	other threads:[~2008-05-18  2:07 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-17  5:34 Alexey Tourbin
2008-05-17  9:50 ` Евгений Терешков
2008-05-17 12:06 ` Alexey Gladkov
2008-05-17 13:23   ` Andrey Rahmatullin
2008-05-17 13:54     ` Alexey Gladkov
2008-05-17 19:00   ` Alexey Tourbin
2008-05-17 20:01     ` Led
2008-05-17 19:55       ` Andrey Rahmatullin
2008-05-17 21:16         ` Led
2008-05-17 21:09           ` Andrey Rahmatullin
2008-05-18  6:34             ` Kirill Maslinsky
2008-05-17 20:50       ` Alexey Tourbin
2008-05-17 21:58     ` Alexey Gladkov
2008-05-17 21:46       ` Andrey Rahmatullin
2008-05-17 22:14         ` Alexey Gladkov
2008-05-17 22:00           ` Andrey Rahmatullin
2008-05-17 22:21             ` Alexey Gladkov
2008-05-17 22:10               ` Andrey Rahmatullin
2008-05-17 22:32                 ` Alexey Gladkov
2008-05-17 22:45       ` Sergey Bolshakov
2008-05-17 23:03       ` Alexey Tourbin
2008-05-19  4:02         ` Ildar Mulyukov
2008-05-19  4:53           ` Alexey Tourbin
2008-05-19 10:26             ` Ildar Mulyukov
2008-05-19 10:35               ` Andrey Rahmatullin
2008-05-19 10:41                 ` Pavlov Konstantin
2008-05-19 10:43                   ` Andrey Rahmatullin
2008-05-19 10:53                   ` Aleksey Avdeev
2008-05-20 12:27             ` Alexander Bokovoy
2008-05-18  2:07     ` Alexey Tourbin [this message]
2008-05-18  2:25       ` Alexey Tourbin
2008-05-18  9:26       ` Alexey Gladkov
2008-05-18 21:35         ` Alexey Tourbin
2008-05-18 22:26           ` Alexey Gladkov
2008-05-20  2:34     ` Alexey Morozov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080518020751.GD9319@solemn.turbinal \
    --to=at@altlinux.ru \
    --cc=devel@lists.altlinux.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

ALT Linux Team development discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/devel/0 devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 devel devel/ http://lore.altlinux.org/devel \
		devel@altlinux.org devel@altlinux.ru devel@lists.altlinux.org devel@lists.altlinux.ru devel@linux.iplabs.ru mandrake-russian@linuxteam.iplabs.ru sisyphus@linuxteam.iplabs.ru
	public-inbox-index devel

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git