- some pieces of code for the unified lookup/search interface
authorMichael Schroeder <mls@suse.de>
Fri, 14 Dec 2007 20:08:42 +0000 (20:08 +0000)
committerMichael Schroeder <mls@suse.de>
Fri, 14 Dec 2007 20:08:42 +0000 (20:08 +0000)
src/evr.c
src/repo.c
src/repo.h
src/repo_solv.c

index 857b92e..9ea0398 100644 (file)
--- a/src/evr.c
+++ b/src/evr.c
@@ -98,6 +98,16 @@ evrcmp(Pool *pool, Id evr1id, Id evr2id, int mode)
     ;
   for (s2 = evr2; *s2 >= '0' && *s2 <= '9'; s2++)
     ;
+  if (mode == EVRCMP_MATCH && (*evr1 == ':' || *evr2 == ':'))
+    {
+      /* empty epoch, skip epoch check */
+      if (*s1 == ':')
+       evr1 = s1 + 1;
+      if (*s2 == ':')
+       evr2 = s2 + 1;
+      s1 = evr1;
+      s2 = evr2;
+    }
   if (s1 == evr1 || *s1 != ':')
     s1 = 0;
   if (s2 == evr2 || *s2 != ':')
index 90deae5..0a18895 100644 (file)
@@ -445,111 +445,175 @@ repo_fix_legacy(Repo *repo, Offset provides, Offset supplements)
   return supplements;
 }
 
-#if 0
 void
 repodata_search(Repodata *data, Id key)
 {
 }
 
+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;
+    }
+}
+
+unsigned char *
+data_skip(unsigned char *dp, int type)
+{
+  switch (type)
+    {
+    case TYPE_VOID:
+      return dp;
+    case TYPE_ID:
+      while ((*dp & 0x80) != 0)
+       dp++;
+      return dp;
+    case TYPE_IDARRAY:
+    case TYPE_REL_IDARRAY:
+    case TYPE_IDVALUEARRAY:
+    case TYPE_IDVALUEVALUEARRAY:
+      while ((*dp & 0xc0) != 0)
+       dp++;
+      return dp;
+    default:
+      fprintf(stderr, "unknown type in data_skip\n");
+      exit(1);
+    }
+}
+
 const char *
-repodata_lookup_id(Repodata *data, Id num, Id key)
+repodata_lookup_str(Repodata *data, Id entry, Id key)
 {
+  Id schema;
   Id id, k, *kp, *keyp;
+  unsigned char *dp;
 
-  fseek(data->fp, data->itemoffsets[num] , SEEK_SET);
-  Id *keyp = data->schemadata + data->schemata[read_id(data->fp, data->numschemata)];
-  /* make sure our schema contains the key */
-  for (kp = keyp; (k = *kp++) != 0)
+  if (data->entryschemau8)
+    schema = data->entryschemau8[entry];
+  else
+    schema = data->entryschema[entry];
+  keyp = data->schemadata + schema;
+  /* make sure the schema of this solvable contains the key */
+  for (kp = keyp; (k = *kp++) != 0; )
     if (k == key)
       break;
   if (k == 0)
     return 0;
-  /* get it */
-  while ((k = *keyp++) != 0)
+  switch (data->keys[key].storage)
     {
-      if (k == key)
-       break;
-      switch (keys[key].type)
+    case KEY_STORAGE_VERTICAL_OFFSET:
+    case KEY_STORAGE_INCORE:
+      dp = data->incoredata + data->incoreoffset[entry];
+      while ((k = *keyp++) != 0)
        {
-       case TYPE_ID:
-         while ((read_u8(data->fp) & 0x80) != 0)
-           ;
-         break;
-       case TYPE_U32:
-         read_u32(data->fp);
-         break;
-       case TYPE_STR:
-         while(read_u8(data->fp) != 0)
-           ;
-         break;
-       case TYPE_IDARRAY:
-         while ((read_u8(data->fp) & 0xc0) != 0)
-           ;
-         break;
+         if (k == key)
+           break;
+         if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET)
+           {
+             /* skip that offset */
+             dp = data_skip(dp, TYPE_ID);
+             continue;
+           }
+         if (data->keys[k].storage != KEY_STORAGE_INCORE)
+           continue;
+         dp = data_skip(dp, data->keys[k].type);
        }
+      if (data->keys[key].storage == KEY_STORAGE_VERTICAL_OFFSET)
+       {
+         int i, oi, max;
+         if (!data->fp)
+           return 0;
+         dp = data_read_id(dp, &id);
+         max = data->keys[key].size - id;
+         if (max <= 0)
+           return 0;
+          /* we now have the offset, go into vertical */
+         for (i = 1; i < key; i++)
+           if (data->keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET)
+             id += data->keys[i].size;
+         if (fseek(data->fp, data->verticaloffset + id, SEEK_SET))
+           return 0;
+         i = max > 256 ? 256 : max;
+         for (oi = 0;; oi = i, i += 256)
+           {
+             if (i > max)
+               i = max;
+             if (i == oi)
+               return 0;
+             if (i > data->strbuflen)
+               {
+                 data->strbuf = xrealloc(data->strbuf, i);
+                 data->strbuflen = i;
+               }
+             if (fread(data->strbuf + oi, i - oi, 1, data->fp) != 1)
+               return 0;
+             if (memchr(data->strbuf + oi, 0, i - oi))
+               return data->strbuf;
+           }
+       }
+      if (data->keys[key].type == TYPE_STR)
+       return (const char *)dp;
+      /* id type, must either use global or local string strore*/
+      dp = data_read_id(dp, &id);
+#if 0
+      /* not yet working */
+      return data->ss.stringspace + data->ss.strings[id];
+#else
+      return id2str(data->repo->pool, id);
+#endif
     }
-  id = read_id(data->fp, 0);
-  return data->ss.stringspace + data->ss.strings[id];
+  return 0;
 }
 
-Id
-repo_lookup_id(Solvable *s, Id key)
+const char *
+repo_lookup_str(Solvable *s, Id key)
 {
-  Solvable *rs;
   Repo *repo = s->repo;
+  Pool *pool = repo->pool;
   Repodata *data;
   int i, j, n;
 
   switch(key)
     {
     case SOLVABLE_NAME:
-      return s->name;
+      return id2str(pool, s->name);
     case SOLVABLE_ARCH:
-      return s->arch;
+      return id2str(pool, s->arch);
     case SOLVABLE_EVR:
-      return s->evr;
+      return id2str(pool, s->evr);
     case SOLVABLE_VENDOR:
-      return s->vendor;
-    }
-  /* convert solvable id into repo item count */
-  if (repo->end - repo->start + 1 == repo->nsolvables)
-    {
-      n = (s - pool->solvables);
-      if (n < repo->start || n > repo->end)
-       return 0;
-      n -= repo->start;
-    }
-  else
-    {
-      for (i = repo->start, rs = pool->solvables + i, n = 0; i < repo->end; i++, rs++)
-       {
-         if (rs->repo != repo)
-           continue;
-         if (rs == s)
-           break;
-         n++;
-       }
-      if (i == repo->end)
-       return 0;
+      return id2str(pool, s->vendor);
     }
+  n = s - pool->solvables;
   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
     {
-      for (j = 0; j < data->nkeys; j++)
+      if (n < data->start || n >= data->end)
+       continue;
+      for (j = 1; j < data->nkeys; j++)
        {
-         if (data->keys[j].name == key && data->keys[j].type == TYPE_ID)
-           return repodata_lookup_id(data, n, j);
+         if (data->keys[j].name == key && (data->keys[j].type == TYPE_ID || data->keys[j].type == TYPE_STR))
+           return repodata_lookup_str(data, n - data->start, j);
        }
     }
   return 0;
 }
-#endif
+
 
 static int
 key_cmp (const void *pa, const void *pb)
 {
-  struct key { Id name; unsigned type; };
-  struct key *a = (struct key*)pa;
-  struct key *b = (struct key*)pb;
+  Repokey *a = (Repokey *)pa;
+  Repokey *b = (Repokey *)pb;
   return a->name - b->name;
 }
 
@@ -577,17 +641,16 @@ repo_add_attrstore (Repo *repo, Attrstore *s, const char *location)
   memset (data, 0, sizeof (*data));
   data->s = s;
   data->nkeys = s->nkeys;
-  /* Don't store the first key, it's {0,0,0}.  */
-  data->nkeys--;
   if (data->nkeys)
     {
-      data->keys = xmalloc (data->nkeys * sizeof (data->keys[0]));
-      for (i = 0; i < data->nkeys; i++)
+      data->keys = xmalloc(data->nkeys * sizeof(data->keys[0]));
+      for (i = 1; i < data->nkeys; i++)
         {
-          data->keys[i].name = s->keys[i + 1].name;
-         data->keys[i].type = s->keys[i + 1].type;
+          data->keys[i].name = s->keys[i].name;
+         data->keys[i].type = s->keys[i].type;
        }
-      qsort (data->keys, data->nkeys, sizeof (data->keys[0]), key_cmp);
+      if (data->nkeys > 2)
+        qsort(data->keys + 1, data->nkeys - 1, sizeof(data->keys[0]), key_cmp);
     }
   if (location)
     data->location = strdup(location);
index eda14d2..a27b9ba 100644 (file)
 #include "pool.h"
 #include "attr_store.h"
 
+typedef struct _Repokey {
+  Id name;
+  Id type;
+  Id size;
+  Id storage;
+} Repokey;
+
+#define KEY_STORAGE_DROPPED             0
+#define KEY_STORAGE_SOLVABLE           1
+#define KEY_STORAGE_INCORE             2
+#define KEY_STORAGE_VERTICAL_OFFSET    3
+
+struct _Repo;
+
 typedef struct _Repodata {
+  struct _Repo *repo;          /* back pointer to repo */
+
+  int start;                   /* start of solvables this repodata is valid for */
+  int end;                     /* last solvable + 1 of this repodata */
+
   /* Keys provided by this attribute store, sorted by name value.
      The same keys may be provided by multiple attribute stores, but
      then only for different solvables.  I.e. the relation
        (solvable,name) -> store
      has to be injective.  */
-  struct {
-    Id name;
-    unsigned type;
-  } *keys;
-  /* Length of keys array */
-  unsigned nkeys;
+
+  Repokey *keys;               /* keys, first entry is always zero */
+  unsigned int nkeys;          /* length of keys array */
+
+  Id *schemata;                        /* schema -> offset into schemadata */
+  unsigned int nschemata;      /* number of schemata */
+
+  Id *schemadata;              /* schema storage */
+
+  unsigned char *entryschemau8;        /* schema for entry */
+  Id *entryschema;             /* schema for entry */
+
+  unsigned char *incoredata;   /* in-core data */
+  unsigned int incoredatalen;  /* data len */
+  unsigned int incoredatafree; /* data len */
+
+  Id *incoreoffset;            /* offset for all entries */
+
+  FILE *fp;                    /* for paged access */
+  Id verticaloffset;           /* offset of verticals */
+
+  char *strbuf;
+  int strbuflen;
+
 
   /* The attribute store itself.  */
   Attrstore *s;
@@ -42,9 +79,11 @@ typedef struct _Repodata {
   unsigned char checksum[20];
 } Repodata;
 
+
 typedef struct _Repo {
   const char *name;
   struct _Pool *pool;          /* pool containing repo data */
+
   int start;                   /* start of this repo solvables within pool->solvables */
   int end;                     /* last solvable + 1 of this repo */
   int nsolvables;              /* number of solvables repo is contributing to pool */
index a01f719..8c690af 100644 (file)
@@ -284,20 +284,13 @@ skip_item (FILE *fp, unsigned type, unsigned numid, unsigned numrel)
 static int
 key_cmp (const void *pa, const void *pb)
 {
-  struct key { Id name; unsigned type; };
-  struct key *a = (struct key*)pa;
-  struct key *b = (struct key*)pb;
+  Repokey *a = (Repokey *)pa;
+  Repokey *b = (Repokey *)pb;
   return a->name - b->name;
 }
 
-struct key {
-  Id name;
-  Id type;
-  Id size;
-};
-
 static void
-parse_repodata (FILE *fp, Id *keyp, struct key *keys, Id *idmap, unsigned numid, unsigned numrel, Repo *repo)
+parse_repodata (FILE *fp, Id *keyp, Repokey *keys, Id *idmap, unsigned numid, unsigned numrel, Repo *repo)
 {
   Id key, id;
   Id *ida, *ide;
@@ -306,6 +299,7 @@ parse_repodata (FILE *fp, Id *keyp, struct key *keys, Id *idmap, unsigned numid,
 
   repo->repodata = xrealloc(repo->repodata, (repo->nrepodata + 1) * sizeof (*data));
   data = repo->repodata + repo->nrepodata++;
+  data->repo = repo;
   memset(data, 0, sizeof(*data));
 
   while ((key = *keyp++) != 0)
@@ -327,9 +321,10 @@ parse_repodata (FILE *fp, Id *keyp, struct key *keys, Id *idmap, unsigned numid,
              pool_debug (mypool, SAT_FATAL, "invalid attribute data\n");
              exit (1);
            }
-         data->nkeys = n >> 1;
+         data->nkeys = 1 + (n >> 1);
          data->keys = xmalloc2(data->nkeys, sizeof(data->keys[0]));
-         for (i = 0, ide = ida; i < data->nkeys; i++)
+         memset(data->keys, 0, sizeof(Repokey));
+         for (i = 1, ide = ida; i < data->nkeys; i++)
            {
              if (*ide >= numid)
                {
@@ -338,9 +333,12 @@ parse_repodata (FILE *fp, Id *keyp, struct key *keys, Id *idmap, unsigned numid,
                }
              data->keys[i].name = idmap[*ide++];
              data->keys[i].type = *ide++;
+             data->keys[i].size = 0;
+             data->keys[i].storage = 0;
            }
          xfree(ida);
-         qsort(data->keys, data->nkeys, sizeof(data->keys[0]), key_cmp);
+         if (data->nkeys > 2)
+           qsort(data->keys + 1, data->nkeys - 1, sizeof(data->keys[0]), key_cmp);
          break;
        case TYPE_STR:
          if (id != REPODATA_LOCATION)
@@ -366,14 +364,79 @@ parse_repodata (FILE *fp, Id *keyp, struct key *keys, Id *idmap, unsigned numid,
 /*-----------------------------------------------------------------*/
 
 
-void
-skip_schema(FILE *fp, Id *keyp, struct key *keys, unsigned int numid, unsigned int numrel)
+static void
+skip_schema(FILE *fp, Id *keyp, Repokey *keys, unsigned int numid, unsigned int numrel)
 {
   Id key;
   while ((key = *keyp++) != 0)
     skip_item(fp, keys[key].type, numid, numrel);
 }
 
+/*-----------------------------------------------------------------*/
+
+static void
+incore_add_id(Repodata *data, Id x)
+{
+  unsigned char *dp;
+  /* make sure we have at least 5 bytes free */
+  if (data->incoredatafree < 5)
+    {
+      data->incoredata = xrealloc(data->incoredata, data->incoredatalen + 1024);
+      data->incoredatafree = 1024;
+    }
+  dp = data->incoredata + data->incoredatalen;
+  if (x < 0)
+    abort();
+  if (x >= (1 << 14))
+    {
+      if (x >= (1 << 28))
+       *dp++ = (x >> 28) | 128;
+      if (x >= (1 << 21))
+       *dp++ = (x >> 21) | 128;
+      *dp++ = (x >> 14) | 128;
+    }
+  if (x >= (1 << 7))
+    *dp++ = (x >> 7) | 128;
+  *dp++ = x & 127;
+  data->incoredatafree -= dp - (data->incoredata + data->incoredatalen);
+  data->incoredatalen = dp - data->incoredata;
+}
+
+static void
+incore_add_u32(Repodata *data, unsigned int x)
+{
+  unsigned char *dp;
+  /* make sure we have at least 4 bytes free */
+  if (data->incoredatafree < 4)
+    {
+      data->incoredata = xrealloc(data->incoredata, data->incoredatalen + 1024);
+      data->incoredatafree = 1024;
+    }
+  dp = data->incoredata + data->incoredatalen;
+  *dp++ = x >> 24;
+  *dp++ = x >> 16;
+  *dp++ = x >> 8;
+  *dp++ = x;
+  data->incoredatafree -= 4;
+  data->incoredatalen += 4;
+}
+
+static void
+incore_add_u8(Repodata *data, unsigned int x)
+{
+  unsigned char *dp;
+  /* make sure we have at least 1 byte free */
+  if (data->incoredatafree < 1)
+    {
+      data->incoredata = xrealloc(data->incoredata, data->incoredatalen + 1024);
+      data->incoredatafree = 1024;
+    }
+  dp = data->incoredata + data->incoredatalen;
+  *dp++ = x;
+  data->incoredatafree--;
+  data->incoredatalen++;
+}
+
 // ----------------------------------------------
 
 /*
@@ -388,7 +451,9 @@ repo_add_solv(Repo *repo, FILE *fp)
   int i, l;
   unsigned int numid, numrel, numsolv;
   unsigned int numkeys, numschemata, numinfo;
+#if 0
   Attrstore *embedded_store = 0;
+#endif
 
   Offset sizeid;
   Offset *str;                        /* map Id -> Offset into string space */
@@ -408,10 +473,12 @@ repo_add_solv(Repo *repo, FILE *fp)
   Solvable *s;
   unsigned int solvflags;
   unsigned int solvversion;
-  struct key *keys;
+  Repokey *keys;
   Id *schemadata, *schemadatap, *schemadataend;
   Id *schemata, key;
 
+  Repodata data;
+
   mypool = pool;
 
   if (read_u32(fp) != ('S' << 24 | 'O' << 16 | 'L' << 8 | 'V'))
@@ -441,6 +508,9 @@ repo_add_solv(Repo *repo, FILE *fp)
   numinfo = read_u32(fp);
   solvflags = read_u32(fp);
 
+  memset(&data, 0, sizeof(data));
+  data.repo = repo;
+
   if (solvversion < SOLV_VERSION_3
       && numinfo)
     {
@@ -679,11 +749,50 @@ repo_add_solv(Repo *repo, FILE *fp)
   /* keys start at 1 */
   for (i = 1; i < numkeys; i++)
     {
-      keys[i].name = idmap[read_id(fp, numid)];
+      keys[i].name = id = idmap[read_id(fp, numid)];
       keys[i].type = read_id(fp, 0);
       keys[i].size = read_id(fp, 0);
+      keys[i].storage = KEY_STORAGE_DROPPED;
+      switch (keys[i].type)
+       {
+       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_STR:
+         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;
+       }
     }
 
+  data.keys = keys;
+  data.nkeys = numkeys;
+
   /*******  Part 4: Schemata ********************************************/
   
   id = read_id(fp, 0);
@@ -696,6 +805,9 @@ repo_add_solv(Repo *repo, FILE *fp)
       schemata[i] = schemadatap - schemadata;
       schemadatap = read_idarray(fp, numid, 0, schemadatap, schemadataend, 0);
     }
+  data.schemata = schemata;
+  data.nschemata = numschemata;
+  data.schemadata = schemadata;
 
   /*******  Part 5: Info  ***********************************************/
   for (i = 0; i < numinfo; i++)
@@ -760,6 +872,8 @@ repo_add_solv(Repo *repo, FILE *fp)
       Solvable *sstart = s;
       Id type;
 
+/* XXX BROKEN CODE */
+
       for (i = 0; i < numsolv; i++)
        solvschema[i] = read_id(fp, numschemata);
       for (key = 1; key < numkeys; key++)
@@ -793,6 +907,8 @@ repo_add_solv(Repo *repo, FILE *fp)
                    s->evr = did;
                  else if (id == SOLVABLE_VENDOR)
                    s->vendor = did;
+                 else
+                   incore_add_id(&data, did);
                  break;
                case TYPE_U32:
                  h = read_u32(fp);
@@ -802,6 +918,10 @@ repo_add_solv(Repo *repo, FILE *fp)
                        repo->rpmdbid = (Id *)xcalloc(numsolv, sizeof(Id));
                      repo->rpmdbid[i] = h;
                    }
+                 else
+                   {
+                     incore_add_u32(&data, h);
+                   }
                  break;
                case TYPE_STR:
                  while(read_u8(fp) != 0)
@@ -838,6 +958,8 @@ repo_add_solv(Repo *repo, FILE *fp)
                    s->freshens = ido;
                  break;
                case TYPE_VOID:
+                 break;
+#if 0
                case TYPE_ATTR_INT:
                case TYPE_ATTR_CHUNK:
                case TYPE_ATTR_STRING:
@@ -847,6 +969,9 @@ repo_add_solv(Repo *repo, FILE *fp)
                    embedded_store = new_store (pool);
                  add_attr_from_file (embedded_store, i, id, type, idmap, numid, fp);
                  break;
+#endif
+               default:
+                 abort();
                }
            }
        }
@@ -859,6 +984,7 @@ repo_add_solv(Repo *repo, FILE *fp)
       mypool = 0;
       return;
     }
+
   for (i = 0; i < numsolv; i++, s++)
     {
       if (exists && !exists[i])
@@ -879,6 +1005,8 @@ repo_add_solv(Repo *repo, FILE *fp)
                s->evr = did;
              else if (id == SOLVABLE_VENDOR)
                s->vendor = did;
+             else if (keys[key].storage == KEY_STORAGE_INCORE)
+               incore_add_id(&data, did);
 #if 0
              POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %s\n", id2str(pool, id), id2str(pool, did));
 #endif
@@ -894,19 +1022,61 @@ repo_add_solv(Repo *repo, FILE *fp)
                    repo->rpmdbid = (Id *)xcalloc(numsolv, sizeof(Id));
                  repo->rpmdbid[i] = h;
                }
+             else if (keys[key].storage == KEY_STORAGE_INCORE)
+               incore_add_u32(&data, h);
              break;
            case TYPE_STR:
-             while(read_u8(fp) != 0)
-               ;
+              if (keys[key].storage == KEY_STORAGE_INCORE)
+               {
+                 while ((h = read_u8(fp)) != 0)
+                   incore_add_u8(&data, h);
+                 incore_add_u8(&data, 0);
+               }
+             else
+               {
+                 while (read_u8(fp) != 0)
+                   ;
+               }
              break;
            case TYPE_IDARRAY:
            case TYPE_REL_IDARRAY:
              if (id < INTERESTED_START || id > INTERESTED_END)
                {
-                 /* not interested in array */
-                 while ((read_u8(fp) & 0xc0) != 0)
-                   ;
-                 break;
+                 if (keys[key].storage == KEY_STORAGE_INCORE)
+                   {
+                     Id old = 0, rel = keys[key].type == TYPE_REL_IDARRAY ? SOLVABLE_PREREQMARKER : 0;
+                     do
+                       {
+                         did = read_id(fp, 0);
+                         h = did & 0x40;
+                         did = (did & 0x3f) | ((did >> 1) & ~0x3f);
+                         if (rel)
+                           {
+                             if (did == 0)
+                               {
+                                 did = rel;
+                                 old = 0;
+                               }
+                             else
+                               {
+                                 did += old;
+                                 old = did;
+                               }
+                           }
+                         if (did >= numid + numrel)
+                           abort();
+                         did = idmap[did];
+                         did = ((did & ~0x3f) << 1) | h;
+                         incore_add_id(&data, did);
+                       }
+                     while (h);
+                   }
+                 else
+                   {
+                     while ((read_u8(fp) & 0xc0) != 0)
+                       ;
+                     break;
+                   }
                }
              ido = idarraydatap - repo->idarraydata;
              idarraydatap = read_idarray(fp, numid + numrel, idmap, idarraydatap, idarraydataend, keys[key].type == TYPE_REL_IDARRAY);
@@ -934,7 +1104,9 @@ repo_add_solv(Repo *repo, FILE *fp)
                POOL_DEBUG(SAT_DEBUG_STATS,"  %s\n", dep2str(pool, repo->idarraydata[ido]));
 #endif
              break;
+#if 0
            case TYPE_VOID:
+
            case TYPE_ATTR_INT:
            case TYPE_ATTR_CHUNK:
            case TYPE_ATTR_STRING:
@@ -944,12 +1116,45 @@ repo_add_solv(Repo *repo, FILE *fp)
                embedded_store = new_store (pool);
              add_attr_from_file (embedded_store, i, id, keys[key].type, idmap, numid, fp);
              break;
+#endif
            default:
              skip_item(fp, keys[key].type, numid, numrel);
            }
        }
     }
+
+  if (data.incoredatafree)
+    {
+      /* shrink excess size */
+      data.incoredata = xrealloc(data.incoredata, data.incoredatalen);
+      data.incoredatafree = 0;
+    }
+
+  for (i = 1; i < numkeys; i++)
+    if (keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET)
+      break;
+  if (i < numkeys)
+    {
+      /* we have vertical data, make it available */
+      data.fp = fp;
+      data.verticaloffset = ftell(fp);
+    }
+
+  if (data.incoredatalen || data.fp)
+    {
+      /* we got some data, make it available */
+      repo->repodata = xrealloc(repo->repodata, (repo->nrepodata + 1) * sizeof(data));
+      repo->repodata[repo->nrepodata++] = data;
+    }
+  else
+    {
+      xfree(schemata);
+      xfree(schemadata);
+      xfree(keys);
+    }
+
   xfree(exists);
+#if 0
   if (embedded_store)
     {
       attr_store_pack (embedded_store);
@@ -958,10 +1163,8 @@ repo_add_solv(Repo *repo, FILE *fp)
       /* The NULL name here means embedded attributes.  */
       repo_add_attrstore (repo, embedded_store, NULL);
     }
+#endif
   xfree(idmap);
-  xfree(schemata);
-  xfree(schemadata);
-  xfree(keys);
   mypool = 0;
 }