- change solv format in an incompatible way, breaking compatibility
authorMichael Schroeder <mls@suse.de>
Fri, 29 Feb 2008 22:01:20 +0000 (22:01 +0000)
committerMichael Schroeder <mls@suse.de>
Fri, 29 Feb 2008 22:01:20 +0000 (22:01 +0000)
  to all older versions. sorry.
  * new fastlz from Matz
  * maxsize/allsize data for faster reading
  * types are stored as Id to make extensions possible
  * new type CONSTANTID
  * new file repopack.h
  * kill unused vertical/packedsizes flags
- switch to pread for paging so that we don't have to mess with file
  offsets
- define more standard IDs
- add new solver_calc_installsizechange() function
- add repo_add_rpms() function
- change location storage method a bit, now VOID means ommited
  (adapt zypp code, please)
- re-added support for source rpm name to susetags parser

20 files changed:
src/fastlz.c
src/pool.c
src/pool.h
src/pooltypes.h
src/repo.c
src/repo_solv.c
src/repodata.c
src/repodata.h
src/repopack.h [new file with mode: 0644]
src/solver.c
src/solver.h
tools/CMakeLists.txt
tools/dumpsolv.c
tools/repo_patchxml.c
tools/repo_rpmdb.c
tools/repo_rpmdb.h
tools/repo_rpmmd.c
tools/repo_susetags.c
tools/repo_write.c
tools/tools_util.h

index 0dae818..8d3ffdf 100644 (file)
@@ -32,9 +32,13 @@ typedef __uint32_t Ref;
    d 110lllll <8o>
         - back ref of length l+2+8, at offset -(o+1) (o < 1 << 8)
    e 1110llll <8o> <8o>
-        - back ref of length l+2, at offset -(o+1) (o < 1 << 16)
-   f 1111llll <8o> <8o> <8l>
-        - back ref, length l+18 (l < 1<<12), offset -(o+1) (o < 1<<16)
+        - back ref of length l+3, at offset -(o+1) (o < 1 << 16)
+  f1 1111llll <8l> <8o> <8o>
+        - back ref, length l+19 (l < 1<<12), offset -(o+1) (o < 1<<16)
+  f2 11110lll <8l> <8o> <8o>
+        - back ref, length l+19 (l < 1<<11), offset -(o+1) (o < 1<<16)
+   g 11111lll <8l> <8o> <8o> <8o>
+        - back ref, length l+5 (l < 1<<11), offset -(o+1) (o < 1<<24)
 
    Generally for a literal of length L we need L+1 bytes, hence it is
    better to encode also very short backrefs (2 chars) as backrefs if
@@ -50,8 +54,9 @@ typedef __uint32_t Ref;
    L >= 2, L <= 9, O < 1024                            : encode as c
    L >= 10, L <= 41, O < 256                           : encode as d
    else we have either O >= 1024, or L >= 42:
-   L >= 2, L <= 17, O < 65536                          : encode as e
-   L >= 18, L <= 4095+18, O < 65536                    : encode as f
+   L < 3 : encode as 1-literal
+   L >= 3, L <= 18, O < 65536                          : encode as e
+   L >= 19, L <= 4095+18, O < 65536                    : encode as f
    else we have either L >= 4096+18 or O >= 65536.
    O >= 65536: encode as 1-literal, too bad
      (with the current block size this can't happen)
@@ -66,10 +71,10 @@ compress_buf (const unsigned char *in, unsigned int in_len,
   unsigned int oo = 0;         //out-offset
   unsigned int io = 0;         //in-offset
 #define HS (65536)
-  unsigned int htab[HS];
-  unsigned int hnext[BLOCK_SIZE];
-  memset (htab, 0, sizeof (htab));
-  memset (hnext, 0, sizeof (hnext));
+  Ref htab[HS];
+  Ref hnext[BLOCK_SIZE];
+  memset (htab, -1, sizeof (htab));
+  memset (hnext, -1, sizeof (hnext));
   unsigned int litofs = 0;
   while (io + 2 < in_len)
     {
@@ -85,7 +90,7 @@ compress_buf (const unsigned char *in, unsigned int in_len,
       mlen = 0;
       mofs = 0;
 
-      for (tries = 0; tries < 4; tries++)
+      for (tries = 0; try != -1 && tries < 12; tries++)
         {
          if (try < io
              && in[try] == in[io] && in[try + 1] == in[io + 1])
@@ -96,7 +101,7 @@ compress_buf (const unsigned char *in, unsigned int in_len,
            }
          try = hnext[try];
        }
-      for (; tries < 4; tries++)
+      for (; try != -1 && tries < 12; tries++)
        {
          //assert (mlen >= 2);
          //assert (io + mlen < in_len);
@@ -139,20 +144,36 @@ compress_buf (const unsigned char *in, unsigned int in_len,
            }
        no_match:
          try = hnext[try];
-         if (io - try - 1 >= 65536)
-           break;
+         /*if (io - try - 1 >= 65536)
+           break;*/
        }
 
 match_done:
       if (mlen)
        {
-         if (mlen == 2 && (0 || litofs || mofs >= 1024))
+         //fprintf (stderr, "%d %d\n", mlen, mofs);
+         if (mlen == 2 && (litofs || mofs >= 1024))
            mlen = 0;
+         /*else if (mofs >= 65536)
+           mlen = 0;*/
          else if (mofs >= 65536)
+           {
+             if (mlen >= 2048 + 5)
+               mlen = 2047 + 5;
+             else if (mlen < 5)
+               mlen = 0;
+           }
+         else if (mlen < 3)
            mlen = 0;
-         else if (mlen >= 4096 + 18)
-           mlen = 4095 + 18;
-         if (mlen && io + 3 < in_len)
+         /*else if (mlen >= 4096 + 19)
+           mlen = 4095 + 19;*/
+         else if (mlen >= 2048 + 19)
+           mlen = 2047 + 19;
+         /* Skip this match if the next character would deliver a better one,
+            but only do this if we have the chance to really extend the
+            length (i.e. our current length isn't yet the (conservative)
+            maximum).  */
+         if (mlen && mlen < (2048 + 5) && io + 3 < in_len)
            {
              unsigned int hval =
                in[io + 1] | in[io + 2] << 8 | in[io + 3] << 16;
@@ -250,24 +271,35 @@ match_done:
              out[oo++] = 0xc0 | (mlen - 10);
              out[oo++] = mofs;
            }
-         else if (mlen >= 2 && mlen <= 17)
+         else if (mofs >= 65536)
+           {
+             assert (mlen >= 5 && mlen < 2048 + 5);
+             if (oo + 5 >= out_len)
+               return 0;
+             out[oo++] = 0xf8 | ((mlen - 5) >> 8);
+             out[oo++] = (mlen - 5) & 0xff;
+             out[oo++] = mofs & 0xff;
+             out[oo++] = (mofs >> 8) & 0xff;
+             out[oo++] = mofs >> 16;
+           }
+         else if (mlen >= 3 && mlen <= 18)
            {
              assert (mofs < 65536);
              if (oo + 3 >= out_len)
                return 0;
-             out[oo++] = 0xe0 | (mlen - 2);
-             out[oo++] = mofs >> 8;
+             out[oo++] = 0xe0 | (mlen - 3);
              out[oo++] = mofs & 0xff;
+             out[oo++] = mofs >> 8;
            }
          else
            {
-             assert (mlen >= 18 && mlen <= 4095 + 18 && mofs < 65536);
+             assert (mlen >= 19 && mlen <= 4095 + 19 && mofs < 65536);
              if (oo + 4 >= out_len)
                return 0;
-             out[oo++] = 0xf0 | ((mlen - 18) >> 8);
-             out[oo++] = mofs >> 8;
+             out[oo++] = 0xf0 | ((mlen - 19) >> 8);
+             out[oo++] = (mlen - 19) & 0xff;
              out[oo++] = mofs & 0xff;
-             out[oo++] = (mlen - 18) & 0xff;
+             out[oo++] = mofs >> 8;
            }
          /* Insert the hashes for the compressed run [io..io+mlen-1].
             For [io] we have it already done at the start of the loop.
@@ -357,27 +389,34 @@ unchecked_decompress_buf (const unsigned char *in, unsigned int in_len,
   while (in < in_end)
     {
       unsigned int first = *in++;
-      unsigned int o = o;
-      switch (first >> 5)
+      unsigned int o;
+      switch (first >> 4)
        {
-       case 0:
-       case 1:
-       case 2:
-       case 3:
+       default:
+         /* This default case can't happen, but GCCs VRP is not strong
+            enough to see this, so make this explicitely not fall to
+            the end of the switch, so that we don't have to initialize
+            o above.  */
+         continue;
+       case 0: case 1:
+       case 2: case 3:
+       case 4: case 5:
+       case 6: case 7:
          //a 0LLLLLLL
          //fprintf (stderr, "lit: 1\n");
          *out++ = first;
          continue;
-       case 4:
+       case 8: case 9:
          //b 100lllll <l+1 bytes>
          {
-           unsigned int l = (first & 31) + 1;
+           unsigned int l = first & 31;
            //fprintf (stderr, "lit: %d\n", l);
-           while (l--)
+           do
              *out++ = *in++;
+           while (l--);
            continue;
          }
-       case 5:
+       case 10: case 11:
          //c 101oolll <8o>
          {
            o = first & (3 << 3);
@@ -385,29 +424,47 @@ unchecked_decompress_buf (const unsigned char *in, unsigned int in_len,
            first = (first & 7) + 2;
            break;
          }
-       case 6:
+       case 12: case 13:
          //d 110lllll <8o>
          {
            o = *in++;
            first = (first & 31) + 10;
            break;
          }
-       case 7:
-         //e 1110llll <8o> <8o>
-         //f 1111llll <8o> <8o> <8l>
+       case 14:
+         // e 1110llll <8o> <8o>
          {
-           o = *in++ << 8;
-           o |= *in++;
+           o = in[0] | (in[1] << 8);
+           in += 2;
            first = first & 31;
-           if (first >= 16)
-             first = (((first - 16) << 8) | *in++) + 18;
+           first += 3;
+           break;
+         }
+       case 15:
+         //f1 1111llll <8o> <8o> <8l>
+         //f2 11110lll <8o> <8o> <8l>
+         // g 11111lll <8o> <8o> <8o> <8l>
+         {
+           first = first & 15;
+           if (first >= 8)
+             {
+               first = (((first - 8) << 8) | in[0]) + 5;
+               o = in[1] | (in[2] << 8) | (in[3] << 16);
+               in += 4;
+             }
            else
-             first += 2;
+             {
+               first = ((first << 8) | in[0]) + 19;
+               o = in[1] | (in[2] << 8);
+               in += 3;
+             }
            break;
          }
        }
       //fprintf (stderr, "ref: %d @ %d\n", first, o);
       o++;
+      o = -o;
+#if 0
       /* We know that first will not be zero, and this loop structure is
          better optimizable.  */
       do
@@ -416,6 +473,56 @@ unchecked_decompress_buf (const unsigned char *in, unsigned int in_len,
          out++;
        }
       while (--first);
+#else
+      switch (first)
+        {
+         case 18: *out = *(out + o); out++;
+         case 17: *out = *(out + o); out++;
+         case 16: *out = *(out + o); out++;
+         case 15: *out = *(out + o); out++;
+         case 14: *out = *(out + o); out++;
+         case 13: *out = *(out + o); out++;
+         case 12: *out = *(out + o); out++;
+         case 11: *out = *(out + o); out++;
+         case 10: *out = *(out + o); out++;
+         case  9: *out = *(out + o); out++;
+         case  8: *out = *(out + o); out++;
+         case  7: *out = *(out + o); out++;
+         case  6: *out = *(out + o); out++;
+         case  5: *out = *(out + o); out++;
+         case  4: *out = *(out + o); out++;
+         case  3: *out = *(out + o); out++;
+         case  2: *out = *(out + o); out++;
+         case  1: *out = *(out + o); out++;
+         case  0: break;
+         default:
+           /* Duff duff :-) */
+           switch (first & 15)
+             {
+               do
+                 {
+                   case  0: *out = *(out + o); out++;
+                   case 15: *out = *(out + o); out++;
+                   case 14: *out = *(out + o); out++;
+                   case 13: *out = *(out + o); out++;
+                   case 12: *out = *(out + o); out++;
+                   case 11: *out = *(out + o); out++;
+                   case 10: *out = *(out + o); out++;
+                   case  9: *out = *(out + o); out++;
+                   case  8: *out = *(out + o); out++;
+                   case  7: *out = *(out + o); out++;
+                   case  6: *out = *(out + o); out++;
+                   case  5: *out = *(out + o); out++;
+                   case  4: *out = *(out + o); out++;
+                   case  3: *out = *(out + o); out++;
+                   case  2: *out = *(out + o); out++;
+                   case  1: *out = *(out + o); out++;
+                 }
+               while ((int)(first -= 16) > 0);
+             }
+           break;
+       }
+#endif
     }
   return out - orig_out;
 }
@@ -503,7 +610,9 @@ benchmark (FILE * from)
   unsigned int per_loop;
   unsigned int i, j;
   clock_t start, end;
+  float seconds;
 
+#if 0
   calib_loop = 1;
   per_loop = 0;
   start = clock ();
@@ -523,9 +632,10 @@ benchmark (FILE * from)
     for (j = 0; j < per_loop; j++)
       dumb_memcpy (outb, inb, in_len);
   end = clock ();
-  float seconds = (end - start) / (float) CLOCKS_PER_SEC;
+  seconds = (end - start) / (float) CLOCKS_PER_SEC;
   fprintf (stderr, "%.2f seconds == %.2f MB/s\n", seconds,
           ((long long) in_len * per_loop * 10) / (1024 * 1024 * seconds));
+#endif
 
   calib_loop = 1;
   per_loop = 0;
index ff10d2b..8dc56c2 100644 (file)
@@ -64,6 +64,50 @@ static const char *initpool_data[] = {
   "repodata:external",
   "repodata:keys",
   "repodata:location",
+  "repokey:type:void",
+  "repokey:type:constant",
+  "repokey:type:constantid",
+  "repokey:type:id",
+  "repokey:type:num",
+  "repokey:type:num32",
+  "repokey:type:dir",
+  "repokey:type:str",
+  "repokey:type:idarray",
+  "repokey:type:relidarray",
+  "repokey:type:dirstrarray",
+  "repokey:type:dirnumnumarray",
+
+  "solvable:summary",
+  "solvable:description",
+  "solvable:authors",
+  "solvable:group",
+  "solvable:keywords",
+  "solvable:license",
+  "solvable:buildtime",
+
+  "solvable:eula",
+  "solvable:messageins",
+  "solvable:messagedel",
+
+  "solvable:installsize",
+  "solvable:diskusage",
+  "solvable:filelist",
+
+  "solvable:installtime",
+
+  "solvable:mediadir",
+  "solvable:mediafile",
+  "solvable:medianr",
+  "solvable:downloadsize",
+
+  "solvable:sourcearch",
+  "solvable:sourcename",
+  "solvable:sourceevr",
+
+  "solvable:isvisible",                        /* from susetags */
+
+  "solvable:patchcategory",
+
   0
 };
 
@@ -521,7 +565,7 @@ pool_addrelproviders(Pool *pool, Id d)
 
   /* convert to whatprovides id */
 #if 0
-  POOL_DEBUG(DEBUG_1, "addrelproviders: what provides %s?\n", id2str(pool, name));
+  POOL_DEBUG(SAT_DEBUG_STATS, "addrelproviders: what provides %s?\n", dep2str(pool, name));
 #endif
   if (flags && flags < 8)
     {
@@ -582,7 +626,7 @@ pool_addrelproviders(Pool *pool, Id d)
     }
   /* add providers to whatprovides */
 #if 0
-  POOL_DEBUG(DEBUG_1, "addrelproviders: adding %d packages to %d\n", plist.count, d);
+  POOL_DEBUG(SAT_DEBUG_STATS, "addrelproviders: adding %d packages to %d\n", plist.count, d);
 #endif
   pool->whatprovides_rel[d] = pool_queuetowhatprovides(pool, &plist);
   queue_free(&plist);
@@ -765,9 +809,6 @@ pool_addfileprovides(Pool *pool, Repo *installed)
   struct searchfiles sf, isf;
   struct addfileprovides_cbdata cbd;
   int i;
-  Id id_filelist;
-
-  id_filelist = str2id(pool, "filelist", 1);
 
   memset(&sf, 0, sizeof(sf));
   map_init(&sf.seen, pool->ss.nstrings + pool->nrels);
@@ -814,7 +855,7 @@ pool_addfileprovides(Pool *pool, Repo *installed)
       cbd.names = sf.names;
       cbd.olddata = 0;
       cbd.dids = sat_realloc2(cbd.dids, sf.nfiles, sizeof(Id));
-      pool_search(pool, 0, id_filelist, 0, 0, addfileprovides_cb, &cbd);
+      pool_search(pool, 0, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, &cbd);
       sat_free(sf.ids);
       for (i = 0; i < sf.nfiles; i++)
        {
@@ -836,7 +877,7 @@ pool_addfileprovides(Pool *pool, Repo *installed)
       cbd.names = isf.names;
       cbd.olddata = 0;
       cbd.dids = sat_realloc2(cbd.dids, isf.nfiles, sizeof(Id));
-      repo_search(installed, 0, id_filelist, 0, 0, addfileprovides_cb, &cbd);
+      repo_search(installed, 0, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, &cbd);
       sat_free(isf.ids);
       for (i = 0; i < isf.nfiles; i++)
        {
index e28ce8c..99d1e57 100644 (file)
@@ -59,7 +59,51 @@ extern "C" {
 #define REPODATA_KEYS          27
 #define REPODATA_LOCATION      28
 
-#define ID_NUM_INTERNAL                29
+/* The void type is usable to encode one-valued attributes, they have
+   no associated data.  This is useful to encode values which many solvables
+   have in common, and whose overall set is relatively limited.  A prime
+   example would be the media number.  The actual value is encoded in the
+   SIZE member of the key structure.  Be warned: careless use of this
+   leads to combinatoric explosion of number of schemas.  */
+#define REPOKEY_TYPE_VOID      29
+#define REPOKEY_TYPE_CONSTANT  30
+#define REPOKEY_TYPE_CONSTANTID        31
+#define REPOKEY_TYPE_ID                32
+#define REPOKEY_TYPE_NUM       33
+#define REPOKEY_TYPE_U32       34
+#define REPOKEY_TYPE_DIR       35
+#define REPOKEY_TYPE_STR       36
+#define REPOKEY_TYPE_IDARRAY   37
+#define REPOKEY_TYPE_REL_IDARRAY       38
+#define REPOKEY_TYPE_DIRSTRARRAY       39
+#define REPOKEY_TYPE_DIRNUMNUMARRAY    40
+
+#define SOLVABLE_SUMMARY       41
+#define SOLVABLE_DESCRIPTION   42
+#define SOLVABLE_AUTHORS       43
+#define SOLVABLE_GROUP         44
+#define SOLVABLE_KEYWORDS      45
+#define SOLVABLE_LICENSE       46
+#define SOLVABLE_BUILDTIME     47
+#define SOLVABLE_EULA          48
+#define SOLVABLE_MESSAGEINS    49
+#define SOLVABLE_MESSAGEDEL    50
+#define SOLVABLE_INSTALLSIZE   51
+#define SOLVABLE_DISKUSAGE     52
+#define SOLVABLE_FILELIST      53
+#define SOLVABLE_INSTALLTIME   54
+#define SOLVABLE_MEDIADIR      55
+#define SOLVABLE_MEDIAFILE     56
+#define SOLVABLE_MEDIANR       57
+#define SOLVABLE_DOWNLOADSIZE  58
+#define SOLVABLE_SOURCEARCH    59
+#define SOLVABLE_SOURCENAME    60
+#define SOLVABLE_SOURCEEVR     61
+#define SOLVABLE_ISVISIBLE     62
+
+#define SOLVABLE_PATCHCATEGORY 63
+
+#define ID_NUM_INTERNAL                64
 
 
 /* well known solvable */
@@ -143,41 +187,6 @@ struct _Pool {
 #define SAT_DEBUG_JOB                  (1<<11)
 #define SAT_DEBUG_SCHUBI               (1<<12)
 
-/* The void type is usable to encode one-valued attributes, they have
-   no associated data.  This is useful to encode values which many solvables
-   have in common, and whose overall set is relatively limited.  A prime
-   example would be the media number.  The actual value is encoded in the
-   SIZE member of the key structure.  Be warned: careless use of this
-   leads to combinatoric explosion of number of schemas.  */
-
-/* FIXME: Should be 'enum' */
-#define TYPE_VOID               0
-#define TYPE_ID                        1
-#define TYPE_IDARRAY           2
-#define TYPE_STR               3
-#define TYPE_U32               4
-#define TYPE_REL_IDARRAY       5
-
-#define TYPE_ATTR_INT          6
-#define TYPE_ATTR_CHUNK                7
-#define TYPE_ATTR_STRING       8
-#define TYPE_ATTR_INTLIST      9
-#define TYPE_ATTR_LOCALIDS     10
-
-#define TYPE_COUNT_NAMED       11
-#define TYPE_COUNTED           12
-
-#define TYPE_IDVALUEARRAY      13
-
-#define TYPE_DIR               14
-#define TYPE_DIRNUMNUMARRAY    15
-#define TYPE_DIRSTRARRAY       16
-
-#define TYPE_CONSTANT          17
-#define TYPE_NUM               18
-
-#define TYPE_ATTR_TYPE_MAX     18
-
 //-----------------------------------------------
 
 
index 9681f9d..cfe837d 100644 (file)
@@ -20,9 +20,8 @@
 #define SOLV_VERSION_3 3
 #define SOLV_VERSION_4 4
 #define SOLV_VERSION_5 5
+#define SOLV_VERSION_6 6
 
-#define SOLV_FLAG_PACKEDSIZES 1
-#define SOLV_FLAG_VERTICAL    2
 #define SOLV_FLAG_PREFIX_POOL 4
 
 struct _Stringpool;
index dff8840..208d954 100644 (file)
@@ -495,14 +495,14 @@ repo_matchvalue(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValu
     {
       switch (key->type)
        {
-       case TYPE_ID:
-       case TYPE_IDARRAY:
+       case REPOKEY_TYPE_ID:
+       case REPOKEY_TYPE_IDARRAY:
          if (data && data->localpool)
            kv->str = stringpool_id2str(&data->spool, kv->id);
          else
            kv->str = id2str(s->repo->pool, kv->id);
          break;
-       case TYPE_STR:
+       case REPOKEY_TYPE_STR:
          break;
        default:
          return 0;
@@ -552,20 +552,20 @@ repo_matchvalue(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValu
 
 
 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
-  { SOLVABLE_NAME,        TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_ARCH,        TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_EVR,         TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_VENDOR,      TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_PROVIDES,    TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_OBSOLETES,   TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_CONFLICTS,   TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_REQUIRES,    TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_RECOMMENDS,  TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_SUGGESTS,    TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_SUPPLEMENTS, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_ENHANCES,    TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_FRESHENS,    TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { RPM_RPMDBID,          TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_NAME,        REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_ARCH,        REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_EVR,         REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_VENDOR,      REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_PROVIDES,    REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_OBSOLETES,   REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_CONFLICTS,   REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_REQUIRES,    REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_RECOMMENDS,  REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_SUGGESTS,    REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_ENHANCES,    REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_FRESHENS,    REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { RPM_RPMDBID,          REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
 };
 
 static void
@@ -767,7 +767,7 @@ repo_lookup_str(Solvable *s, Id key)
        continue;
       for (j = 1; j < data->nkeys; j++)
        {
-         if (data->keys[j].name == key && (data->keys[j].type == TYPE_ID || data->keys[j].type == TYPE_STR))
+         if (data->keys[j].name == key && (data->keys[j].type == REPOKEY_TYPE_ID || data->keys[j].type == REPOKEY_TYPE_CONSTANTID || data->keys[j].type == REPOKEY_TYPE_STR))
            return repodata_lookup_str(data, n - data->start, j);
        }
     }
@@ -782,6 +782,12 @@ repo_lookup_num(Solvable *s, Id key)
   Repodata *data;
   int i, j, n;
 
+  if (key == RPM_RPMDBID)
+    {
+      if (repo->rpmdbid)
+       return repo->rpmdbid[(s - pool->solvables) - repo->start];
+      return 0;
+    }
   n = s - pool->solvables;
   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
     {
@@ -790,9 +796,9 @@ repo_lookup_num(Solvable *s, Id key)
       for (j = 1; j < data->nkeys; j++)
        {
          if (data->keys[j].name == key
-             && (data->keys[j].type == TYPE_U32
-                 || data->keys[j].type == TYPE_NUM
-                 || data->keys[j].type == TYPE_CONSTANT))
+             && (data->keys[j].type == REPOKEY_TYPE_U32
+                 || data->keys[j].type == REPOKEY_TYPE_NUM
+                 || data->keys[j].type == REPOKEY_TYPE_CONSTANT))
            {
              unsigned value;
              if (repodata_lookup_num(data, n - data->start, j, &value))
index 2fafd52..2723465 100644 (file)
@@ -26,6 +26,8 @@
 #include "repo_solv.h"
 #include "util.h"
 
+#include "repopack.h"
+
 #define INTERESTED_START       SOLVABLE_NAME
 #define INTERESTED_END         SOLVABLE_FRESHENS
 
@@ -134,6 +136,7 @@ read_id(Repodata *data, Id max)
  * read array of Ids
  */
 
+#if 0
 static Id *
 read_rel_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end, Id marker)
 {
@@ -158,7 +161,7 @@ read_rel_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end, Id marker)
          continue;
        }
       x = (x << 6) | (c & 63);
-      if (x == 0 && c == 0x40)
+      if (x == 0)
        {
          /* marker hack */
          if (store == end)
@@ -167,6 +170,11 @@ read_rel_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end, Id marker)
              data->error = SOLV_ERROR_OVERFLOW;
              return 0;
            }
+         if (c != 0x40)
+           {
+             *store++ = 0;
+             return store;
+           }
          *store++ = marker;    /* do not map! */
          old = 0;
          x = 0;
@@ -204,6 +212,99 @@ read_rel_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end, Id marker)
       x = 0;
     }
 }
+#endif
+
+static inline unsigned char *
+data_read_id_max(unsigned char *dp, Id *ret, Id *map, int max, int *error)
+{
+  Id x;
+  dp = data_read_id(dp, &x);
+  if (max && x >= max)
+    {
+      pool_debug(mypool, SAT_ERROR, "data_read_idarray: id too large (%u/%u)\n", x, max);
+      *error = SOLV_ERROR_ID_RANGE;
+      x = 0;
+    }
+  *ret = map ? map[x] : x;
+  return dp;
+}
+
+unsigned char *
+data_read_idarray(unsigned char *dp, Id **storep, Id *map, int max, int *error)
+{
+  Id *store = *storep;
+  unsigned int x = 0;
+  int c;
+
+  for (;;)
+    {
+      c = *dp++;
+      if ((c & 128) != 0)
+       {
+         x = (x << 7) ^ c ^ 128;
+         continue;
+       }
+      x = (x << 6) | (c & 63);
+      if (max && x >= max)
+       {
+         pool_debug(mypool, SAT_ERROR, "data_read_idarray: id too large (%u/%u)\n", x, max);
+         *error = SOLV_ERROR_ID_RANGE;
+         break;
+       }
+      *store++ = x;
+      if ((c & 64) == 0)
+        break;
+      x = 0;
+    }
+  *store++ = 0;
+  *storep = store;
+  return dp;
+}
+
+unsigned char *
+data_read_rel_idarray(unsigned char *dp, Id **storep, Id *map, int max, int *error, Id marker)
+{
+  Id *store = *storep;
+  Id old = 0;
+  unsigned int x = 0;
+  int c;
+
+  for (;;)
+    {
+      c = *dp++;
+      if ((c & 128) != 0)
+       {
+         x = (x << 7) ^ c ^ 128;
+         continue;
+       }
+      x = (x << 6) | (c & 63);
+      if (x == 0)
+       {
+         if (!(c & 64))
+           break;
+          if (marker)
+           *store++ = marker;
+         old = 0;
+         continue;
+       }
+      x = old + (x - 1);
+      old = x;
+      if (max && x >= max)
+       {
+         pool_debug(mypool, SAT_ERROR, "data_read_rel_idarray: id too large (%u/%u)\n", x, max);
+         *error = SOLV_ERROR_ID_RANGE;
+         break;
+       }
+      *store++ = map ? map[x] : x;
+      if (!(c & 64))
+        break;
+      x = 0;
+    }
+  *store++ = 0;
+  *storep = store;
+  return dp;
+}
+
 
 static Id *
 read_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end)
@@ -298,37 +399,36 @@ read_str(Repodata *data, char **inbuf, unsigned *len)
 }
 
 static void
-skip_item (Repodata *data, unsigned type, unsigned numid, unsigned numrel)
+skip_item(Repodata *data, unsigned type, unsigned numid, unsigned numrel)
 {
   switch (type)
     {
-      case TYPE_VOID:
-      case TYPE_CONSTANT:
+      case REPOKEY_TYPE_VOID:
+      case REPOKEY_TYPE_CONSTANT:
+      case REPOKEY_TYPE_CONSTANTID:
        break;
-      case TYPE_ID:
+      case REPOKEY_TYPE_ID:
        read_id(data, numid + numrel);          /* just check Id */
        break;
-      case TYPE_DIR:
+      case REPOKEY_TYPE_DIR:
        read_id(data, numid + data->dirpool.ndirs);     /* just check Id */
        break;
-      case TYPE_NUM:
+      case REPOKEY_TYPE_NUM:
        read_id(data, 0);
        break;
-      case TYPE_U32:
+      case REPOKEY_TYPE_U32:
        read_u32(data);
        break;
-      case TYPE_ATTR_STRING:
-      case TYPE_STR:
+      case REPOKEY_TYPE_STR:
        while (read_u8(data) != 0)
          ;
        break;
-      case TYPE_IDARRAY:
-      case TYPE_REL_IDARRAY:
-      case TYPE_ATTR_INTLIST:
+      case REPOKEY_TYPE_IDARRAY:
+      case REPOKEY_TYPE_REL_IDARRAY:
        while ((read_u8(data) & 0xc0) != 0)
          ;
        break;
-      case TYPE_DIRNUMNUMARRAY:
+      case REPOKEY_TYPE_DIRNUMNUMARRAY:
        for (;;)
          {
            read_id(data, numid + data->dirpool.ndirs); /* just check Id */
@@ -337,7 +437,7 @@ skip_item (Repodata *data, unsigned type, unsigned numid, unsigned numrel)
              break;
          }
        break;
-      case TYPE_DIRSTRARRAY:
+      case REPOKEY_TYPE_DIRSTRARRAY:
        for (;;)
          {
            Id id = read_id(data, 0);
@@ -347,35 +447,6 @@ skip_item (Repodata *data, unsigned type, unsigned numid, unsigned numrel)
              break;
          }
        break;
-      case TYPE_COUNT_NAMED:
-       {
-         unsigned count = read_id(data, 0);
-         while (count--)
-           {
-             read_id(data, numid);    /* Name */
-             unsigned t = read_id(data, TYPE_ATTR_TYPE_MAX + 1);
-             skip_item(data, t, numid, numrel);
-           }
-       }
-       break;
-      case TYPE_COUNTED:
-        {
-         unsigned count = read_id(data, 0);
-         unsigned t = read_id(data, TYPE_ATTR_TYPE_MAX + 1);
-         while (count--)
-           skip_item(data, t, numid, numrel);
-       }
-        break;
-      case TYPE_ATTR_CHUNK:
-       read_id(data, 0);
-       /* Fallthrough.  */
-      case TYPE_ATTR_INT:
-       read_id(data, 0);
-       break;
-      case TYPE_ATTR_LOCALIDS:
-       while (read_id(data, 0) != 0)
-         ;
-       break;
       default:
        pool_debug(mypool, SAT_ERROR, "unknown type %d\n", type);
         data->error = SOLV_ERROR_CORRUPT;
@@ -413,10 +484,10 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned
       id = keys[key].name;
       switch (keys[key].type)
        {
-       case TYPE_IDVALUEARRAY:
+       case REPOKEY_TYPE_IDARRAY:
          if (id != REPODATA_KEYS)
            {
-             skip_item(maindata, TYPE_IDVALUEARRAY, numid, numrel);
+             skip_item(maindata, REPOKEY_TYPE_IDARRAY, numid, numrel);
              break;
            }
          /* read_idarray writes a terminating 0, that's why the + 1 */
@@ -441,7 +512,7 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned
                  return;
                }
              data->keys[i].name = idmap ? idmap[*ide++] : *ide++;
-             data->keys[i].type = *ide++;
+             data->keys[i].type = idmap ? idmap[*ide++] : *ide++;
              data->keys[i].size = 0;
              data->keys[i].storage = 0;
            }
@@ -449,9 +520,9 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned
          if (data->nkeys > 2)
            qsort(data->keys + 1, data->nkeys - 1, sizeof(data->keys[0]), key_cmp);
          break;
-       case TYPE_STR:
+       case REPOKEY_TYPE_STR:
          if (id != REPODATA_LOCATION)
-           skip_item(maindata, TYPE_STR, numid, numrel);
+           skip_item(maindata, REPOKEY_TYPE_STR, numid, numrel);
          else
            {
              char buf[1024];
@@ -512,6 +583,19 @@ incore_add_id(Repodata *data, Id x)
 }
 
 static void
+incore_add_blob(Repodata *data, unsigned char *buf, int len)
+{
+  if (data->incoredatafree < len)
+    {
+      data->incoredata = sat_realloc(data->incoredata, data->incoredatalen + 1024 + len);
+      data->incoredatafree = 1024 + len;
+    }
+  memcpy(data->incoredata + data->incoredatalen, buf, len);
+  data->incoredatafree -= len;
+  data->incoredatalen += len;
+}
+
+static void
 incore_add_u32(Repodata *data, unsigned int x)
 {
   unsigned char *dp;
@@ -530,6 +614,7 @@ incore_add_u32(Repodata *data, unsigned int x)
   data->incoredatalen += 4;
 }
 
+#if 0
 static void
 incore_add_u8(Repodata *data, unsigned int x)
 {
@@ -545,6 +630,7 @@ incore_add_u8(Repodata *data, unsigned int x)
   data->incoredatafree--;
   data->incoredatalen++;
 }
+#endif
 
 
 
@@ -569,7 +655,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
   char *strsp;                        /* repo string space */
   char *sp;                           /* pointer into string space */
   Id *idmap;                          /* map of repo Ids to pool Ids */
-  Id id;
+  Id id, type;
   unsigned int hashmask, h;
   int hh;
   Id *hashtbl;
@@ -587,6 +673,9 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
   Id *schemata, key;
   int have_xdata;
   unsigned oldnrepodata;
+  int maxsize, allsize;
+  unsigned char *buf, *dp, *dps;
+  int left;
 
   struct _Stringpool *spool;
 
@@ -595,6 +684,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
   memset(&data, 0, sizeof(data));
   data.repo = repo;
   data.fp = fp;
+  data.pagefd = -1;
 
   mypool = pool;
 
@@ -606,14 +696,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
   solvversion = read_u32(&data);
   switch (solvversion)
     {
-      case SOLV_VERSION_1:
-      case SOLV_VERSION_2:
-      case SOLV_VERSION_3:
-      case SOLV_VERSION_4:
-      case SOLV_VERSION_5:
-      /* Version 6 existed only intermittantly.  It's equivalent to
-        version 5.  */
-      case 6:
+      case SOLV_VERSION_6:
         break;
       default:
         pool_debug(pool, SAT_ERROR, "unsupported SOLV version\n");
@@ -624,29 +707,18 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
 
   numid = read_u32(&data);
   numrel = read_u32(&data);
-  if (solvversion >= SOLV_VERSION_4)
-    numdir = read_u32(&data);
-  else
-    numdir = 0;
+  numdir = read_u32(&data);
   numsolv = read_u32(&data);
   numkeys = read_u32(&data);
   numschemata = read_u32(&data);
   numinfo = read_u32(&data);
   solvflags = read_u32(&data);
 
-  if (solvversion < SOLV_VERSION_5)
-    numschemata++;
-
   if (numdir && numdir < 2)
     {
       pool_debug(pool, SAT_ERROR, "bad number of dirs\n");
       return SOLV_ERROR_CORRUPT;
     }
-  if (numinfo && solvversion < SOLV_VERSION_3)
-    {
-      pool_debug(pool, SAT_ERROR, "unsupported SOLV format (has info)\n");
-      return SOLV_ERROR_UNSUPPORTED;
-    }
 
   if (parent)
     {
@@ -956,63 +1028,36 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
        id = idmap[id];
       else if (parent)
         id = str2id(pool, stringpool_id2str(spool, id), 1);
-      keys[i].name = id;
-      keys[i].type = read_id(&data, 0);
-      keys[i].size = read_id(&data, 0);
-#if 0
-      fprintf (stderr, "key %d %s %d %d\n", i, id2str(pool,id), keys[i].type,
-               keys[i].size);
-#endif
-      if (solvversion >= SOLV_VERSION_5)
+      type = read_id(&data, numid);
+      if (idmap)
+       type = idmap[type];
+      else if (parent)
+        type = str2id(pool, stringpool_id2str(spool, type), 1);
+      if (type < REPOKEY_TYPE_VOID || type > REPOKEY_TYPE_DIRNUMNUMARRAY)
        {
-         keys[i].storage = read_id(&data, 0);
-         continue;
+         pool_debug(pool, SAT_ERROR, "unsupported data type '%s'\n", id2str(pool, type));
+         data.error = SOLV_ERROR_UNSUPPORTED;
+         type = REPOKEY_TYPE_VOID;
        }
-      keys[i].storage = KEY_STORAGE_DROPPED;
-      if (parent)
+      keys[i].name = id;
+      keys[i].type = type;
+      keys[i].size = read_id(&data, keys[i].type == REPOKEY_TYPE_CONSTANTID ? numid + numrel : 0);
+      keys[i].storage = read_id(&data, 0);
+      if (id >= SOLVABLE_NAME && id <= RPM_RPMDBID)
+       keys[i].storage = KEY_STORAGE_SOLVABLE;
+      else if (keys[i].storage == KEY_STORAGE_SOLVABLE)
+       keys[i].storage = KEY_STORAGE_INCORE;
+      if (keys[i].type == REPOKEY_TYPE_CONSTANTID)
        {
-         keys[i].storage = KEY_STORAGE_INCORE;
-         continue;
-       }
-      switch (keys[i].type)
-       {
-       case TYPE_VOID:
-       case TYPE_CONSTANT:
-       case TYPE_STR:
-       case TYPE_NUM:
-       case TYPE_DIRNUMNUMARRAY:
-         keys[i].storage = KEY_STORAGE_INCORE;
-         break;
-       case TYPE_ID:
-         switch(id)
-           {
-           case SOLVABLE_NAME:
-           case SOLVABLE_ARCH:
-           case SOLVABLE_EVR:
-           case SOLVABLE_VENDOR:
-             keys[i].storage = KEY_STORAGE_SOLVABLE;
-             break;
-           default:
-             keys[i].storage = KEY_STORAGE_INCORE;
-             break;
-           }
-         break;
-       case TYPE_IDARRAY:
-       case TYPE_REL_IDARRAY:
-          if (id >= INTERESTED_START && id <= INTERESTED_END)
-           keys[i].storage = KEY_STORAGE_SOLVABLE;
-         else
-           keys[i].storage = KEY_STORAGE_INCORE;
-         break;
-       case TYPE_U32:
-         if (id == RPM_RPMDBID)
-           keys[i].storage = KEY_STORAGE_SOLVABLE;
-         else
-           keys[i].storage = KEY_STORAGE_INCORE;
-         break;
-       default:
-         break;
+         if (idmap)
+           keys[i].size = idmap[keys[i].size];
+         else if (parent)
+           keys[i].size = str2id(pool, stringpool_id2str(spool, keys[i].size), 1);
        }
+#if 0
+      fprintf(stderr, "key %d %s %s %d %d\n", i, id2str(pool,id), id2str(pool, keys[i].type),
+               keys[i].size, keys[i].storage);
+#endif
     }
 
   have_xdata = parent ? 1 : 0;
@@ -1050,6 +1095,11 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
 
   /*******  Part 6: Info  ***********************************************/
   oldnrepodata = repo->nrepodata;
+  if (numinfo)
+    {
+      id = read_id(&data, 0);
+      id = read_id(&data, 0);
+    }
   for (i = 0; i < numinfo; i++)
     {
       /* for now we're just interested in data that starts with
@@ -1057,11 +1107,9 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
        */
       Id *keyp;
       id = read_id(&data, numschemata);
-      if (solvversion < SOLV_VERSION_5)
-       id++;
       keyp = schemadata + schemata[id];
       key = *keyp;
-      if (keys[key].name == REPODATA_EXTERNAL && keys[key].type == TYPE_VOID)
+      if (keys[key].name == REPODATA_EXTERNAL && keys[key].type == REPOKEY_TYPE_VOID)
        {
          /* external data for some ids */
          parse_repodata(&data, keyp, keys, idmap, numid, numrel, repo);
@@ -1071,42 +1119,38 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
     }
 
 
-  /*******  Part 7: packed sizes (optional)  ****************************/
-  char *exists = 0;
-  if ((solvflags & SOLV_FLAG_PACKEDSIZES) != 0)
-    {
-      exists = sat_malloc (numsolv);
-      for (i = 0; i < numsolv; i++)
-       exists[i] = read_id(&data, 0) != 0;
-    }
-
-
-  /*******  Part 8: item data *******************************************/
+  /*******  Part 7: item data *******************************************/
 
   /* calculate idarray size */
   size_idarray = 0;
   for (i = 1; i < numkeys; i++)
     {
       id = keys[i].name;
-      if ((keys[i].type == TYPE_IDARRAY || keys[i].type == TYPE_REL_IDARRAY)
+      if ((keys[i].type == REPOKEY_TYPE_IDARRAY || keys[i].type == REPOKEY_TYPE_REL_IDARRAY)
           && id >= INTERESTED_START && id <= INTERESTED_END)
        size_idarray += keys[i].size;
     }
 
-  /* allocate needed space in repo */
-  if (size_idarray)
+  if (numsolv)
     {
-      repo_reserve_ids(repo, 0, size_idarray);
-      idarraydatap = repo->idarraydata + repo->idarraysize;
-      repo->idarraysize += size_idarray;
-      idarraydataend = idarraydatap + size_idarray;
-      repo->lastoff = 0;
+      maxsize = read_id(&data, 0);
+      allsize = read_id(&data, 0);
+      if (maxsize > allsize)
+       {
+         pool_debug(pool, SAT_ERROR, "maxsize %d is greater then allsize %d\n", maxsize, allsize);
+         data.error = SOLV_ERROR_CORRUPT;
+       }
     }
   else
-    {
-      idarraydatap = 0;
-      idarraydataend = 0;
-    }
+    maxsize = allsize = 0;
+
+  /* allocate needed space in repo */
+  /* we add maxsize because it is an upper limit for all idarrays */
+  repo_reserve_ids(repo, 0, size_idarray + maxsize + 1);
+  idarraydatap = repo->idarraydata + repo->idarraysize;
+  repo->idarraysize += size_idarray;
+  idarraydataend = idarraydatap + size_idarray;
+  repo->lastoff = 0;
 
   /* read solvables */
   if (numsolv)
@@ -1132,16 +1176,38 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
   if (have_xdata)
     repodata_extend_block(&data, data.start, numsolv);
 
+  left = 0;
+  buf = sat_calloc(maxsize + 4, 1);
+  dp = buf;
   for (i = 0; i < numsolv; i++, s++)
     {
       Id *keyp;
       if (data.error)
        break;
-      if (exists && !exists[i])
-        continue;
-      id = read_id(&data, numschemata);
-      if (solvversion < SOLV_VERSION_5)
-       id++;
+
+      left -= (dp - buf);
+      if (left < 0)
+        {
+         pool_debug(mypool, SAT_ERROR, "buffer overrun\n");
+         data.error = SOLV_ERROR_EOF;
+         break;
+        }
+      if (left)
+        memmove(buf, dp, left);
+      l = maxsize - left;
+      if (l > allsize)
+        l = allsize;
+      if (l && fread(buf + left, l, 1, data.fp) != 1)
+        {
+         pool_debug(mypool, SAT_ERROR, "unexpected EOF\n");
+         data.error = SOLV_ERROR_EOF;
+         break;
+        }
+      allsize -= l;
+      left += l;
+      dp = buf;
+
+      dp = data_read_id_max(dp, &id, 0, numschemata, &data.error);
       if (have_xdata)
        {
          data.incoreoffset[i] = data.incoredatalen;
@@ -1150,6 +1216,9 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
       keyp = schemadata + schemata[id];
       while ((key = *keyp++) != 0)
        {
+         if (data.error)
+           break;
+
          id = keys[key].name;
 #if 0
 fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, keys[key].storage);
@@ -1157,21 +1226,16 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key
          if (keys[key].storage == KEY_STORAGE_VERTICAL_OFFSET)
            {
              /* copy offset/length into incore */
-             did = read_id(&data, 0);
-             incore_add_id(&data, did);
-             did = read_id(&data, 0);
-             incore_add_id(&data, did);
+             dps = dp;
+             dp = data_skip(dp, REPOKEY_TYPE_ID);
+             dp = data_skip(dp, REPOKEY_TYPE_ID);
+             incore_add_blob(&data, dps, dp - dps);
              continue;
            }
          switch (keys[key].type)
            {
-           case TYPE_VOID:
-           case TYPE_CONSTANT:
-             break;
-           case TYPE_ID:
-             did = read_id(&data, numid + numrel);
-             if (idmap)
-               did = idmap[did];
+           case REPOKEY_TYPE_ID:
+             dp = data_read_id_max(dp, &did, idmap, numid + numrel, &data.error);
              if (id == SOLVABLE_NAME)
                s->name = did;
              else if (id == SOLVABLE_ARCH)
@@ -1186,16 +1250,8 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key
              POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %s\n", id2str(pool, id), id2str(pool, did));
 #endif
              break;
-           case TYPE_NUM:
-             did = read_id(&data, 0);
-             if (keys[key].storage == KEY_STORAGE_INCORE)
-               incore_add_id(&data, did);
-#if 0
-             POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %d\n", id2str(pool, id), did);
-#endif
-             break;
-           case TYPE_U32:
-             h = read_u32(&data);
+           case REPOKEY_TYPE_U32:
+             dp = data_read_u32(dp, &h);
 #if 0
              POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %u\n", id2str(pool, id), h);
 #endif
@@ -1208,53 +1264,33 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key
              else if (keys[key].storage == KEY_STORAGE_INCORE)
                incore_add_u32(&data, h);
              break;
-           case TYPE_STR:
-              if (keys[key].storage == KEY_STORAGE_INCORE)
-               {
-                 while ((h = read_u8(&data)) != 0)
-                   incore_add_u8(&data, h);
-                 incore_add_u8(&data, 0);
-               }
-             else
-               {
-                 while (read_u8(&data) != 0)
-                   ;
-               }
-             break;
-           case TYPE_IDARRAY:
-           case TYPE_REL_IDARRAY:
+           case REPOKEY_TYPE_IDARRAY:
+           case REPOKEY_TYPE_REL_IDARRAY:
              if (id < INTERESTED_START || id > INTERESTED_END)
                {
+                 dps = dp;
+                 dp = data_skip(dp, REPOKEY_TYPE_IDARRAY);
+                 if (keys[key].storage == KEY_STORAGE_INCORE && idmap)
+                   abort();
                  if (keys[key].storage == KEY_STORAGE_INCORE)
-                   {
-                     if (idmap)
-                       {
-                         abort();      /* implement me! */
-                       }
-                     else
-                       {
-                         while (((h = read_u8(&data)) & 0xc0) != 0)
-                           incore_add_u8(&data, h);
-                         break;
-                       }
-                   }
-                 else
-                   {
-                     while ((read_u8(&data) & 0xc0) != 0)
-                       ;
-                     break;
-                   }
+                   incore_add_blob(&data, dps, dp - dps);
                  break;
                }
              ido = idarraydatap - repo->idarraydata;
-             if (keys[key].type == TYPE_IDARRAY)
-               idarraydatap = read_idarray(&data, numid + numrel, idmap, idarraydatap, idarraydataend);
+             if (keys[key].type == REPOKEY_TYPE_IDARRAY)
+               dp = data_read_idarray(dp, &idarraydatap, idmap, numid + numrel, &data.error);
              else if (id == SOLVABLE_REQUIRES)
-               idarraydatap = read_rel_idarray(&data, numid + numrel, idmap, idarraydatap, idarraydataend, SOLVABLE_PREREQMARKER);
+               dp = data_read_rel_idarray(dp, &idarraydatap, idmap, numid + numrel, &data.error, SOLVABLE_PREREQMARKER);
              else if (id == SOLVABLE_PROVIDES)
-               idarraydatap = read_rel_idarray(&data, numid + numrel, idmap, idarraydatap, idarraydataend, SOLVABLE_FILEMARKER);
+               dp = data_read_rel_idarray(dp, &idarraydatap, idmap, numid + numrel, &data.error, SOLVABLE_FILEMARKER);
              else
-               idarraydatap = read_rel_idarray(&data, numid + numrel, idmap, idarraydatap, idarraydataend, 0);
+               dp = data_read_rel_idarray(dp, &idarraydatap, idmap, numid + numrel, &data.error, 0);
+             if (idarraydatap > idarraydataend)
+               {
+                 pool_debug(pool, SAT_ERROR, "idarray overflow\n");
+                 data.error = SOLV_ERROR_OVERFLOW;
+                 break;
+               }
              if (id == SOLVABLE_PROVIDES)
                s->provides = ido;
              else if (id == SOLVABLE_OBSOLETES)
@@ -1279,52 +1315,29 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key
                POOL_DEBUG(SAT_DEBUG_STATS,"  %s\n", dep2str(pool, repo->idarraydata[ido]));
 #endif
              break;
-           case TYPE_DIRNUMNUMARRAY:
-             for (;;)
-               {
-                 Id num, num2;
-                 did = read_id(&data, numdir);
-                 num = read_id(&data, 0);
-                 num2 = read_id(&data, 0);
-                 if (keys[key].storage == KEY_STORAGE_INCORE)
-                   {
-#if 0
-                     POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %d %d %d\n", id2str(pool, id), did, num, num2);
-#endif
-                     incore_add_id(&data, did);
-                     incore_add_id(&data, num);
-                     incore_add_id(&data, num2);
-                   }
-                 if (!(num2 & 0x40))
-                   break;
-               }
-             break;
-           case TYPE_DIRSTRARRAY:
-             for (;;)
-               {
-                 did = read_id(&data, 0);
-                 if (keys[key].storage == KEY_STORAGE_INCORE)
-                   {
-                     incore_add_id(&data, did);
-                     while ((h = read_u8(&data)) != 0)
-                       incore_add_u8(&data, h);
-                     incore_add_u8(&data, 0);
-                   }
-                 else
-                   {
-                     while (read_u8(&data) != 0)
-                       ;
-                   }
-                 if (!(did & 0x40))
-                   break;
-               }
-             break;
            default:
-             skip_item(&data, keys[key].type, numid, numrel);
+             dps = dp;
+             dp = data_skip(dp, keys[key].type);
+             if (keys[key].storage == KEY_STORAGE_INCORE)
+               incore_add_blob(&data, dps, dp - dps);
+             break;
            }
        }
     }
 
+  /* should shrink idarraydata again */
+
+  if (!data.error)
+    {
+      left -= (dp - buf);
+      if (left < 0)
+        {
+         pool_debug(mypool, SAT_ERROR, "buffer overrun\n");
+         data.error = SOLV_ERROR_EOF;
+        }
+    }
+  sat_free(buf);
+
   if (data.error)
     {
       /* free solvables */
@@ -1369,7 +1382,7 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key
       data.fp = 0;
     }
 
-  if (parent)
+  if (parent && !data.error)
     {
       /* we're a store */
       sat_free(parent->schemata);
@@ -1378,7 +1391,7 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key
       sat_free(parent->location);
       *parent = data;
     }
-  else if (data.incoredatalen || data.fp)
+  else if ((data.incoredatalen || data.fp) && !data.error)
     {
       /* we got some data, make it available */
       repo->repodata = sat_realloc2(repo->repodata, repo->nrepodata + 1, sizeof(data));
@@ -1394,7 +1407,6 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key
       sat_free(keys);
     }
 
-  sat_free(exists);
   sat_free(idmap);
   mypool = 0;
   return data.error;
index 31d1e67..60fc61f 100644 (file)
@@ -26,6 +26,8 @@
 #include "poolid_private.h"
 #include "util.h"
 
+#include "repopack.h"
+
 extern unsigned int compress_buf (const unsigned char *in, unsigned int in_len,
                                  unsigned char *out, unsigned int out_len);
 extern unsigned int unchecked_decompress_buf (const unsigned char *in,
@@ -63,142 +65,8 @@ repodata_free(Repodata *data)
   sat_free(data->attrdata);
   sat_free(data->attriddata);
   
-  if (data->fp)
-    fclose(data->fp);
-}
-
-static unsigned char *
-data_read_id(unsigned char *dp, Id *idp)
-{
-  Id x = 0;
-  unsigned char c;
-  for (;;)
-    {
-      c = *dp++;
-      if (!(c & 0x80))
-       {
-         *idp = (x << 7) ^ c;
-          return dp;
-       }
-      x = (x << 7) ^ c ^ 128;
-    }
-}
-
-static unsigned char *
-data_read_ideof(unsigned char *dp, Id *idp, int *eof)
-{
-  Id x = 0;
-  unsigned char c;
-  for (;;)
-    {
-      c = *dp++;
-      if (!(c & 0x80))
-       {
-         if (c & 0x40)
-           {
-             c ^= 0x40;
-             *eof = 0;
-           }
-         else
-           *eof = 1;
-         *idp = (x << 6) ^ c;
-          return dp;
-       }
-      x = (x << 7) ^ c ^ 128;
-    }
-}
-
-static unsigned char *
-data_skip(unsigned char *dp, int type)
-{
-  unsigned char x;
-  switch (type)
-    {
-    case TYPE_VOID:
-    case TYPE_CONSTANT:
-      return dp;
-    case TYPE_ID:
-    case TYPE_NUM:
-    case TYPE_DIR:
-      while ((*dp & 0x80) != 0)
-       dp++;
-      return dp + 1;
-    case TYPE_IDARRAY:
-      while ((*dp & 0xc0) != 0)
-       dp++;
-      return dp + 1;
-    case TYPE_STR:
-      while ((*dp) != 0)
-       dp++;
-      return dp + 1;
-    case TYPE_DIRSTRARRAY:
-      for (;;)
-       {
-          while ((*dp & 0x80) != 0)
-           dp++;
-         x = *dp++;
-          while ((*dp) != 0)
-           dp++;
-         dp++;
-         if (!(x & 0x40))
-           return dp;
-       }
-    case TYPE_DIRNUMNUMARRAY:
-      for (;;)
-       {
-         while ((*dp & 0x80) != 0)
-           dp++;
-         dp++;
-         while ((*dp & 0x80) != 0)
-           dp++;
-         dp++;
-         while ((*dp & 0x80) != 0)
-           dp++;
-         if (!(*dp & 0x40))
-           return dp + 1;
-         dp++;
-       }
-    default:
-      fprintf(stderr, "unknown type in data_skip\n");
-      exit(1);
-    }
-}
-
-static unsigned char *
-data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key)
-{
-  kv->eof = 1;
-  if (!dp)
-    return 0;
-  switch (key->type)
-    {
-    case TYPE_VOID:
-      return dp;
-    case TYPE_CONSTANT:
-      kv->num = key->size;
-      return dp;
-    case TYPE_STR:
-      kv->str = (const char *)dp;
-      return dp + strlen(kv->str) + 1;
-    case TYPE_ID:
-      return data_read_id(dp, &kv->id);
-    case TYPE_NUM:
-      return data_read_id(dp, &kv->num);
-    case TYPE_IDARRAY:
-      return data_read_ideof(dp, &kv->id, &kv->eof);
-    case TYPE_DIR:
-      return data_read_id(dp, &kv->id);
-    case TYPE_DIRSTRARRAY:
-      dp = data_read_ideof(dp, &kv->id, &kv->eof);
-      kv->str = (const char *)dp;
-      return dp + strlen(kv->str) + 1;
-    case TYPE_DIRNUMNUMARRAY:
-      dp = data_read_id(dp, &kv->id);
-      dp = data_read_id(dp, &kv->num);
-      return data_read_ideof(dp, &kv->num2, &kv->eof);
-    default:
-      return 0;
-    }
+  if (data->pagefd != -1)
+    close(data->pagefd);
 }
 
 static unsigned char *
@@ -213,8 +81,8 @@ forward_to_key(Repodata *data, Id key, Id schemaid, unsigned char *dp)
        return dp;
       if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
        {
-         dp = data_skip(dp, TYPE_ID);  /* skip that offset */
-         dp = data_skip(dp, TYPE_ID);  /* skip that length */
+         dp = data_skip(dp, REPOKEY_TYPE_ID);  /* skip that offset */
+         dp = data_skip(dp, REPOKEY_TYPE_ID);  /* skip that length */
          continue;
        }
       if (data->keys[k].storage != KEY_STORAGE_INCORE)
@@ -354,27 +222,20 @@ load_page_range(Repodata *data, unsigned int pstart, unsigned int pend)
 #ifdef DEBUG_PAGING
          fprintf (stderr, "PAGEIN: %d to %d", i, pnum);
 #endif
-         /* Not mapped, so read in this page.  */
-         if (fseek(data->fp, p->file_offset, SEEK_SET) < 0)
-           {
-             perror ("mapping fseek");
-             exit (1);
-           }
-         if (fread(compressed ? buf : dest, in_len, 1, data->fp) != 1)
+          if (pread(data->pagefd, compressed ? buf : dest, in_len, p->file_offset) != in_len)
            {
-             perror ("mapping fread");
-             exit (1);
+             perror ("mapping pread");
+             return 0;
            }
          if (compressed)
            {
              unsigned int out_len;
              out_len = unchecked_decompress_buf(buf, in_len,
                                                  dest, BLOB_PAGESIZE);
-             if (out_len != BLOB_PAGESIZE
-                 && i < data->num_pages - 1)
+             if (out_len != BLOB_PAGESIZE && i < data->num_pages - 1)
                {
-                 fprintf (stderr, "can't decompress\n");
-                 exit (1);
+                 fprintf(stderr, "can't decompress\n");
+                 return 0;
                }
 #ifdef DEBUG_PAGING
              fprintf (stderr, " (expand %d to %d)", in_len, out_len);
@@ -394,7 +255,7 @@ static unsigned char *
 make_vertical_available(Repodata *data, Repokey *key, Id off, Id len)
 {
   unsigned char *dp;
-  if (key->type == TYPE_VOID)
+  if (key->type == REPOKEY_TYPE_VOID)
     return 0;
   if (off >= data->lastverticaloffset)
     {
@@ -403,7 +264,7 @@ make_vertical_available(Repodata *data, Repokey *key, Id off, Id len)
        return 0;
       return data->vincore + off;
     }
-  if (!data->fp)
+  if (data->pagefd == -1)
     return 0;
   if (off + len > key->size)
     return 0;
@@ -477,12 +338,14 @@ repodata_lookup_str(Repodata *data, Id entry, Id keyid)
   dp = get_data(data, key, &dp);
   if (!dp)
     return 0;
-  if (key->type == TYPE_STR)
+  if (key->type == REPOKEY_TYPE_STR)
     return (const char *)dp;
-  if (key->type != TYPE_ID)
+  if (key->type == REPOKEY_TYPE_CONSTANTID)
+    return id2str(data->repo->pool, key->size);
+  if (key->type == REPOKEY_TYPE_ID)
+    dp = data_read_id(dp, &id);
+  else
     return 0;
-  /* id type, must either use global or local string store*/
-  dp = data_read_id(dp, &id);
   if (data->localpool)
     return data->spool.stringspace + data->spool.strings[id];
   return id2str(data->repo->pool, id);
@@ -513,9 +376,9 @@ repodata_lookup_num(Repodata *data, Id entry, Id keyid, unsigned *value)
   dp = get_data(data, key, &dp);
   if (!dp)
     return 0;
-  if (key->type == TYPE_NUM
-      || key->type == TYPE_U32
-      || key->type == TYPE_CONSTANT)
+  if (key->type == REPOKEY_TYPE_NUM
+      || key->type == REPOKEY_TYPE_U32
+      || key->type == REPOKEY_TYPE_CONSTANT)
     {
       dp = data_fetch(dp, &kv, key);
       *value = kv.num;
@@ -672,14 +535,14 @@ dataiterator_match(Dataiterator *di, KeyValue *kv)
     {
       switch (di->key->type)
        {
-       case TYPE_ID:
-       case TYPE_IDARRAY:
+       case REPOKEY_TYPE_ID:
+       case REPOKEY_TYPE_IDARRAY:
          if (di->data && di->data->localpool)
            kv->str = stringpool_id2str(&di->data->spool, kv->id);
          else
            kv->str = id2str(di->repo->pool, kv->id);
          break;
-       case TYPE_STR:
+       case REPOKEY_TYPE_STR:
          break;
        default:
          return 0;
@@ -727,20 +590,20 @@ dataiterator_match(Dataiterator *di, KeyValue *kv)
 }
 
 static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = {
-  { SOLVABLE_NAME,        TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_ARCH,        TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_EVR,         TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_VENDOR,      TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_PROVIDES,    TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_OBSOLETES,   TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_CONFLICTS,   TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_REQUIRES,    TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_RECOMMENDS,  TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_SUGGESTS,    TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_SUPPLEMENTS, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_ENHANCES,    TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { SOLVABLE_FRESHENS,    TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
-  { RPM_RPMDBID,          TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_NAME,        REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_ARCH,        REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_EVR,         REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_VENDOR,      REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_PROVIDES,    REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_OBSOLETES,   REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_CONFLICTS,   REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_REQUIRES,    REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_RECOMMENDS,  REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_SUGGESTS,    REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_ENHANCES,    REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { SOLVABLE_FRESHENS,    REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE },
+  { RPM_RPMDBID,          REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE },
 };
 
 int
@@ -921,6 +784,7 @@ repodata_init(Repodata *data, Repo *repo, int localpool)
   data->start = repo->start;
   data->end = repo->end;
   data->incoreoffset = sat_extend_resize(0, data->end - data->start, sizeof(Id), REPODATA_BLOCK);
+  data->pagefd = -1;
 }
 
 /* extend repodata so that it includes solvables p */
@@ -1026,7 +890,7 @@ repodata_set(Repodata *data, Id entry, Repokey *key, Id val)
   for (keyid = 1; keyid < data->nkeys; keyid++)
     if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type)
       {
-        if (key->type == TYPE_CONSTANT && key->size != data->keys[keyid].size)
+        if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size)
           continue;
         break;
       }
@@ -1049,7 +913,7 @@ repodata_set_id(Repodata *data, Id entry, Id keyname, Id id)
 {
   Repokey key;
   key.name = keyname;
-  key.type = TYPE_ID;
+  key.type = REPOKEY_TYPE_ID;
   key.size = 0;
   key.storage = KEY_STORAGE_INCORE;
   repodata_set(data, entry, &key, id);
@@ -1060,7 +924,7 @@ repodata_set_num(Repodata *data, Id entry, Id keyname, Id num)
 {
   Repokey key;
   key.name = keyname;
-  key.type = TYPE_NUM;
+  key.type = REPOKEY_TYPE_NUM;
   key.size = 0;
   key.storage = KEY_STORAGE_INCORE;
   repodata_set(data, entry, &key, num);
@@ -1076,7 +940,7 @@ repodata_set_poolstr(Repodata *data, Id entry, Id keyname, const char *str)
   else
     id = str2id(data->repo->pool, str, 1);
   key.name = keyname;
-  key.type = TYPE_ID;
+  key.type = REPOKEY_TYPE_ID;
   key.size = 0;
   key.storage = KEY_STORAGE_INCORE;
   repodata_set(data, entry, &key, id);
@@ -1087,18 +951,29 @@ repodata_set_constant(Repodata *data, Id entry, Id keyname, Id constant)
 {
   Repokey key;
   key.name = keyname;
-  key.type = TYPE_CONSTANT;
+  key.type = REPOKEY_TYPE_CONSTANT;
   key.size = constant;
   key.storage = KEY_STORAGE_INCORE;
   repodata_set(data, entry, &key, 0);
 }
 
 void
+repodata_set_constantid(Repodata *data, Id entry, Id keyname, Id id)
+{
+  Repokey key;
+  key.name = keyname;
+  key.type = REPOKEY_TYPE_CONSTANTID;
+  key.size = id;
+  key.storage = KEY_STORAGE_INCORE;
+  repodata_set(data, entry, &key, 0);
+}
+
+void
 repodata_set_void(Repodata *data, Id entry, Id keyname)
 {
   Repokey key;
   key.name = keyname;
-  key.type = TYPE_VOID;
+  key.type = REPOKEY_TYPE_VOID;
   key.size = 0;
   key.storage = KEY_STORAGE_INCORE;
   repodata_set(data, entry, &key, 0);
@@ -1112,7 +987,7 @@ repodata_set_str(Repodata *data, Id entry, Id keyname, const char *str)
 
   l = strlen(str) + 1;
   key.name = keyname;
-  key.type = TYPE_STR;
+  key.type = REPOKEY_TYPE_STR;
   key.size = 0;
   key.storage = KEY_STORAGE_INCORE;
   data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
@@ -1133,7 +1008,7 @@ fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", entry, dir, num, nu
   if (data->attrs && data->attrs[entry])
     {
       for (pp = data->attrs[entry]; *pp; pp += 2)
-        if (data->keys[*pp].name == keyname && data->keys[*pp].type == TYPE_DIRNUMNUMARRAY)
+        if (data->keys[*pp].name == keyname && data->keys[*pp].type == REPOKEY_TYPE_DIRNUMNUMARRAY)
          break;
       if (*pp)
        {
@@ -1162,7 +1037,7 @@ fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", entry, dir, num, nu
        }
     }
   key.name = keyname;
-  key.type = TYPE_DIRNUMNUMARRAY;
+  key.type = REPOKEY_TYPE_DIRNUMNUMARRAY;
   key.size = 0;
   key.storage = KEY_STORAGE_INCORE;
   data->attriddata = sat_extend(data->attriddata, data->attriddatalen, 4, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
@@ -1192,7 +1067,7 @@ fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", entry, dir, str,  data->a
   if (data->attrs && data->attrs[entry])
     {
       for (pp = data->attrs[entry]; *pp; pp += 2)
-        if (data->keys[*pp].name == keyname && data->keys[*pp].type == TYPE_DIRSTRARRAY)
+        if (data->keys[*pp].name == keyname && data->keys[*pp].type == REPOKEY_TYPE_DIRSTRARRAY)
          break;
       if (*pp)
        {
@@ -1220,7 +1095,7 @@ fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", entry, dir, str,  data->a
        }
     }
   key.name = keyname;
-  key.type = TYPE_DIRSTRARRAY;
+  key.type = REPOKEY_TYPE_DIRSTRARRAY;
   key.size = 0;
   key.storage = KEY_STORAGE_INCORE;
   data->attriddata = sat_extend(data->attriddata, data->attriddatalen, 3, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
@@ -1439,8 +1314,8 @@ fprintf(stderr, "schemadata %p\n", data->schemadata);
              /* Skip the data associated with this old key.  */
              if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
                {
-                 ndp = data_skip(dp, TYPE_ID);
-                 ndp = data_skip(ndp, TYPE_ID);
+                 ndp = data_skip(dp, REPOKEY_TYPE_ID);
+                 ndp = data_skip(ndp, REPOKEY_TYPE_ID);
                }
              else if (key->storage == KEY_STORAGE_INCORE)
                ndp = data_skip(dp, key->type);
@@ -1471,18 +1346,19 @@ fprintf(stderr, "schemadata %p\n", data->schemadata);
              id = seen[*keyp] - 1;
              switch (key->type)
                {
-               case TYPE_VOID:
-               case TYPE_CONSTANT:
+               case REPOKEY_TYPE_VOID:
+               case REPOKEY_TYPE_CONSTANT:
+               case REPOKEY_TYPE_CONSTANTID:
                  break;
-               case TYPE_STR:
+               case REPOKEY_TYPE_STR:
                  data_addblob(xd, data->attrdata + id, strlen((char *)(data->attrdata + id)) + 1);
                  break;
-               case TYPE_ID:
-               case TYPE_NUM:
-               case TYPE_DIR:
+               case REPOKEY_TYPE_ID:
+               case REPOKEY_TYPE_NUM:
+               case REPOKEY_TYPE_DIR:
                  data_addid(xd, id);
                  break;
-               case TYPE_DIRNUMNUMARRAY:
+               case REPOKEY_TYPE_DIRNUMNUMARRAY:
                  for (ida = data->attriddata + id; *ida; ida += 3)
                    {
                      data_addid(xd, ida[0]);
@@ -1490,7 +1366,7 @@ fprintf(stderr, "schemadata %p\n", data->schemadata);
                      data_addideof(xd, ida[2], ida[3] ? 0 : 1);
                    }
                  break;
-               case TYPE_DIRSTRARRAY:
+               case REPOKEY_TYPE_DIRSTRARRAY:
                  for (ida = data->attriddata + id; *ida; ida += 2)
                    {
                      data_addideof(xd, ida[0], ida[2] ? 0 : 1);
@@ -1587,10 +1463,12 @@ read_u32(FILE *fp)
   return x;
 }
 
+#define SOLV_ERROR_EOF         3
+#define SOLV_ERROR_CORRUPT     6
+
 /* Try to either setup on-demand paging (using FP as backing
    file), or in case that doesn't work (FP not seekable) slurps in
    all pages and deactivates paging.  */
-
 void
 repodata_read_or_setup_pages(Repodata *data, unsigned int pagesz, unsigned int blobsz)
 {
@@ -1600,16 +1478,22 @@ repodata_read_or_setup_pages(Repodata *data, unsigned int pagesz, unsigned int b
   unsigned int can_seek;
   long cur_file_ofs;
   unsigned char buf[BLOB_PAGESIZE];
+
   if (pagesz != BLOB_PAGESIZE)
     {
       /* We could handle this by slurping in everything.  */
-      fprintf (stderr, "non matching page size\n");
-      exit (1);
+      data->error = SOLV_ERROR_CORRUPT;
+      return;
     }
   can_seek = 1;
   if ((cur_file_ofs = ftell(fp)) < 0)
     can_seek = 0;
-  clearerr (fp);
+  clearerr(fp);
+  if (can_seek)
+    data->pagefd = dup(fileno(fp));
+  if (data->pagefd == -1)
+    can_seek = 0;
+
 #ifdef DEBUG_PAGING
   fprintf (stderr, "can %sseek\n", can_seek ? "" : "NOT ");
 #endif
@@ -1643,7 +1527,10 @@ repodata_read_or_setup_pages(Repodata *data, unsigned int pagesz, unsigned int b
              fprintf (stderr, "can't seek after we thought we can\n");
              /* We can't fall back to non-seeking behaviour as we already
                 read over some data pages without storing them away.  */
-             exit (1);
+             data->error = SOLV_ERROR_EOF;
+             close(data->pagefd);
+             data->pagefd = -1;
+             return;
            }
          cur_file_ofs += in_len;
        }
@@ -1657,48 +1544,23 @@ repodata_read_or_setup_pages(Repodata *data, unsigned int pagesz, unsigned int b
          /* We can't seek, so suck everything in.  */
          if (fread(compressed ? buf : dest, in_len, 1, fp) != 1)
            {
-             perror ("fread");
-             exit (1);
+             perror("fread");
+             data->error = SOLV_ERROR_EOF;
+             return;
            }
          if (compressed)
            {
              out_len = unchecked_decompress_buf(buf, in_len, dest, BLOB_PAGESIZE);
-             if (out_len != BLOB_PAGESIZE
-                 && i < npages - 1)
+             if (out_len != BLOB_PAGESIZE && i < npages - 1)
                {
-                 fprintf (stderr, "can't decompress\n");
-                 exit (1);
+                 data->error = SOLV_ERROR_CORRUPT;
+                 return;
                }
            }
        }
     }
-
-  if (can_seek)
-    {
-      /* If we are here we were able to seek to all page
-         positions, so activate paging by copying FP into our structure.
-        We dup() the file, so that our callers can fclose() it and we
-        still have it open.  But this means that we share file positions
-        with the input filedesc.  So in case our caller reads it after us,
-        and calls back into us we might change the file position unexpectedly
-        to him.  */
-      int fd = dup (fileno (fp));
-      if (fd < 0)
-        {
-         /* Jeez!  What a bloody system, we can't dup() anymore.  */
-         perror ("dup");
-         exit (1);
-       }
-      /* XXX we don't close this yet anywhere.  */
-      data->fp = fdopen (fd, "r");
-      if (!data->fp)
-        {
-         /* My God!  What happened now?  */
-         perror ("fdopen");
-         exit (1);
-       }
-    }
 }
+
 /*
 vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4:
 */
index f3fafb2..cb81793 100644 (file)
@@ -57,6 +57,7 @@ typedef struct _Repodata {
   FILE *fp;                    /* file pointer of solv file */
   int error;                   /* corrupt solv file */
 
+
   struct _Repokey *keys;       /* keys, first entry is always zero */
   unsigned int nkeys;          /* length of keys array */
 
@@ -80,8 +81,8 @@ typedef struct _Repodata {
   Id *verticaloffset;          /* offset for all verticals, nkeys elements */
   Id lastverticaloffset;       /* end of verticals */
 
+  int pagefd;                  /* file descriptor of page file */
   unsigned char *blob_store;
-
   Attrblobpage *pages;
   unsigned int num_pages;
 
@@ -127,6 +128,7 @@ void repodata_set_id(Repodata *data, Id entry, Id keyname, Id id);
 void repodata_set_num(Repodata *data, Id entry, Id keyname, Id num);
 void repodata_set_poolstr(Repodata *data, Id entry, Id keyname, const char *str);
 void repodata_set_constant(Repodata *data, Id entry, Id keyname, Id constant);
+void repodata_set_constantid(Repodata *data, Id entry, Id keyname, Id id);
 void repodata_set_void(Repodata *data, Id entry, Id keyname);
 void repodata_set_str(Repodata *data, Id entry, Id keyname, const char *str);
 void repodata_add_dirnumnum(Repodata *data, Id entry, Id keyname, Id dir, Id num, Id num2);
diff --git a/src/repopack.h b/src/repopack.h
new file mode 100644 (file)
index 0000000..fa4e69d
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2007, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+/* pack/unpack functions for key data */
+
+#ifndef SATSOLVER_REPOPACK_H
+#define SATSOLVER_REPOPACK_H
+
+static inline unsigned char *
+data_read_id(unsigned char *dp, Id *idp)
+{
+  Id x = 0;
+  unsigned char c;
+  for (;;)
+    {
+      c = *dp++;
+      if (!(c & 0x80))
+        {
+          *idp = (x << 7) ^ c;
+          return dp;
+        }
+      x = (x << 7) ^ c ^ 128;
+    }
+}
+
+static inline unsigned char *
+data_read_ideof(unsigned char *dp, Id *idp, int *eof)
+{
+  Id x = 0;
+  unsigned char c;
+  for (;;)
+    {
+      c = *dp++;
+      if (!(c & 0x80))
+        {
+          if (c & 0x40)
+            {
+              c ^= 0x40;
+              *eof = 0;
+            }
+          else
+            *eof = 1;
+          *idp = (x << 6) ^ c;
+          return dp;
+        }
+      x = (x << 7) ^ c ^ 128;
+    }
+}
+
+static inline unsigned char *
+data_read_u32(unsigned char *dp, unsigned int *nump)
+{
+  *nump = (dp[0] << 24) | (dp[1] << 16) | (dp[2] << 8) | dp[3];
+  return dp + 4;
+}
+
+static inline unsigned char *
+data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key)
+{
+  kv->eof = 1;
+  if (!dp)
+    return 0;
+  switch (key->type)
+    {
+    case REPOKEY_TYPE_VOID:
+      return dp;
+    case REPOKEY_TYPE_CONSTANT:
+      kv->num = key->size;
+      return dp;
+    case REPOKEY_TYPE_CONSTANTID:
+      kv->id = key->size;
+      return dp;
+    case REPOKEY_TYPE_STR:
+      kv->str = (const char *)dp;
+      return dp + strlen(kv->str) + 1;
+    case REPOKEY_TYPE_ID:
+    case REPOKEY_TYPE_DIR:
+      return data_read_id(dp, &kv->id);
+    case REPOKEY_TYPE_NUM:
+      return data_read_id(dp, &kv->num);
+    case REPOKEY_TYPE_U32:
+      return data_read_u32(dp, (unsigned int *)&kv->num);
+    case REPOKEY_TYPE_IDARRAY:
+      return data_read_ideof(dp, &kv->id, &kv->eof);
+    case REPOKEY_TYPE_DIRSTRARRAY:
+      dp = data_read_ideof(dp, &kv->id, &kv->eof);
+      kv->str = (const char *)dp;
+      return dp + strlen(kv->str) + 1;
+    case REPOKEY_TYPE_DIRNUMNUMARRAY:
+      dp = data_read_id(dp, &kv->id);
+      dp = data_read_id(dp, &kv->num);
+      return data_read_ideof(dp, &kv->num2, &kv->eof);
+    default:
+      return 0;
+    }
+}
+
+static inline unsigned char *
+data_skip(unsigned char *dp, int type)
+{
+  unsigned char x;
+  switch (type)
+    {
+    case REPOKEY_TYPE_VOID:
+    case REPOKEY_TYPE_CONSTANT:
+    case REPOKEY_TYPE_CONSTANTID:
+      return dp;
+    case REPOKEY_TYPE_ID:
+    case REPOKEY_TYPE_NUM:
+    case REPOKEY_TYPE_DIR:
+      while ((*dp & 0x80) != 0)
+        dp++;
+      return dp + 1;
+    case REPOKEY_TYPE_U32:
+      return dp + 4;
+    case REPOKEY_TYPE_IDARRAY:
+    case REPOKEY_TYPE_REL_IDARRAY:
+      while ((*dp & 0xc0) != 0)
+        dp++;
+      return dp + 1;
+    case REPOKEY_TYPE_STR:
+      while ((*dp) != 0)
+        dp++;
+      return dp + 1;
+    case REPOKEY_TYPE_DIRSTRARRAY:
+      for (;;)
+        {
+          while ((*dp & 0x80) != 0)
+            dp++;
+          x = *dp++;
+          while ((*dp) != 0)
+            dp++;
+          dp++;
+          if (!(x & 0x40))
+            return dp;
+        }
+    case REPOKEY_TYPE_DIRNUMNUMARRAY:
+      for (;;)
+        {
+          while ((*dp & 0x80) != 0)
+            dp++;
+          dp++;
+          while ((*dp & 0x80) != 0)
+            dp++;
+          dp++;
+          while ((*dp & 0x80) != 0)
+            dp++;
+          if (!(*dp & 0x40))
+            return dp + 1;
+          dp++;
+        }
+    default:
+      return 0;
+    }
+}
+
+static inline unsigned char *
+data_skip_verify(unsigned char *dp, int type, int maxid, int maxdir)
+{
+  Id id;
+  int eof;
+
+  switch (type)
+    {
+    case REPOKEY_TYPE_VOID:
+    case REPOKEY_TYPE_CONSTANT:
+    case REPOKEY_TYPE_CONSTANTID:
+      return dp;
+    case REPOKEY_TYPE_NUM:
+      while ((*dp & 0x80) != 0)
+        dp++;
+      return dp + 1;
+    case REPOKEY_TYPE_U32:
+      return dp + 4;
+    case REPOKEY_TYPE_ID:
+      dp = data_read_id(dp, &id);
+      if (id >= maxid)
+       return 0;
+      return dp;
+    case REPOKEY_TYPE_DIR:
+      dp = data_read_id(dp, &id);
+      if (id >= maxdir)
+       return 0;
+      return dp;
+    case REPOKEY_TYPE_IDARRAY:
+      for (;;)
+       {
+         dp = data_read_ideof(dp, &id, &eof);
+         if (id >= maxid)
+           return 0;
+         if (eof)
+           return dp;
+       }
+    case REPOKEY_TYPE_STR:
+      while ((*dp) != 0)
+        dp++;
+      return dp + 1;
+    case REPOKEY_TYPE_DIRSTRARRAY:
+      for (;;)
+        {
+         dp = data_read_ideof(dp, &id, &eof);
+         if (id >= maxdir)
+           return 0;
+          while ((*dp) != 0)
+            dp++;
+          dp++;
+          if (eof)
+            return dp;
+        }
+    case REPOKEY_TYPE_DIRNUMNUMARRAY:
+      for (;;)
+        {
+         dp = data_read_id(dp, &id);
+         if (id >= maxdir)
+           return 0;
+          while ((*dp & 0x80) != 0)
+            dp++;
+          dp++;
+          while ((*dp & 0x80) != 0)
+            dp++;
+          if (!(*dp & 0x40))
+            return dp + 1;
+          dp++;
+        }
+    default:
+      return 0;
+    }
+}
+
+#endif /* SATSOLVER_REPOPACK */
index 3ffe4ab..977cd28 100644 (file)
@@ -3964,7 +3964,6 @@ solver_calc_duchanges(Solver *solv, DUChanges *mps, int nmps)
 {
   Pool *pool = solv->pool;
   Solvable *s;
-  Id id_diskusage;
   char *p;
   const char *path, *compstr;
   struct mptree *mptree;
@@ -3974,8 +3973,6 @@ solver_calc_duchanges(Solver *solv, DUChanges *mps, int nmps)
   Map installmap;
   struct ducbdata cbd;
 
-  id_diskusage = str2id(pool, "diskusage", 1);
-
   cbd.mps = mps;
   cbd.addsub = 0;
   cbd.dirmap = 0;
@@ -4074,20 +4071,50 @@ solver_calc_duchanges(Solver *solv, DUChanges *mps, int nmps)
       if (!MAPTST(&installmap, i))
        continue;
       s = pool->solvables + i;
-      repo_search(s->repo, i, id_diskusage, 0, 0, solver_fill_DU_cb, &cbd);
+      repo_search(s->repo, i, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
     }
   map_free(&installmap);
   /* run through erase solvable dudata */
   if (solv->installed)
     {
       cbd.addsub = -1;
-      for (i = solv->installed->start; i < solv->installed->end; i++)
+      FOR_REPO_SOLVABLES(solv->installed, i, s)
        {
          if (solv->decisionmap[i] >= 0)
            continue;
-         repo_search(solv->installed, i, id_diskusage, 0, 0, solver_fill_DU_cb, &cbd);
+         repo_search(solv->installed, i, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
        }
     }
   sat_free(cbd.dirmap);
   sat_free(mptree);
 }
+
+int
+solver_calc_installsizechange(Solver *solv)
+{
+  Pool *pool = solv->pool;
+  int i, change;
+  Id p;
+  Solvable *s;
+
+  change = 0;
+  for (i = 1; i < solv->decisionq.count; i++)
+    {
+      Id p = solv->decisionq.elements[i];
+      if (p < 0)
+       continue;
+      s = pool->solvables + p;
+      if (!s->repo)
+       continue;
+      if (solv->installed && s->repo == solv->installed)
+       continue;
+      change += repo_lookup_num(s, SOLVABLE_INSTALLSIZE);
+    }
+  if (solv->installed)
+    {
+      FOR_REPO_SOLVABLES(solv->installed, p, s)
+       if (solv->decisionmap[p] < 0)
+         change -= repo_lookup_num(s, SOLVABLE_INSTALLSIZE);
+    }
+  return change;
+}
index 423f4ec..b446d53 100644 (file)
@@ -286,6 +286,7 @@ typedef struct _duchanges {
 } DUChanges;
 
 void solver_calc_duchanges(Solver *solv, DUChanges *mps, int nmps);
+int solver_calc_installsizechange(Solver *solv);
 
 
 #endif /* SATSOLVER_SOLVER_H */
index 5dfdb82..5485737 100644 (file)
@@ -10,6 +10,10 @@ SET(rpmdb2solv_REPOS
 ADD_EXECUTABLE( rpmdb2solv ${rpmdb2solv_REPOS} )
 TARGET_LINK_LIBRARIES( rpmdb2solv satsolver ${RPMDB_LIBRARY})
 
+SET(rpms2solv_REPOS rpms2solv.c repo_rpmdb.h repo_rpmdb.c repo_write.c common_write.c )
+ADD_EXECUTABLE( rpms2solv ${rpms2solv_REPOS} )
+TARGET_LINK_LIBRARIES( rpms2solv satsolver ${RPMDB_LIBRARY})
+
 SET(rpmmd2solv_REPOS rpmmd2solv.c repo_rpmmd.h repo_rpmmd.c repo_write.c common_write.c )
 ADD_EXECUTABLE( rpmmd2solv ${rpmmd2solv_REPOS} )
 TARGET_LINK_LIBRARIES( rpmmd2solv satsolver ${EXPAT_LIBRARY})
index 04af673..1d644b6 100644 (file)
@@ -26,9 +26,9 @@ dump_repodata (Repo *repo)
   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
     {
       unsigned int j;
-      printf("%s has %d keys", data->location ? data->location : "**EMBED**", data->nkeys);
+      printf("%s has %d keys, %d schemata", data->location ? data->location : "**EMBED**", data->nkeys, data->nschemata);
       for (j = 1; j < data->nkeys; j++)
-        printf("\n  %s (type %d size %d storage %d)", id2str(repo->pool, data->keys[j].name), data->keys[j].type, data->keys[j].size, data->keys[j].storage);
+        printf("\n  %s (type %s size %d storage %d)", id2str(repo->pool, data->keys[j].name), id2str(repo->pool, data->keys[j].type), data->keys[j].size, data->keys[j].storage);
       printf("\n");
     }
   printf("\n");
@@ -72,36 +72,39 @@ dump_repoattrs_cb(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyV
   keyname = id2str(s->repo->pool, key->name);
   switch(key->type)
     {
-    case TYPE_ID:
+    case REPOKEY_TYPE_ID:
       if (data && data->localpool)
        kv->str = stringpool_id2str(&data->spool, kv->id);
       else
         kv->str = id2str(s->repo->pool, kv->id);
       printf("%s: %s\n", keyname, kv->str);
       break;
-    case TYPE_IDARRAY:
+    case REPOKEY_TYPE_CONSTANTID:
+      printf("%s: %s\n", keyname, dep2str(s->repo->pool, kv->id));
+      break;
+    case REPOKEY_TYPE_IDARRAY:
       if (data && data->localpool)
         printf("%s: %s\n", keyname, stringpool_id2str(&data->spool, kv->id));
       else
         printf("%s: %s\n", keyname, dep2str(s->repo->pool, kv->id));
       break;
-    case TYPE_STR:
+    case REPOKEY_TYPE_STR:
       printf("%s: %s\n", keyname, kv->str);
       break;
-    case TYPE_VOID:
-      printf("%s\n", keyname);
+    case REPOKEY_TYPE_VOID:
+      printf("%s: (void)\n", keyname);
       break;
-    case TYPE_U32:
-    case TYPE_NUM:
-    case TYPE_CONSTANT:
+    case REPOKEY_TYPE_U32:
+    case REPOKEY_TYPE_NUM:
+    case REPOKEY_TYPE_CONSTANT:
       printf("%s: %d\n", keyname, kv->num);
       break;
-    case TYPE_DIRNUMNUMARRAY:
+    case REPOKEY_TYPE_DIRNUMNUMARRAY:
       printf("%s: ", keyname);
       printdir(data, kv->id);
       printf(" %d %d\n", kv->num, kv->num2);
       break;
-    case TYPE_DIRSTRARRAY:
+    case REPOKEY_TYPE_DIRSTRARRAY:
       printf("%s: ", keyname);
       printdir(data, kv->id);
       printf("/%s\n", kv->str);
@@ -135,19 +138,13 @@ dump_repoattrs(Repo *repo, Id p)
 void
 dump_some_attrs(Repo *repo, Solvable *s)
 {
-  Id name = str2id (repo->pool, "summary", 0);
   const char *summary = 0;
   unsigned int medianr = -1, downloadsize = -1;
   unsigned int time = -1;
-  if (name)
-    summary = repo_lookup_str (s, name);
-  if ((name = str2id (repo->pool, "medianr", 0)))
-    medianr = repo_lookup_num (s, name);
-  if ((name = str2id (repo->pool, "downloadsize", 0)))
-    downloadsize = repo_lookup_num (s, name);
-  if ((name = str2id (repo->pool, "time", 0)))
-    time = repo_lookup_num (s, name);
-
+  summary = repo_lookup_str(s, SOLVABLE_SUMMARY);
+  medianr = repo_lookup_num(s, SOLVABLE_MEDIANR);
+  downloadsize = repo_lookup_num (s, SOLVABLE_DOWNLOADSIZE);
+  time = repo_lookup_num(s, SOLVABLE_BUILDTIME);
   printf ("  XXX %d %d %u %s\n", medianr, downloadsize, time, summary);
 }
 #endif
@@ -190,15 +187,15 @@ tryme (Repo *repo, Id p, Id keyname, const char *match, int flags)
     {
       switch (di.key->type)
        {
-         case TYPE_ID:
-         case TYPE_IDARRAY:
+         case REPOKEY_TYPE_ID:
+         case REPOKEY_TYPE_IDARRAY:
              if (di.data && di.data->localpool)
                di.kv.str = stringpool_id2str(&di.data->spool, di.kv.id);
              else
                di.kv.str = id2str(repo->pool, di.kv.id);
              break;
-         case TYPE_STR:
-         case TYPE_DIRSTRARRAY:
+         case REPOKEY_TYPE_STR:
+         case REPOKEY_TYPE_DIRSTRARRAY:
              break;
          default:
              di.kv.str = 0;
@@ -285,7 +282,7 @@ int main(int argc, char **argv)
       n++;
     }
 #if 0
-  tryme(repo, 0, str2id (repo->pool, "medianr", 0), 0, 0);
+  tryme(repo, 0, SOLVABLE_MEDIANR, 0, 0);
   printf("\n");
   tryme(repo, 0, 0, 0, 0);
   printf("\n");
index f7edd1e..20761c4 100644 (file)
@@ -154,12 +154,6 @@ struct parsedata {
   struct deltarpm delta;
 };
 
-/* repo data attribute ids */
-static Id id_timestamp;
-static Id id_summary;
-static Id id_description;
-static Id id_category;
-
 #if 0
 static void
 append_str(struct parsedata *pd, const char *s)
@@ -414,7 +408,7 @@ startElement(void *userData, const char *name, const char **atts)
         {
           pd->datanum = (pd->solvable - pool->solvables) - pd->repo->start;
          repodata_extend(pd->data, pd->solvable - pool->solvables);
-          repodata_set_num(pd->data, pd->datanum, id_timestamp, pd->timestamp);
+          repodata_set_num(pd->data, pd->datanum, SOLVABLE_BUILDTIME, pd->timestamp);
        }
 #if 0
       fprintf(stderr, "package #%d\n", pd->solvable - pool->solvables);
@@ -622,13 +616,13 @@ endElement(void *userData, const char *name)
       s->arch = str2id(pool, pd->content, 1);
       break;
     case STATE_SUMMARY:
-      repodata_set_str(pd->data, pd->datanum, id_summary, pd->content);
+      repodata_set_str(pd->data, pd->datanum, SOLVABLE_SUMMARY, pd->content);
       break;
     case STATE_DESCRIPTION:
-      repodata_set_str(pd->data, pd->datanum, id_description, pd->content);
+      repodata_set_str(pd->data, pd->datanum, SOLVABLE_DESCRIPTION, pd->content);
       break;
     case STATE_CATEGORY:  
-      repodata_set_str(pd->data, pd->datanum, id_category, pd->content);
+      repodata_set_str(pd->data, pd->datanum, SOLVABLE_PATCHCATEGORY, pd->content);
       break;
     case STATE_DELTARPM:
 #ifdef TESTMM
@@ -724,11 +718,6 @@ repo_add_patchxml(Repo *repo, FILE *fp, int flags)
   pd.repo = repo;
   pd.data = repo_add_repodata(pd.repo);
 
-  id_timestamp = str2id(pool, "patch:timestamp", 1);
-  id_summary = str2id(pool, "summary", 1);
-  id_description = str2id(pool, "description", 1);
-  id_category = str2id(pool, "patch:category", 1);
-  
   pd.content = malloc(256);
   pd.acontent = 256;
   pd.lcontent = 0;
index 8b50970..3001f5e 100644 (file)
@@ -19,6 +19,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <rpm/db.h>
 
@@ -28,8 +29,6 @@
 #include "util.h"
 #include "repo_rpmdb.h"
 
-#include "tools_util.h"
-
 
 #define TAG_NAME               1000
 #define TAG_VERSION            1001
 #define TAG_ARCH               1022
 #define TAG_FILESIZES          1028
 #define TAG_FILEMODES          1030
+#define TAG_SOURCERPM          1044
 #define TAG_PROVIDENAME                1047
 #define TAG_REQUIREFLAGS       1048
 #define TAG_REQUIRENAME                1049
 #define TAG_REQUIREVERSION     1050
+#define TAG_NOSOURCE           1051
+#define TAG_NOPATCH            1052
 #define TAG_CONFLICTFLAGS      1053
 #define TAG_CONFLICTNAME       1054
 #define TAG_CONFLICTVERSION    1055
@@ -88,6 +90,23 @@ typedef struct rpmhead {
   unsigned char data[1];
 } RpmHead;
 
+static int
+headexists(RpmHead *h, int tag)
+{
+  unsigned int i;
+  unsigned char *d, taga[4];
+
+  d = h->dp - 16;
+  taga[0] = tag >> 24;
+  taga[1] = tag >> 16;
+  taga[2] = tag >> 8;
+  taga[3] = tag;
+  for (i = 0; i < h->cnt; i++, d -= 16)
+    if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
+      return 1;
+  return 0;
+}
+
 static unsigned int *
 headint32array(RpmHead *h, int tag, int *cnt)
 {
@@ -484,8 +503,11 @@ adddudata(Pool *pool, Repo *repo, Repodata *repodata, Solvable *s, RpmHead *rpmh
     {
       if (!fn[i])
        continue;
-      did = repodata_str2dir(repodata, dn[i], 1);
-      repodata_add_dirnumnum(repodata, entry, id_diskusage, did, fkb[i], fn[i]);
+      if (!*dn[i] && (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC))
+        did = repodata_str2dir(repodata, "/usr/src", 1);
+      else
+        did = repodata_str2dir(repodata, dn[i], 1);
+      repodata_add_dirnumnum(repodata, entry, SOLVABLE_DISKUSAGE, did, fkb[i], fn[i]);
     }
   sat_free(fn);
   sat_free(fkb);
@@ -581,7 +603,7 @@ addfileprovides(Pool *pool, Repo *repo, Repodata *repodata, Solvable *s, RpmHead
          repodata_extend(repodata, s - pool->solvables);
          entry = (s - pool->solvables) - repodata->start;
          did = repodata_str2dir(repodata, dn[di[i]], 1);
-         repodata_add_dirstr(repodata, entry, id_filelist, did, bn[i]);
+         repodata_add_dirstr(repodata, entry, SOLVABLE_FILELIST, did, bn[i]);
        }
     }
   if (fn)
@@ -607,7 +629,15 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *repodata, Solvable *s, RpmHead *rpmhe
       fprintf(stderr, "package has no name\n");
       exit(1);
     }
-  s->arch = str2id(pool, headstring(rpmhead, TAG_ARCH), 1);
+  if (headstring(rpmhead, TAG_SOURCERPM))
+    s->arch = str2id(pool, headstring(rpmhead, TAG_ARCH), 1);
+  else
+    {
+      if (headexists(rpmhead, TAG_NOSOURCE) || headexists(rpmhead, TAG_NOPATCH))
+        s->arch = ARCH_NOSRC;
+      else
+        s->arch = ARCH_SRC;
+    }
   if (!s->arch)
     s->arch = ARCH_NOARCH;
   evr = headtoevr(rpmhead);
@@ -639,7 +669,7 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *repodata, Solvable *s, RpmHead *rpmhe
       entry = (s - pool->solvables) - repodata->start;
       str = headstring(rpmhead, TAG_SUMMARY);
       if (str)
-        repodata_set_str(repodata, entry, id_summary, str);
+        repodata_set_str(repodata, entry, SOLVABLE_SUMMARY, str);
       str = headstring(rpmhead, TAG_DESCRIPTION);
       if (str)
        {
@@ -657,7 +687,7 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *repodata, Solvable *s, RpmHead *rpmhe
              while (l > 0 && str[l - 1] == '\n')
                str[--l] = 0;
              if (l)
-                repodata_set_str(repodata, entry, id_description, str);
+                repodata_set_str(repodata, entry, SOLVABLE_DESCRIPTION, str);
              p = aut + 19;
              aut = str;        /* copy over */
              while (*p == ' ' || *p == '\n')
@@ -677,22 +707,21 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *repodata, Solvable *s, RpmHead *rpmhe
                aut--;
              *aut = 0;
              if (*str)
-               repodata_set_str(repodata, entry, id_authors, str);
+               repodata_set_str(repodata, entry, SOLVABLE_AUTHORS, str);
              free(str);
            }
          else if (*str)
-           repodata_set_str(repodata, entry, id_description, str);
+           repodata_set_str(repodata, entry, SOLVABLE_DESCRIPTION, str);
        }
       str = headstring(rpmhead, TAG_GROUP);
       if (str)
-        repodata_set_poolstr(repodata, entry, id_group, str);
+        repodata_set_poolstr(repodata, entry, SOLVABLE_GROUP, str);
       u32 = headint32(rpmhead, TAG_BUILDTIME);
       if (u32)
-        repodata_set_num(repodata, entry, id_time, u32);
+        repodata_set_num(repodata, entry, SOLVABLE_BUILDTIME, u32);
       u32 = headint32(rpmhead, TAG_SIZE);
       if (u32)
-        repodata_set_num(repodata, entry, id_installsize, (u32 + 1023) / 1024);
-
+        repodata_set_num(repodata, entry, SOLVABLE_INSTALLSIZE, (u32 + 1023) / 1024);
     }
   return 1;
 }
@@ -729,7 +758,6 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir)
     abort();           /* FIXME: rpmdbid */
 
   repodata = repo_add_repodata(repo);
-  init_attr_ids(repo->pool);
 
   if (ref && !(ref->nsolvables && ref->rpmdbid))
     ref = 0;
@@ -1032,9 +1060,173 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir)
     repodata_internalize(repodata);
 }
 
-/* XXX: delete me! */
-void rpmdb_dummy()
+static inline unsigned int
+getu32(unsigned char *dp)
+{
+  return dp[0] << 24 | dp[1] << 16 | dp[2] << 8 | dp[3];
+}
+
+static void
+add_location(Repodata *data, Solvable *s, const char *location)
 {
-  makeevr(0, 0);
-  split(0, 0, 0);
+  Pool *pool = s->repo->pool;
+  const char *name, *n1, *n2;
+  int l;
+  Id entry;
+
+  repodata_extend(data, s - pool->solvables);
+  entry = (s - pool->solvables) - data->start;
+
+  /* skip ./ prefix */
+  if (location[0] == '.' && location[1] == '/' && location[2] != '/')
+    location += 2;
+
+  name = strrchr(location, '/');
+  if (!name)
+    name = location;
+  else
+    {
+      name++;
+      n2 = id2str(pool, s->arch);
+      l = strlen(n2);
+      if (strncmp(location, n2, l) != 0 || location + l + 1 != name)
+       {
+         /* too bad, need to store directory */
+         char *dir = strdup(location);
+         dir[name - location - 1] = 0;
+         repodata_set_str(data, entry, SOLVABLE_MEDIADIR, dir);
+         free(dir);
+       }
+      else
+        repodata_set_void(data, entry, SOLVABLE_MEDIADIR);
+    }
+  n1 = name;
+  for (n2 = id2str(pool, s->name); *n2; n1++, n2++)
+    if (*n1 != *n2)
+      break;
+  if (*n2 || *n1 != '-')
+    goto nontrivial;
+  n1++;
+  for (n2 = id2str (pool, s->evr); *n2; n1++, n2++)
+    if (*n1 != *n2)
+      break;
+  if (*n2 || *n1 != '.')
+    goto nontrivial;
+  n1++;
+  for (n2 = id2str (pool, s->arch); *n2; n1++, n2++)
+    if (*n1 != *n2)
+      break;
+  if (*n2 || strcmp (n1, ".rpm"))
+    goto nontrivial;
+  repodata_set_void(data, entry, SOLVABLE_MEDIAFILE);
+  return;
+
+nontrivial:
+  repodata_set_str(data, entry, SOLVABLE_MEDIAFILE, name);
+  return;
+}
+
+
+void
+repo_add_rpms(Repo *repo, const char **rpms, int nrpms)
+{
+  int i, sigdsize, sigcnt, l;
+  Pool *pool = repo->pool;
+  Solvable *s;
+  Repodata *repodata;
+  RpmHead *rpmhead = 0;
+  int rpmheadsize = 0;
+  FILE *fp;
+  unsigned char lead[4096];
+
+  if (nrpms <= 0)
+    return;
+  repodata = repo_add_repodata(repo);
+  for (i = 0; i < nrpms; i++)
+    {
+      if ((fp = fopen(rpms[i], "r")) == 0)
+       {
+         perror(rpms[i]);
+         continue;
+       }
+      if (fread(lead, 96 + 16, 1, fp) != 1 || getu32(lead) != 0xedabeedb)
+       {
+         fprintf(stderr, "%s: not a rpm\n", rpms[i]);
+         fclose(fp);
+         continue;
+       }
+      if (lead[78] != 0 || lead[79] != 5)
+       {
+         fprintf(stderr, "%s: not a V5 header\n", rpms[i]);
+         fclose(fp);
+         continue;
+       }
+      if (getu32(lead + 96) != 0x8eade801)
+       {
+         fprintf(stderr, "%s: bad signature header\n", rpms[i]);
+         fclose(fp);
+         continue;
+       }
+      sigcnt = getu32(lead + 96 + 8);
+      sigdsize = getu32(lead + 96 + 12);
+      if (sigcnt >= 0x4000000 || sigdsize >= 0x40000000)
+       {
+         fprintf(stderr, "%s: bad signature header\n", rpms[i]);
+         fclose(fp);
+         continue;
+       }
+      sigdsize += sigcnt * 16;
+      sigdsize = (sigdsize + 7) & ~7;
+      while (sigdsize)
+       {
+         l = sigdsize > 4096 ? 4096 : sigdsize;
+         if (fread(lead, l, 1, fp) != 1)
+           {
+             fprintf(stderr, "%s: unexpected EOF\n", rpms[i]);
+             fclose(fp);
+             continue;
+           }
+         sigdsize -= l;
+       }
+      if (fread(lead, 16, 1, fp) != 1)
+       {
+         fprintf(stderr, "%s: unexpected EOF\n", rpms[i]);
+         fclose(fp);
+         continue;
+       }
+      if (getu32(lead) != 0x8eade801)
+       {
+         fprintf(stderr, "%s: bad header\n", rpms[i]);
+         fclose(fp);
+         continue;
+       }
+      sigcnt = getu32(lead + 8);
+      sigdsize = getu32(lead + 12);
+      if (sigcnt >= 0x4000000 || sigdsize >= 0x40000000)
+       {
+         fprintf(stderr, "%s: bad header\n", rpms[i]);
+         fclose(fp);
+         continue;
+       }
+      l = sigdsize + sigcnt * 16;
+      if (l > rpmheadsize)
+       rpmhead = sat_realloc(rpmhead, sizeof(*rpmhead) + l);
+      if (fread(rpmhead->data, l, 1, fp) != 1)
+       {
+         fprintf(stderr, "%s: unexpected EOF\n", rpms[i]);
+         fclose(fp);
+         continue;
+       }
+      rpmhead->cnt = sigcnt;
+      rpmhead->dcnt = sigdsize;
+      rpmhead->dp = rpmhead->data + rpmhead->cnt * 16;
+      fclose(fp);
+      s = pool_id2solvable(pool, repo_add_solvable(repo));
+      rpm2solv(pool, repo, repodata, s, rpmhead);
+      add_location(repodata, s, rpms[i]);
+    }
+  if (rpmhead)
+    sat_free(rpmhead);
+  if (repodata)
+    repodata_internalize(repodata);
 }
index 1ce138d..42e31c0 100644 (file)
@@ -6,3 +6,4 @@
  */
 
 extern void repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir);
+extern void repo_add_rpms(Repo *repo, const char **rpms, int nrpms);
index e38a42a..ef62056 100644 (file)
@@ -448,7 +448,7 @@ set_desciption_author(Repodata *data, Id entry, char *str)
       while (l > 0 && str[l - 1] == '\n')
        str[--l] = 0; 
       if (l)
-       repodata_set_str(data, entry, id_description, str);
+       repodata_set_str(data, entry, SOLVABLE_DESCRIPTION, str);
       p = aut + 19;
       aut = str;        /* copy over */
       while (*p == ' ' || *p == '\n')
@@ -468,10 +468,10 @@ set_desciption_author(Repodata *data, Id entry, char *str)
        aut--;
       *aut = 0; 
       if (*str)
-       repodata_set_str(data, entry, id_authors, str);
+       repodata_set_str(data, entry, SOLVABLE_AUTHORS, str);
     }
   else if (*str)
-    repodata_set_str(data, entry, id_description, str);
+    repodata_set_str(data, entry, SOLVABLE_DESCRIPTION, str);
 }
 
 static void XMLCALL
@@ -612,14 +612,14 @@ startElement(void *userData, const char *name, const char **atts)
          const char *str2 = strrchr(str, '/');
          if (str2)
            {
-             char *str3 = strdup (str);
+             char *str3 = strdup(str);
              str3[str2 - str] = 0;
-             repodata_set_poolstr(pd->data, entry, id_mediadir, str3);
+             repodata_set_poolstr(pd->data, entry, SOLVABLE_MEDIADIR, str3);
              free(str3);
-              repodata_set_str(pd->data, entry, id_mediafile, str2 + 1);
+              repodata_set_str(pd->data, entry, SOLVABLE_MEDIAFILE, str2 + 1);
            }
          else
-            repodata_set_str(pd->data, entry, id_mediafile, str);
+            repodata_set_str(pd->data, entry, SOLVABLE_MEDIAFILE, str);
        }
       break;
     case STATE_CHECKSUM:
@@ -630,7 +630,7 @@ startElement(void *userData, const char *name, const char **atts)
         unsigned t;
         str = find_attr("build", atts);
         if (str && (t = atoi(str)) != 0)
-          repodata_set_num(pd->data, entry, id_time, t);
+          repodata_set_num(pd->data, entry, SOLVABLE_BUILDTIME, t);
        break;
       }
     case STATE_SIZE:
@@ -638,14 +638,14 @@ startElement(void *userData, const char *name, const char **atts)
         unsigned k;
         str = find_attr("installed", atts);
        if (str && (k = atoi(str)) != 0)
-         repodata_set_num(pd->data, entry, id_installsize, (k + 1023) / 1024);
+         repodata_set_num(pd->data, entry, SOLVABLE_INSTALLSIZE, (k + 1023) / 1024);
        /* XXX the "package" attribute gives the size of the rpm file,
           i.e. the download size.  Except on packman, there it seems to be
           something else entirely, it has a value near to the other two
           values, as if the rpm is uncompressed.  */
         str = find_attr("package", atts);
        if (str && (k = atoi(str)) != 0)
-         repodata_set_num(pd->data, entry, id_downloadsize, (k + 1023) / 1024);
+         repodata_set_num(pd->data, entry, SOLVABLE_DOWNLOADSIZE, (k + 1023) / 1024);
         break;
       }
     default:
@@ -698,10 +698,10 @@ endElement(void *userData, const char *name)
       s->vendor = str2id(pool, pd->content, 1);
       break;
     case STATE_RPM_GROUP:
-      repodata_set_poolstr(pd->data, entry, id_group, pd->content);
+      repodata_set_poolstr(pd->data, entry, SOLVABLE_GROUP, pd->content);
       break;
     case STATE_RPM_LICENSE:
-      repodata_set_poolstr(pd->data, entry, id_license, pd->content);
+      repodata_set_poolstr(pd->data, entry, SOLVABLE_LICENSE, pd->content);
       break;
     case STATE_FILE:
 #if 0
@@ -715,7 +715,7 @@ endElement(void *userData, const char *name)
        id = 1;
        p = pd->content;
       }
-      repodata_add_dirstr(pd->data, entry, id_filelist, id, p);
+      repodata_add_dirstr(pd->data, entry, SOLVABLE_FILELIST, id, p);
       break;
     // xml store capabilities
     case STATE_CAP_PROVIDES:
@@ -747,7 +747,7 @@ endElement(void *userData, const char *name)
       break;
     case STATE_SUMMARY:
       pd->lang = 0;
-      repodata_set_str(pd->data, entry, id_summary, pd->content);
+      repodata_set_str(pd->data, entry, SOLVABLE_SUMMARY, pd->content);
       break;
     case STATE_DESCRIPTION:
       pd->lang = 0;
@@ -806,7 +806,6 @@ repo_add_rpmmd(Repo *repo, FILE *fp, int flags)
   pd.common.repo = repo;
 
   pd.data = repo_add_repodata(repo);
-  init_attr_ids(pool);
 
   pd.content = sat_malloc(256);
   pd.acontent = 256;
index 5b29b71..0c5b76d 100644 (file)
@@ -22,8 +22,6 @@ struct parsedata {
   Repo *repo;
   Repodata *data;
   struct parsedata_common common;
-  char **sources;
-  int nsources;
   int last_found_source;
   char **share_with;
   int nshare;
@@ -105,9 +103,9 @@ add_location(struct parsedata *pd, char *line, Solvable *s, unsigned entry)
     {
       /* medianr filename dir
          don't optimize this one */
-      repodata_set_constant(pd->data, entry, id_medianr, atoi(sp[0]));
-      repodata_set_poolstr(pd->data, entry, id_mediadir, sp[2]);
-      repodata_set_str(pd->data, entry, id_mediafile, sp[1]);
+      repodata_set_constant(pd->data, entry, SOLVABLE_MEDIANR, atoi(sp[0]));
+      repodata_set_poolstr(pd->data, entry, SOLVABLE_MEDIADIR, sp[2]);
+      repodata_set_str(pd->data, entry, SOLVABLE_MEDIAFILE, sp[1]);
       return;
     }
   else
@@ -137,26 +135,24 @@ add_location(struct parsedata *pd, char *line, Solvable *s, unsigned entry)
       if (*n2 || strcmp (n1, ".rpm"))
         goto nontrivial;
 
-      repodata_set_constant(pd->data, entry, id_medianr, medianr);
-      repodata_set_void(pd->data, entry, id_mediafile);
+      repodata_set_constant(pd->data, entry, SOLVABLE_MEDIANR, medianr);
+      repodata_set_void(pd->data, entry, SOLVABLE_MEDIAFILE);
       return;
 
 nontrivial:
-      repodata_set_constant(pd->data, entry, id_medianr, medianr);
-      repodata_set_str(pd->data, entry, id_mediafile, sp[1]);
+      repodata_set_constant(pd->data, entry, SOLVABLE_MEDIANR, medianr);
+      repodata_set_str(pd->data, entry, SOLVABLE_MEDIAFILE, sp[1]);
       return;
     }
 }
 
-#if 0
-
 /*
  * add_source
  * 
  */
 
 static void
-add_source(struct parsedata *pd, char *line, Solvable *s, unsigned entry, int first)
+add_source(struct parsedata *pd, char *line, Solvable *s, unsigned entry)
 {
   Repo *repo = s->repo;
   Pool *pool = repo->pool;
@@ -169,68 +165,20 @@ add_source(struct parsedata *pd, char *line, Solvable *s, unsigned entry, int fi
     }
 
   Id name = str2id(pool, sp[0], 1);
-  Id evr = makeevr(pool, join(pd, sp[1], "-", sp[2]));
+  Id evr = makeevr(pool, join2(sp[1], "-", sp[2]));
   Id arch = str2id(pool, sp[3], 1);
-
-  /* Now, if the source of a package only differs in architecture
-     (src or nosrc), code only that fact.  */
-  if (s->name == name && s->evr == evr
-      && (arch == ARCH_SRC || arch == ARCH_NOSRC))
-    {
-      add_attr_void (attr, entry, arch == ARCH_SRC ? id_source : id_nosource);
-    }
-  else if (first)
-    {
-      if (entry >= pd->nsources)
-        {
-         if (pd->nsources)
-           {
-             pd->sources = realloc (pd->sources, (entry + 256) * sizeof (*pd->sources));
-             memset (pd->sources + pd->nsources, 0, (entry + 256 - pd->nsources) * sizeof (*pd->sources));
-           }
-         else
-           pd->sources = calloc (entry + 256, sizeof (*pd->sources));
-         pd->nsources = entry + 256;
-       }
-      /* Uarrr.  Unsplit.  */
-      sp[0][strlen (sp[0])] = ' ';
-      sp[1][strlen (sp[1])] = ' ';
-      sp[2][strlen (sp[2])] = ' ';
-      pd->sources[entry] = strdup (sp[0]);
-    }
+  /* XXX: could record a dep here, depends on where we want to store the data */
+  if (name == s->name)
+    repodata_set_void(pd->data, entry, SOLVABLE_SOURCENAME);
   else
-    {
-      unsigned n, nn;
-      Solvable *found = 0;
-      /* Otherwise we may find a solvable with exactly matching name, evr, arch
-         in the repository already.  In that case encode its ID.  */
-      for (n = repo->start, nn = repo->start + pd->last_found_source;
-           n < repo->end; n++, nn++)
-        {
-         if (nn >= repo->end)
-           nn = repo->start;
-         found = pool->solvables + nn;
-         if (found->repo == repo
-             && found->name == name
-             && found->evr == evr
-             && found->arch == arch)
-           {
-             pd->last_found_source = nn - repo->start;
-             break;
-           }
-        }
-      if (n != repo->end)
-        add_attr_int (attr, entry, id_sourceid, nn - repo->start);
-      else
-        {
-          add_attr_localids_id (attr, entry, id_source, str2localid (attr, sp[0], 1));
-          add_attr_localids_id (attr, entry, id_source, str2localid (attr, join (pd, sp[1], "-", sp[2]), 1));
-          add_attr_localids_id (attr, entry, id_source, str2localid (attr, sp[3], 1));
-       }
-    }
+    repodata_set_id(pd->data, entry, SOLVABLE_SOURCENAME, name);
+  if (evr == s->evr)
+    repodata_set_void(pd->data, entry, SOLVABLE_SOURCEEVR);
+  else
+    repodata_set_id(pd->data, entry, SOLVABLE_SOURCEEVR, evr);
+  repodata_set_constantid(pd->data, entry, SOLVABLE_SOURCEARCH, arch);
 }
-#endif
-
+  
 /*
  * add_dirline
  * add a line with directory information
@@ -336,7 +284,7 @@ commit_diskusage (struct parsedata *pd, unsigned entry)
   for (i = 0; i < pd->ndirs; i++)
     if (pd->dirs[i][1] || pd->dirs[i][2])
       {
-       repodata_add_dirnumnum(pd->data, entry, id_diskusage, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]);
+       repodata_add_dirnumnum(pd->data, entry, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]);
       }
   pd->ndirs = 0;
 }
@@ -401,7 +349,6 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags)
   Repodata *data = 0;
 
   data = repo_add_repodata(repo);
-  init_attr_ids(pool);
 
   memset(&pd, 0, sizeof(pd));
   line = malloc(1024);
@@ -627,12 +574,13 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags)
            s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind);
            continue;
           case CTAG('=', 'P', 'r', 'q'):                                        /* pre-requires / packages required */
-           if (pd.kind) {
-             if (flags & SUSETAGS_KINDS_SEPARATELY)
-               repodata_set_poolstr(data, last_found_pack, id_must, line + 6);
-             else
-               s->requires = adddep(pool, &pd, s->requires, line, 0, 0);           /* patterns: a required package */
-           }
+           if (pd.kind)
+             {
+               if (flags & SUSETAGS_KINDS_SEPARATELY)
+                 repodata_set_poolstr(data, last_found_pack, str2id(pool, "solvable:must", 1), line + 6);
+               else
+                 s->requires = adddep(pool, &pd, s->requires, line, 0, 0);           /* patterns: a required package */
+             }
            else
              s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */
            continue;
@@ -659,13 +607,13 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags)
            continue;
           case CTAG('=', 'P', 'r', 'c'):                                        /* packages recommended */
            if (flags & SUSETAGS_KINDS_SEPARATELY)
-             repodata_set_poolstr(data, last_found_pack, id_should, line + 6);
+             repodata_set_poolstr(data, last_found_pack, str2id(pool, "solvable:should", 1), line + 6);
            else
              s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0);
            continue;
           case CTAG('=', 'P', 's', 'g'):                                        /* packages suggested */
            if (flags & SUSETAGS_KINDS_SEPARATELY)
-             repodata_set_poolstr(data, last_found_pack, id_may, line + 6);
+             repodata_set_poolstr(data, last_found_pack, str2id(pool, "solvable:may", 1), line + 6);
            else
              s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0);
            continue;
@@ -706,55 +654,51 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags)
 
         /* From here it's the attribute tags.  */
           case CTAG('=', 'G', 'r', 'p'):
-           repodata_set_poolstr(data, last_found_pack, id_group, line + 6);
+           repodata_set_poolstr(data, last_found_pack, SOLVABLE_GROUP, line + 6);
            continue;
           case CTAG('=', 'L', 'i', 'c'):
-           repodata_set_poolstr(data, last_found_pack, id_license, line + 6);
+           repodata_set_poolstr(data, last_found_pack, SOLVABLE_LICENSE, line + 6);
            continue;
           case CTAG('=', 'L', 'o', 'c'):
            add_location(&pd, line + 6, s, last_found_pack);
            continue;
-#if 0
           case CTAG('=', 'S', 'r', 'c'):
-           add_source(&pd, line + 6, s, last_found_pack, 1);
+           add_source(&pd, line + 6, s, last_found_pack);
            continue;
-#endif
           case CTAG('=', 'S', 'i', 'z'):
            if (split (line + 6, sp, 3) == 2)
              {
-               repodata_set_num(data, last_found_pack, id_downloadsize, (atoi(sp[0]) + 1023) / 1024);
-               repodata_set_num(data, last_found_pack, id_installsize, (atoi(sp[1]) + 1023) / 1024);
+               repodata_set_num(data, last_found_pack, SOLVABLE_DOWNLOADSIZE, (atoi(sp[0]) + 1023) / 1024);
+               repodata_set_num(data, last_found_pack, SOLVABLE_INSTALLSIZE, (atoi(sp[1]) + 1023) / 1024);
              }
            continue;
           case CTAG('=', 'T', 'i', 'm'):
            {
              unsigned int t = atoi (line + 6);
              if (t)
-               {
-                 repodata_set_num(data, last_found_pack, id_time, t);
-               }
+               repodata_set_num(data, last_found_pack, SOLVABLE_BUILDTIME, t);
            }
            continue;
           case CTAG('=', 'K', 'w', 'd'):
-           repodata_set_poolstr(data, last_found_pack, id_keywords, line + 6);
+           repodata_set_poolstr(data, last_found_pack, SOLVABLE_KEYWORDS, line + 6);
            continue;
           case CTAG('=', 'A', 'u', 't'):
-           repodata_set_str(data, last_found_pack, id_authors, line + 6);
+           repodata_set_str(data, last_found_pack, SOLVABLE_AUTHORS, line + 6);
            continue;
           case CTAG('=', 'S', 'u', 'm'):
-           repodata_set_str(data, last_found_pack, id_summary, line + 6);
+           repodata_set_str(data, last_found_pack, SOLVABLE_SUMMARY, line + 6);
            continue;
           case CTAG('=', 'D', 'e', 's'):
-           repodata_set_str(data, last_found_pack, id_description, line + 6);
+           repodata_set_str(data, last_found_pack, SOLVABLE_DESCRIPTION, line + 6);
            continue;
           case CTAG('=', 'E', 'u', 'l'):
-           repodata_set_str(data, last_found_pack, id_eula, line + 6);
+           repodata_set_str(data, last_found_pack, SOLVABLE_EULA, line + 6);
            continue;
           case CTAG('=', 'I', 'n', 's'):
-           repodata_set_str(data, last_found_pack, id_messageins, line + 6);
+           repodata_set_str(data, last_found_pack, SOLVABLE_MESSAGEINS, line + 6);
            continue;
           case CTAG('=', 'D', 'e', 'l'):
-           repodata_set_str(data, last_found_pack, id_messagedel, line + 6);
+           repodata_set_str(data, last_found_pack, SOLVABLE_MESSAGEDEL, line + 6);
            continue;
           case CTAG('=', 'V', 'i', 's'):
            {
@@ -762,7 +706,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags)
              unsigned k;
              k = atoi (line + 6);
              if (k || !strcasecmp (line + 6, "true"))
-               repodata_set_constant(data, last_found_pack, id_isvisible, 1);
+               repodata_set_constant(data, last_found_pack, SOLVABLE_ISVISIBLE, 1);
            }
            continue;
           case CTAG('=', 'S', 'h', 'r'):
@@ -799,20 +743,6 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags)
   if (s && pd.ndirs)
     commit_diskusage(&pd, last_found_pack);
     
-#if 0
-  if (pd.sources)
-    {
-      int i, last_found;
-      for (i = 0; i < pd.nsources; i++)
-        if (pd.sources[i])
-         {
-           add_source(&pd, pd.sources[i], pool->solvables + repo->start + i, i, 0);
-           free (pd.sources[i]);
-         }
-      free (pd.sources);
-    }
-#endif
-
   /* Shared attributes
    *  (e.g. multiple binaries built from same source)
    */
index 978d573..6d958da 100644 (file)
@@ -165,15 +165,13 @@ write_u8(FILE *fp, unsigned int x)
 static void
 write_blob(FILE *fp, void *data, int len)
 {
-  if (fwrite(data, len, 1, fp) != 1)
+  if (len && fwrite(data, len, 1, fp) != 1)
     {
       perror("write error blob");
       exit(1);
     }
 }
 
-static unsigned id_bytes;
-
 /*
  * Id
  */
@@ -198,7 +196,17 @@ write_id(FILE *fp, Id x)
     }
 }
 
-#if 1
+static inline void
+write_id_eof(FILE *fp, Id x, int eof)
+{
+  if (x >= 64)
+    x = (x & 63) | ((x & ~63) << 1);
+  write_id(fp, x | (eof ? 0 : 64));
+}
+
+
+
+#if 0
 static void
 write_str(FILE *fp, const char *str)
 {
@@ -249,6 +257,7 @@ cmp_ids (const void *pa, const void *pb)
   return a - b;
 }
 
+#if 0
 static void
 write_idarray_sort(FILE *fp, Pool *pool, NeedId *needid, Id *ids, Id marker)
 {
@@ -337,17 +346,7 @@ write_idarray_sort(FILE *fp, Pool *pool, NeedId *needid, Id *ids, Id marker)
   if (sids != lids)
     sat_free(sids);
 }
-
-static inline void
-write_id_value(FILE *fp, Id id, Id value, int eof)
-{
-  if (id >= 64)
-    id = (id & 63) | ((id & ~63) << 1);
-  write_id(fp, id | 64);
-  if (value >= 64)
-    value = (value & 63) | ((value & ~63) << 1);
-  write_id(fp, value | (eof ? 0 : 64));
-}
+#endif
 
 
 struct extdata {
@@ -382,7 +381,6 @@ struct cbdata {
   Id schematacache[256];
 
   Id *solvschemata;
-  Id *incorelen;
 
   struct extdata *extdata;
 
@@ -394,9 +392,9 @@ struct cbdata {
 #define NEEDED_BLOCK 1023
 #define SCHEMATA_BLOCK 31
 #define SCHEMATADATA_BLOCK 255
-#define EXTDATA_BLOCK 1023
+#define EXTDATA_BLOCK 4095
 
-static void
+static inline void
 data_addid(struct extdata *xd, Id x)
 {
   unsigned char *dp;
@@ -417,7 +415,7 @@ data_addid(struct extdata *xd, Id x)
   xd->len = dp - xd->buf;
 }
 
-static void
+static inline void
 data_addideof(struct extdata *xd, Id x, int eof)
 {
   if (x >= 64)
@@ -426,6 +424,95 @@ data_addideof(struct extdata *xd, Id x, int eof)
 }
 
 static void
+data_addidarray_sort(struct extdata *xd, Pool *pool, NeedId *needid, Id *ids, Id marker)
+{
+  int len, i;
+  Id lids[64], *sids;
+
+  if (!ids)
+    return;
+  if (!*ids)
+    {
+      data_addid(xd, 0);
+      return;
+    }
+  for (len = 0; len < 64 && ids[len]; len++)
+    {
+      Id id = ids[len];
+      if (needid)
+        id = needid[ISRELDEP(id) ? RELOFF(id) : id].need;
+      lids[len] = id;
+    }
+  if (ids[len])
+    {
+      for (i = len + 1; ids[i]; i++)
+       ;
+      sids = sat_malloc2(i, sizeof(Id));
+      memcpy(sids, lids, 64 * sizeof(Id));
+      for (; ids[len]; len++)
+       {
+         Id id = ids[len];
+         if (needid)
+            id = needid[ISRELDEP(id) ? RELOFF(id) : id].need;
+         sids[len] = id;
+       }
+    }
+  else
+    sids = lids;
+
+  /* That bloody solvable:prereqmarker needs to stay in position :-(  */
+  if (needid)
+    marker = needid[marker].need;
+  for (i = 0; i < len; i++)
+    if (sids[i] == marker)
+      break;
+  if (i > 1)
+    qsort(sids, i, sizeof (Id), cmp_ids);
+  if ((len - i) > 2)
+    qsort(sids + i + 1, len - i - 1, sizeof(Id), cmp_ids);
+
+  Id id, old = 0;
+
+  /* The differencing above produces many runs of ones and twos.  I tried
+     fairly elaborate schemes to RLE those, but they give only very mediocre
+     improvements in compression, as coding the escapes costs quite some
+     space.  Even if they are coded only as bits in IDs.  The best improvement
+     was about 2.7% for the whole .solv file.  It's probably better to
+     invest some complexity into sharing idarrays, than RLEing.  */
+  for (i = 0; i < len - 1; i++)
+    {
+      id = sids[i];
+    /* Ugly PREREQ handling.  A "difference" of 0 is the prereq marker,
+       hence all real differences are offsetted by 1.  Otherwise we would
+       have to handle negative differences, which would cost code space for
+       the encoding of the sign.  We loose the exact mapping of prereq here,
+       but we know the result, so we can recover from that in the reader.  */
+      if (id == marker)
+       id = old = 0;
+      else
+       {
+          id = id - old + 1;
+         old = sids[i];
+       }
+      /* XXX If difference is zero we have multiple equal elements,
+        we might want to skip writing them out.  */
+      if (id >= 64)
+       id = (id & 63) | ((id & ~63) << 1);
+      data_addid(xd, id | 64);
+    }
+  id = sids[i];
+  if (id == marker)
+    id = 0;
+  else
+    id = id - old + 1;
+  if (id >= 64)
+    id = (id & 63) | ((id & ~63) << 1);
+  data_addid(xd, id);
+  if (sids != lids)
+    sat_free(sids);
+}
+
+static inline void
 data_addblob(struct extdata *xd, unsigned char *blob, int len)
 {
   xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK);
@@ -433,6 +520,17 @@ data_addblob(struct extdata *xd, unsigned char *blob, int len)
   xd->len += len;
 }
 
+static inline void
+data_addu32(struct extdata *xd, unsigned int num)
+{
+  unsigned char d[4];
+  d[0] = num >> 24;
+  d[1] = num >> 16;
+  d[2] = num >> 8;
+  d[3] = num;
+  data_addblob(xd, d, 4);
+}
+
 static Id
 addschema(struct cbdata *cbdata, Id *schema)
 {
@@ -539,20 +637,21 @@ repo_write_cb_needed(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, K
   rm = cbdata->keymap[cbdata->keymapstart[data - data->repo->repodata] + (key - data->keys)];
   if (!rm)
     return SEARCH_NEXT_KEY;    /* we do not want this one */
+  /* record key in schema */
   if (cbdata->sp == cbdata->schema || cbdata->sp[-1] != rm)
     *cbdata->sp++ = rm;
   switch(key->type)
     {
-      case TYPE_ID:
-      case TYPE_IDARRAY:
+      case REPOKEY_TYPE_ID:
+      case REPOKEY_TYPE_IDARRAY:
        id = kv->id;
        if (!ISRELDEP(id) && cbdata->ownspool && id > 1)
          id = putinownpool(cbdata, data->localpool ? &data->spool : &repo->pool->ss, id);
        incneedid(repo->pool, id, cbdata->needid);
        break;
-      case TYPE_DIR:
-      case TYPE_DIRNUMNUMARRAY:
-      case TYPE_DIRSTRARRAY:
+      case REPOKEY_TYPE_DIR:
+      case REPOKEY_TYPE_DIRNUMNUMARRAY:
+      case REPOKEY_TYPE_DIRSTRARRAY:
        id = kv->id;
        if (cbdata->owndirpool)
          putinowndirpool(cbdata, data, &data->dirpool, id);
@@ -566,7 +665,7 @@ repo_write_cb_needed(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, K
 }
 
 static int
-repo_write_cb_sizes(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv)
+repo_write_cb_adddata(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv)
 {
   struct cbdata *cbdata = vcbdata;
   int rm;
@@ -589,27 +688,28 @@ repo_write_cb_sizes(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, Ke
     xd = cbdata->extdata + 0;          /* incore buffer */
   switch(key->type)
     {
-      case TYPE_VOID:
-      case TYPE_CONSTANT:
+      case REPOKEY_TYPE_VOID:
+      case REPOKEY_TYPE_CONSTANT:
+      case REPOKEY_TYPE_CONSTANTID:
        break;
-      case TYPE_ID:
+      case REPOKEY_TYPE_ID:
        id = kv->id;
        if (!ISRELDEP(id) && cbdata->ownspool && id > 1)
          id = putinownpool(cbdata, data->localpool ? &data->spool : &data->repo->pool->ss, id);
        id = cbdata->needid[id].need;
        data_addid(xd, id);
        break;
-      case TYPE_IDARRAY:
+      case REPOKEY_TYPE_IDARRAY:
        id = kv->id;
        if (cbdata->ownspool && id > 1)
          id = putinownpool(cbdata, data->localpool ? &data->spool : &data->repo->pool->ss, id);
        id = cbdata->needid[id].need;
        data_addideof(xd, id, kv->eof);
        break;
-      case TYPE_STR:
+      case REPOKEY_TYPE_STR:
        data_addblob(xd, (unsigned char *)kv->str, strlen(kv->str) + 1);
        break;
-      case TYPE_U32:
+      case REPOKEY_TYPE_U32:
        u32 = kv->num;
        v[0] = u32 >> 24;
        v[1] = u32 >> 16;
@@ -617,17 +717,17 @@ repo_write_cb_sizes(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, Ke
        v[3] = u32;
        data_addblob(xd, v, 4);
        break;
-      case TYPE_NUM:
+      case REPOKEY_TYPE_NUM:
        data_addid(xd, kv->num);
        break;
-      case TYPE_DIR:
+      case REPOKEY_TYPE_DIR:
        id = kv->id;
        if (cbdata->owndirpool)
          id = putinowndirpool(cbdata, data, &data->dirpool, id);
        id = cbdata->dirused[id];
        data_addid(xd, id);
        break;
-      case TYPE_DIRNUMNUMARRAY:
+      case REPOKEY_TYPE_DIRNUMNUMARRAY:
        id = kv->id;
        if (cbdata->owndirpool)
          id = putinowndirpool(cbdata, data, &data->dirpool, id);
@@ -636,7 +736,7 @@ repo_write_cb_sizes(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, Ke
        data_addid(xd, kv->num);
        data_addideof(xd, kv->num2, kv->eof);
        break;
-      case TYPE_DIRSTRARRAY:
+      case REPOKEY_TYPE_DIRSTRARRAY:
        id = kv->id;
        if (cbdata->owndirpool)
          id = putinowndirpool(cbdata, data, &data->dirpool, id);
@@ -674,7 +774,6 @@ traverse_dirs(Dirpool *dp, Id *dirmap, Id n, Id dir, Id *used)
        continue;
       if (sib == 1 && parent == 1)
        continue;       /* already did that one above */
-assert (sib < dp->ndirs);
       dirmap[n++] = sib;
     }
   lastn = n;
@@ -737,15 +836,14 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
   Id *dirmap;
   int ndirmap;
   Id *keyused;
-  int ext0len;
   unsigned char *repodataused;
+  int anyrepodataused;
   
   struct cbdata cbdata;
   int needrels;
   Repokey *key;
   int poolusage, dirpoolusage, idused, dirused;
   int reloff;
-  unsigned char *incoredata;
 
   Repodata *data;
   Stringpool ownspool, *spool;
@@ -755,6 +853,12 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
   Id repodataschema = 0;
   Id repodataschema_internal = 0;
 
+  struct extdata *xd;
+
+  int entrysize;
+  Id maxentrysize;
+  Id type_constantid = 0;
+
   /* If we're given a fileinfo structure, but have no subfiles, then we're
      writing a subfile and our callers wants info about it.  */
   if (fileinfo && nsubfiles == 0)
@@ -787,11 +891,11 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
       key = cbdata.mykeys + i;
       key->name = i;
       if (i < SOLVABLE_PROVIDES)
-        key->type = TYPE_ID;
+        key->type = REPOKEY_TYPE_ID;
       else if (i < RPM_RPMDBID)
-        key->type = TYPE_REL_IDARRAY;
+        key->type = REPOKEY_TYPE_REL_IDARRAY;
       else
-        key->type = TYPE_U32;
+        key->type = REPOKEY_TYPE_U32;
       key->size = 0;
       key->storage = KEY_STORAGE_SOLVABLE;
       if (keyfilter)
@@ -802,7 +906,7 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
          key->storage = KEY_STORAGE_SOLVABLE;
        }
       poolusage = 1;
-      if (key->type == TYPE_IDARRAY || key->type == TYPE_REL_IDARRAY)
+      if (key->type == REPOKEY_TYPE_IDARRAY || key->type == REPOKEY_TYPE_REL_IDARRAY)
        needrels = 1;
       cbdata.keymap[i] = i;
     }
@@ -813,21 +917,21 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
     {
       key = cbdata.mykeys + cbdata.nmykeys;
       key->name = REPODATA_EXTERNAL;
-      key->type = TYPE_VOID;
+      key->type = REPOKEY_TYPE_VOID;
       key->size = 0;
       key->storage = KEY_STORAGE_SOLVABLE;
       cbdata.keymap[key->name] = key - cbdata.mykeys;
       key++;
 
       key->name = REPODATA_KEYS;
-      key->type = TYPE_IDVALUEARRAY;
+      key->type = REPOKEY_TYPE_IDARRAY;
       key->size = 0;
       key->storage = KEY_STORAGE_SOLVABLE;
       cbdata.keymap[key->name] = key - cbdata.mykeys;
       key++;
 
       key->name = REPODATA_LOCATION;
-      key->type = TYPE_STR;
+      key->type = REPOKEY_TYPE_STR;
       key->size = 0;
       key->storage = KEY_STORAGE_SOLVABLE;
       cbdata.keymap[key->name] = key - cbdata.mykeys;
@@ -856,22 +960,20 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
            {
              if (key->name == cbdata.mykeys[k].name && key->type == cbdata.mykeys[k].type)
                {
-                 if (key->type == TYPE_CONSTANT && key->size != cbdata.mykeys[k].size)
+                 if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != cbdata.mykeys[k].size)
                    continue;
                  break;
                }
            }
          if (k < cbdata.nmykeys)
-           {
-             repodataused[i] = 1;
-             cbdata.keymap[n] = k;
-           }
+           cbdata.keymap[n] = k;
           else
            {
+             /* found a new key! */
              cbdata.mykeys[cbdata.nmykeys] = *key;
              key = cbdata.mykeys + cbdata.nmykeys;
              key->storage = KEY_STORAGE_INCORE;
-             if (key->type != TYPE_CONSTANT)
+             if (key->type != REPOKEY_TYPE_CONSTANT && key->type != REPOKEY_TYPE_CONSTANTID)
                key->size = 0;
              if (keyfilter)
                {
@@ -907,9 +1009,10 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
            }
 
          repodataused[i] = 1;
-         if (key->type != TYPE_STR && key->type != TYPE_U32)
+         anyrepodataused = 1;
+         if (key->type != REPOKEY_TYPE_STR && key->type != REPOKEY_TYPE_U32)
            idused = 1;
-         if (key->type == TYPE_DIR || key->type == TYPE_DIRNUMNUMARRAY || key->type == TYPE_DIRSTRARRAY)
+         if (key->type == REPOKEY_TYPE_DIR || key->type == REPOKEY_TYPE_DIRNUMNUMARRAY || key->type == REPOKEY_TYPE_DIRSTRARRAY)
            dirused = 1;
        }
       if (idused)
@@ -966,18 +1069,6 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
       poolusage = 1;
       spool = &repo->pool->ss;
     }
-
-  if (poolusage > 1)
-    {
-      /* convert global keys to new pool names */
-      for (i = 0; i < cbdata.nmykeys; i++)
-       {
-         if (cbdata.mykeys[i].storage == KEY_STORAGE_DROPPED)
-           continue;
-         cbdata.mykeys[i].name = stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[i].name), 1);
-       }
-    }
-
   if (dirpoolusage == 3)
     {
       dirpool = &owndirpool;
@@ -994,7 +1085,7 @@ fprintf(stderr, "poolusage: %d\n", poolusage);
 fprintf(stderr, "dirpoolusage: %d\n", dirpoolusage);
 fprintf(stderr, "nmykeys: %d\n", cbdata.nmykeys);
 for (i = 1; i < cbdata.nmykeys; i++)
-  fprintf(stderr, "  %2d: %d %d %d\n", i, cbdata.mykeys[i].name, cbdata.mykeys[i].type, cbdata.mykeys[i].storage);
+  fprintf(stderr, "  %2d: %d %d %d %d\n", i, cbdata.mykeys[i].name, cbdata.mykeys[i].type, cbdata.mykeys[i].size, cbdata.mykeys[i].storage);
 #endif
 
 /********************************************************************/
@@ -1097,14 +1188,17 @@ for (i = 1; i < cbdata.nmykeys; i++)
        }
       cbdata.sp = sp;
 
-      for (j = 0, data = repo->repodata; j < repo->nrepodata; j++, data++)
+      if (anyrepodataused)
        {
-         if (!repodataused[j])
-           continue;
-         if (i < data->start || i >= data->end)
-           continue;
-         repodata_search(data, i - data->start, 0, repo_write_cb_needed, &cbdata);
-         needid = cbdata.needid;
+         for (j = 0, data = repo->repodata; j < repo->nrepodata; j++, data++)
+           {
+             if (!repodataused[j])
+               continue;
+             if (i < data->start || i >= data->end)
+               continue;
+             repodata_search(data, i - data->start, 0, repo_write_cb_needed, &cbdata);
+             needid = cbdata.needid;
+           }
        }
       *cbdata.sp = 0;
       cbdata.solvschemata[n] = addschema(&cbdata, cbdata.schema);
@@ -1139,7 +1233,10 @@ for (i = 1; i < cbdata.nmykeys; i++)
       if (2 * fileinfo[i].nkeys > cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size)
        cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size = 2 * fileinfo[i].nkeys;
       for (j = 1; j < fileinfo[i].nkeys; j++)
-       needid[fileinfo[i].keys[j].name].need++;
+       {
+         needid[fileinfo[i].keys[j].type].need++;
+         needid[fileinfo[i].keys[j].name].need++;
+       }
 #if 0
       fprintf (stderr, " %d nkeys: %d:", i, fileinfo[i].nkeys);
       for (j = 1; j < fileinfo[i].nkeys; j++)
@@ -1156,7 +1253,7 @@ for (i = 1; i < cbdata.nmykeys; i++)
 
 /********************************************************************/
 
-  /* remove unused keys, also increment needid for key names */
+  /* remove unused keys, convert ids to local ids and increment their needid */
   keyused = sat_calloc(cbdata.nmykeys, sizeof(Id));
   for (i = 0; i < cbdata.myschemadatalen; i++)
     keyused[cbdata.myschemadata[i]] = 1;
@@ -1168,7 +1265,21 @@ for (i = 1; i < cbdata.nmykeys; i++)
       keyused[i] = n;
       if (i != n)
        cbdata.mykeys[n] = cbdata.mykeys[i];
+      if (cbdata.mykeys[n].type == REPOKEY_TYPE_CONSTANTID)
+       {
+         if (!type_constantid)
+           type_constantid = poolusage > 1 ? stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[n].type), 1) : REPOKEY_TYPE_CONSTANTID;
+         if (poolusage > 1)
+           cbdata.mykeys[n].size = stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[n].size), 1);
+         needid[cbdata.mykeys[n].size].need++;
+       }
+      if (poolusage > 1)
+       {
+         cbdata.mykeys[n].name = stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[n].name), 1);
+         cbdata.mykeys[n].type = stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[n].type), 1);
+       }
       needid[cbdata.mykeys[n].name].need++;
+      needid[cbdata.mykeys[n].type].need++;
       n++;
     }
   cbdata.nmykeys = n;
@@ -1282,32 +1393,58 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1);
 
 /********************************************************************/
   cbdata.extdata = sat_calloc(cbdata.nmykeys, sizeof(struct extdata));
-  cbdata.incorelen = sat_calloc(repo->nsolvables, sizeof(Id));
-  /* calculate incore/vertical data and sizes */
-  ext0len = 0;
-
-  for (i = 1; i < cbdata.nmykeys; i++)
-    if (cbdata.mykeys[i].storage != KEY_STORAGE_SOLVABLE)
-      break;
-  if (i < cbdata.nmykeys)
+  
+  xd = cbdata.extdata;
+  maxentrysize = 0;
+  for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++)
     {
-      /* we need incore/vertical data */
-      for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++)
+      if (s->repo != repo)
+       continue;
+      entrysize = xd->len;
+      data_addid(xd, cbdata.solvschemata[n]);
+      if (cbdata.keymap[SOLVABLE_NAME])
+        data_addid(xd, needid[s->name].need);
+      if (cbdata.keymap[SOLVABLE_ARCH])
+        data_addid(xd, needid[s->arch].need);
+      if (cbdata.keymap[SOLVABLE_EVR])
+        data_addid(xd, needid[s->evr].need);
+      if (s->vendor && cbdata.keymap[SOLVABLE_VENDOR])
+        data_addid(xd, needid[s->vendor].need);
+      if (s->provides && cbdata.keymap[SOLVABLE_PROVIDES])
+        data_addidarray_sort(xd, pool, needid, idarraydata + s->provides, SOLVABLE_FILEMARKER);
+      if (s->obsoletes && cbdata.keymap[SOLVABLE_OBSOLETES])
+        data_addidarray_sort(xd, pool, needid, idarraydata + s->obsoletes, 0);
+      if (s->conflicts && cbdata.keymap[SOLVABLE_CONFLICTS])
+        data_addidarray_sort(xd, pool, needid, idarraydata + s->conflicts, 0);
+      if (s->requires && cbdata.keymap[SOLVABLE_REQUIRES])
+        data_addidarray_sort(xd, pool, needid, idarraydata + s->requires, SOLVABLE_PREREQMARKER);
+      if (s->recommends && cbdata.keymap[SOLVABLE_RECOMMENDS])
+        data_addidarray_sort(xd, pool, needid, idarraydata + s->recommends, 0);
+      if (s->suggests && cbdata.keymap[SOLVABLE_SUGGESTS])
+        data_addidarray_sort(xd, pool, needid, idarraydata + s->suggests, 0);
+      if (s->supplements && cbdata.keymap[SOLVABLE_SUPPLEMENTS])
+        data_addidarray_sort(xd, pool, needid, idarraydata + s->supplements, 0);
+      if (s->enhances && cbdata.keymap[SOLVABLE_ENHANCES])
+        data_addidarray_sort(xd, pool, needid, idarraydata + s->enhances, 0);
+      if (s->freshens && cbdata.keymap[SOLVABLE_FRESHENS])
+        data_addidarray_sort(xd, pool, needid, idarraydata + s->freshens, 0);
+      if (repo->rpmdbid && cbdata.keymap[RPM_RPMDBID])
+        data_addu32(xd, repo->rpmdbid[i - repo->start]);
+      if (anyrepodataused)
        {
-         if (s->repo != repo)
-           continue;
          for (j = 0, data = repo->repodata; j < repo->nrepodata; j++, data++)
            {
              if (!repodataused[j])
                continue;
              if (i < data->start || i >= data->end)
                continue;
-             repodata_search(data, i - data->start, 0, repo_write_cb_sizes, &cbdata);
+             repodata_search(data, i - data->start, 0, repo_write_cb_adddata, &cbdata);
            }
-         cbdata.incorelen[n] = cbdata.extdata[0].len - ext0len;
-         ext0len = cbdata.extdata[0].len;
-         n++;
        }
+      entrysize = xd->len - entrysize;
+      if (entrysize > maxentrysize)
+        maxentrysize = entrysize;
+      n++;
     }
 
 /********************************************************************/
@@ -1316,7 +1453,7 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1);
 
   /* write file header */
   write_u32(fp, 'S' << 24 | 'O' << 16 | 'L' << 8 | 'V');
-  write_u32(fp, SOLV_VERSION_5);
+  write_u32(fp, SOLV_VERSION_6);
 
   /* write counts */
   write_u32(fp, nstrings);
@@ -1328,9 +1465,6 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1);
   write_u32(fp, nsubfiles);    /* info blocks.  */
   solv_flags = 0;
   solv_flags |= SOLV_FLAG_PREFIX_POOL;
-#if 0
-  solv_flags |= SOLV_FLAG_VERTICAL;
-#endif
   write_u32(fp, solv_flags);
 
   /* Build the prefix-encoding of the string pool.  We need to know
@@ -1406,9 +1540,14 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1);
   for (i = 1; i < cbdata.nmykeys; i++)
     {
       write_id(fp, needid[cbdata.mykeys[i].name].need);
-      write_id(fp, cbdata.mykeys[i].type);
+      write_id(fp, needid[cbdata.mykeys[i].type].need);
       if (cbdata.mykeys[i].storage != KEY_STORAGE_VERTICAL_OFFSET)
-        write_id(fp, cbdata.mykeys[i].size);
+       {
+         if (cbdata.mykeys[i].type == type_constantid)
+            write_id(fp, needid[cbdata.mykeys[i].size].need);
+         else
+            write_id(fp, cbdata.mykeys[i].size);
+       }
       else
         write_id(fp, cbdata.extdata[i].len);
       write_id(fp, cbdata.mykeys[i].storage);
@@ -1429,90 +1568,51 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1);
   /*
    * write info block
    */
-  for (i = 0; i < nsubfiles; i++)
+  if (nsubfiles)
     {
-      int j;
+      struct extdata xd;
+      xd.buf = 0;
+      xd.len = 0;
+      int max = 0;
+      int cur;
 
-      if (fileinfo[i].location)
-        write_id(fp, repodataschema);
-      else
-        write_id(fp, repodataschema_internal);
-      /* keys + location, write idarray */
-      for (j = 1; j < fileinfo[i].nkeys; j++)
-        {
-                  
-         Id id = needid[fileinfo[i].keys[j].name].need;
-#if 0
-         fprintf (stderr, "writing %d(%s) %d\n", id,
-                  id2str(pool, needid[id].map),
-                  fileinfo[i].keys[j].type);
-#endif
-         write_id_value(fp, id, fileinfo[i].keys[j].type, j == fileinfo[i].nkeys - 1);
-        }
-      if (fileinfo[i].location)
-        write_str(fp, fileinfo[i].location);
-    }
+      for (i = 0; i < nsubfiles; i++)
+       {
+         int j;
 
+         cur = xd.len;
+         if (fileinfo[i].location)
+           data_addid(&xd, repodataschema);
+         else
+           data_addid(&xd, repodataschema_internal);
+         /* key,type array + location, write idarray */
+         for (j = 1; j < fileinfo[i].nkeys; j++)
+           {
+             data_addideof(&xd, needid[fileinfo[i].keys[j].name].need, 0);
+             data_addideof(&xd, needid[fileinfo[i].keys[j].type].need, j == fileinfo[i].nkeys - 1);
+           }
+         if (fileinfo[i].location)
+           data_addblob(&xd, (unsigned char *)fileinfo[i].location, strlen(fileinfo[i].location) + 1);
+         cur = xd.len - cur;
+         if (cur > max)
+           max = cur;
+       }
+      write_id(fp, max);
+      write_id(fp, xd.len);
+      write_blob(fp, xd.buf, xd.len);
+    }
 
 /********************************************************************/
 
 
   /*
-   * write Solvables
+   * write Solvable data
    */
-  incoredata = cbdata.extdata[0].buf;
-  for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++)
+  if (repo->nsolvables)
     {
-      if (s->repo != repo)
-       continue;
-      id_bytes = 0;
-      /* keep in sync with schema generation! */
-      write_id(fp, cbdata.solvschemata[n]);
-#if 0
-{
-  Id *sp;
-  fprintf(stderr, "write solvable %d (%s): \n", n, id2str(pool, s->name));
-  sp = cbdata.myschemadata + cbdata.myschemata[cbdata.solvschemata[n]];
-  for (; *sp; sp++)
-    fprintf(stderr, " (%d,%d)", cbdata.mykeys[*sp].name, cbdata.mykeys[*sp].type);
-  fprintf(stderr, "\n");
-}
-#endif
-      if (cbdata.keymap[SOLVABLE_NAME])
-        write_id(fp, needid[s->name].need);
-      if (cbdata.keymap[SOLVABLE_ARCH])
-        write_id(fp, needid[s->arch].need);
-      if (cbdata.keymap[SOLVABLE_EVR])
-        write_id(fp, needid[s->evr].need);
-      if (s->vendor && cbdata.keymap[SOLVABLE_VENDOR])
-        write_id(fp, needid[s->vendor].need);
-      if (s->provides && cbdata.keymap[SOLVABLE_PROVIDES])
-        write_idarray_sort(fp, pool, needid, idarraydata + s->provides, SOLVABLE_FILEMARKER);
-      if (s->obsoletes && cbdata.keymap[SOLVABLE_OBSOLETES])
-        write_idarray_sort(fp, pool, needid, idarraydata + s->obsoletes, 0);
-      if (s->conflicts && cbdata.keymap[SOLVABLE_CONFLICTS])
-        write_idarray_sort(fp, pool, needid, idarraydata + s->conflicts, 0);
-      if (s->requires && cbdata.keymap[SOLVABLE_REQUIRES])
-        write_idarray_sort(fp, pool, needid, idarraydata + s->requires, SOLVABLE_PREREQMARKER);
-      if (s->recommends && cbdata.keymap[SOLVABLE_RECOMMENDS])
-        write_idarray_sort(fp, pool, needid, idarraydata + s->recommends, 0);
-      if (s->suggests && cbdata.keymap[SOLVABLE_SUGGESTS])
-        write_idarray_sort(fp, pool, needid, idarraydata + s->suggests, 0);
-      if (s->supplements && cbdata.keymap[SOLVABLE_SUPPLEMENTS])
-        write_idarray_sort(fp, pool, needid, idarraydata + s->supplements, 0);
-      if (s->enhances && cbdata.keymap[SOLVABLE_ENHANCES])
-        write_idarray_sort(fp, pool, needid, idarraydata + s->enhances, 0);
-      if (s->freshens && cbdata.keymap[SOLVABLE_FRESHENS])
-        write_idarray_sort(fp, pool, needid, idarraydata + s->freshens, 0);
-      if (repo->rpmdbid && cbdata.keymap[RPM_RPMDBID])
-        write_u32(fp, repo->rpmdbid[i - repo->start]),id_bytes+=4;
-      if (cbdata.incorelen[n])
-       {
-         write_blob(fp, incoredata, cbdata.incorelen[n]);
-         incoredata += cbdata.incorelen[n];
-         id_bytes += cbdata.incorelen[n];
-       }
-      n++;
+      write_id(fp, maxentrysize);
+      write_id(fp, cbdata.extdata[0].len);
+      write_blob(fp, cbdata.extdata[0].buf, cbdata.extdata[0].len);
     }
   sat_free(cbdata.extdata[0].buf);
 
@@ -1594,6 +1694,5 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1);
   sat_free(cbdata.keymap);
   sat_free(cbdata.keymapstart);
   sat_free(cbdata.dirused);
-  sat_free(cbdata.incorelen);
   sat_free(repodataused);
 }
index a7f30e2..34878ba 100644 (file)
@@ -24,7 +24,7 @@ struct parsedata_common {
   Repo *repo;
 };
 
-static Id
+static inline Id
 makeevr(Pool *pool, char *s)
 {
   if (!strncmp(s, "0:", 2) && s[2])
@@ -134,88 +134,12 @@ join2(const char *s1, const char *s2, const char *s3)
 //   return pd->tmp;
 // }
 
-/* key Ids */
-
-/* packages */
-static Id id_authors;
-static Id id_description;
-static Id id_diskusage;
-static Id id_eula;
-static Id id_group;
-static Id id_installsize;
-static Id id_keywords;
-static Id id_license;
-static Id id_messagedel;
-static Id id_messageins;
-static Id id_mediadir;
-static Id id_mediafile;
-static Id id_medianr;
-static Id id_nosource;
-static Id id_source;
-static Id id_sourceid;
-static Id id_time;
-static Id id_filelist;
-
-/* resobject */
-static Id id_summary;
-static Id id_description;
-// static Id id_insnotify;
-// static Id id_delnotify;
-static Id id_size;
-static Id id_downloadsize;
-static Id id_installtime;
-static Id id_installonly;
-
-static Id id_isvisible;
-
-/* experimental */
-static Id id_must;
-static Id id_should;
-static Id id_may;
-
-static void init_attr_ids(Pool *pool)
-{
-  id_size = str2id(pool, "size", 1);;
-  id_downloadsize = str2id(pool, "downloadsize", 1);;
-  id_installtime = str2id(pool, "installtime", 1);;
-  id_installonly = str2id(pool, "installonly", 1);;
-  id_summary = str2id(pool, "summary", 1);
-
-  // package
-  id_authors = str2id(pool, "authors", 1);
-  id_summary = str2id(pool, "summary", 1);
-  id_description = str2id(pool, "description", 1);
-  id_diskusage = str2id(pool, "diskusage", 1);
-  id_downloadsize = str2id(pool, "downloadsize", 1);
-  id_eula = str2id(pool, "eula", 1);
-  id_group = str2id(pool, "group", 1);
-  id_installsize = str2id(pool, "installsize", 1);
-  id_keywords = str2id(pool, "keywords", 1);
-  id_license = str2id(pool, "license", 1);
-  id_messagedel = str2id(pool, "messagedel", 1);
-  id_messageins = str2id(pool, "messageins", 1);
-  id_mediadir = str2id(pool, "mediadir", 1);
-  id_mediafile = str2id(pool, "mediafile", 1);
-  id_medianr = str2id(pool, "medianr", 1);
-  id_nosource = str2id(pool, "nosource", 1);
-  id_source = str2id(pool, "source", 1);
-  id_sourceid = str2id(pool, "sourceid", 1);
-  id_time = str2id(pool, "time", 1);
-  id_filelist = str2id(pool, "filelist", 1);
-
-  id_isvisible = str2id(pool, "isvisible", 1);
-
-  id_must = str2id(pool, "must", 1);
-  id_should = str2id(pool, "should", 1);
-  id_may = str2id(pool, "may", 1);
-
-}
 
 /* util function to set a translated string */
-void repodata_set_tstr(Repodata *data, Id rid, const char *attrname, const char *lang, const char *str)
+static inline void repodata_set_tstr(Repodata *data, Id rid, const char *attrname, const char *lang, const char *str)
 {
   Id attrid;
-  attrid = str2id(data->repo->pool, join2( attrname, ":", lang), 1);
+  attrid = str2id(data->repo->pool, join2(attrname, ":", lang), 1);
   repodata_set_str(data, rid, attrid, str);
 }