(De-)Serialize structured types. Dataiterator and repo_search support
authorMichael Matz <matz@suse.de>
Sun, 27 Apr 2008 18:15:46 +0000 (18:15 +0000)
committerMichael Matz <matz@suse.de>
Sun, 27 Apr 2008 18:15:46 +0000 (18:15 +0000)
them too, but not yet nested, so that is unsupported for now.

src/repo.h
src/repo_solv.c
src/repodata.c
src/repopack.h
tools/dumpsolv.c
tools/repo_susetags.c
tools/repo_write.c

index cc85d3c..5eebed5 100644 (file)
@@ -189,6 +189,9 @@ typedef struct _Dataiterator
   KeyValue kv;
   regex_t regex;
   int regex_err;
+  Id *subkeyp;
+  int subnum;
+  Id subschema;
 } Dataiterator;
 
 /* Use these like:
index 6ff57a3..8822dcc 100644 (file)
@@ -710,7 +710,6 @@ incore_add_u8(Repodata *data, unsigned int x)
 
 // ----------------------------------------------
 
-
 /*
  * read repo from .solv file
  *  and add it to pool
@@ -1135,7 +1134,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
        type = idmap[type];
       else if (parent)
         type = str2id(pool, stringpool_id2str(spool, type), 1);
-      if (type < REPOKEY_TYPE_VOID || type > REPOKEY_TYPE_SHA256)
+      if (type < REPOKEY_TYPE_VOID || type > REPOKEY_TYPE_COUNTED)
        {
          pool_debug(pool, SAT_ERROR, "unsupported data type '%s'\n", id2str(pool, type));
          data.error = SOLV_ERROR_UNSUPPORTED;
@@ -1455,9 +1454,40 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
                POOL_DEBUG(SAT_DEBUG_STATS,"  %s\n", dep2str(pool, repo->idarraydata[ido]));
 #endif
              break;
+           case REPOKEY_TYPE_COUNTED:
+               {
+                 Id num, did;
+                 dp = data_read_id(dp, &num);
+                 incore_add_id(&data, num);
+                 dp = data_read_id_max(dp, &did, 0, numschemata, &data.error);
+                 incore_add_id(&data, did);
+                 while (num--)
+                   {
+                     Id *kp = schemadata + schemata[did];
+                     for (; *kp; kp++)
+                       {
+                         Id tid;
+                         switch (keys[*kp].type)
+                           {
+                             case REPOKEY_TYPE_ID:
+                               dp = data_read_id_max(dp, &tid, idmap, numid + numrel, &data.error);
+                               incore_add_id(&data, tid);
+                               break;
+                             default:
+                               dps = dp;
+                               //dp = data_skip(dp, keys[*kp].type);
+                               dp = data_skip_recursive(&data, dp, keys + *kp);
+                               incore_add_blob(&data, dps, dp - dps);
+                               break;
+                           }
+                       }
+                   }
+               }
+             break;
            default:
              dps = dp;
-             dp = data_skip(dp, keys[key].type);
+             //dp = data_skip(dp, keys[key].type);
+             dp = data_skip_recursive(&data, dp, keys + key);
              if (keys[key].storage == KEY_STORAGE_INCORE)
                incore_add_blob(&data, dps, dp - dps);
              break;
index 0c1c2c4..803154c 100644 (file)
@@ -98,6 +98,24 @@ repodata_free(Repodata *data)
     close(data->pagefd);
 }
 
+unsigned char *
+data_skip_recursive(Repodata *data, unsigned char *dp, Repokey *key)
+{
+  KeyValue kv;
+  if (key->type != REPOKEY_TYPE_COUNTED)
+    return data_skip(dp, key->type);
+  dp = data_fetch(dp, &kv, key);
+  int num = kv.num;
+  int schema = kv.id;
+  while (num--)
+    {
+      Id *keyp = data->schemadata + data->schemata[schema];
+      for (; *keyp; keyp++)
+       dp = data_skip_recursive(data, dp, data->keys + *keyp);
+    }
+  return dp;
+}
+
 static unsigned char *
 forward_to_key(Repodata *data, Id keyid, Id schemaid, unsigned char *dp)
 {
@@ -116,7 +134,7 @@ forward_to_key(Repodata *data, Id keyid, Id schemaid, unsigned char *dp)
        }
       if (data->keys[k].storage != KEY_STORAGE_INCORE)
        continue;
-      dp = data_skip(dp, data->keys[k].type);
+      dp = data_skip_recursive(data, dp, data->keys + k);
     }
   return 0;
 }
@@ -317,7 +335,7 @@ get_data(Repodata *data, Repokey *key, unsigned char **dpp)
   if (key->storage == KEY_STORAGE_INCORE)
     {
       /* hmm, this is a bit expensive */
-      *dpp = data_skip(dp, key->type);
+      *dpp = data_skip_recursive(data, dp, key);
       return dp;
     }
   else if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
@@ -568,7 +586,32 @@ repodata_search(Repodata *data, Id entry, Id keyname, int (*callback)(void *cbda
          ddp = data_fetch(ddp, &kv, key);
          if (!ddp)
            break;
-         stop = callback(cbdata, data->repo->pool->solvables + data->start + entry, data, key, &kv);
+         if (key->type == REPOKEY_TYPE_COUNTED)
+           {
+             int num = kv.num;
+             int subschema = kv.id;
+             Repokey *countkey = key;
+             kv.eof = 0;
+             callback(cbdata, data->repo->pool->solvables + data->start + entry, data, countkey, &kv);
+             while (num--)
+               {
+                 Id *kp = data->schemadata + data->schemata[subschema];
+                 for (; *kp; kp++)
+                   {
+                     key = data->keys + *kp;
+                     ddp = data_fetch(ddp, &kv, key);
+                     if (!ddp)
+                       exit(1);
+                     callback(cbdata, data->repo->pool->solvables + data->start + entry, data, key, &kv);
+                   }
+                 kv.eof = 1;
+                 callback(cbdata, data->repo->pool->solvables + data->start + entry, data, countkey, &kv);
+               }
+             kv.eof = 2;
+             stop = callback(cbdata, data->repo->pool->solvables + data->start + entry, data, countkey, &kv);
+           }
+         else
+           stop = callback(cbdata, data->repo->pool->solvables + data->start + entry, data, key, &kv);
        }
       while (!kv.eof && !stop);
       if (onekey || stop > SEARCH_NEXT_KEY)
@@ -702,6 +745,7 @@ dataiterator_init(Dataiterator *di, Repo *repo, Id p, Id keyname,
   di->kv.eof = 1;
   di->repo = repo;
   di->idp = 0;
+  di->subkeyp = 0;
 }
 
 /* FIXME factor and merge with repo_matchvalue */
@@ -908,6 +952,34 @@ restart:
                continue;
            }
        }
+      else if (di->subkeyp)
+       {
+         Id keyid;
+         if (!di->subnum)
+           {
+             /* Send end-of-substruct.  We are here only when we saw a
+                _COUNTED key one level up.  Since then we didn't increment
+                ->keyp, so it still can be found at keyp[-1].  */
+             di->kv.eof = 2;
+             di->key = di->data->keys + di->keyp[-1];
+             di->subkeyp = 0;
+           }
+         else if (!(keyid = *di->subkeyp++))
+           {
+             /* Send end-of-element.  See above for keyp[-1].  */
+             di->kv.eof = 1;
+             di->key = di->data->keys + di->keyp[-1];
+             di->subkeyp = di->data->schemadata + di->data->schemata[di->subschema];
+             di->subnum--;
+           }
+         else
+           {
+             di->key = di->data->keys + keyid;
+             di->dp = data_fetch(di->dp, &di->kv, di->key);
+             if (!di->dp)
+               exit(1);
+           }
+       }
       else
        {
          if (di->kv.eof)
@@ -986,6 +1058,13 @@ skiprepo:;
                }
              di->dp = data_fetch(di->dp, &di->kv, di->key);
            }
+         if (di->key->type == REPOKEY_TYPE_COUNTED)
+           {
+             di->subnum = di->kv.num;
+             di->subschema = di->kv.id;
+             di->kv.eof = 0;
+             di->subkeyp = di->data->schemadata + di->data->schemata[di->subschema];
+           }
        }
 weg2:
       if (!di->match
@@ -1523,7 +1602,9 @@ Id
 repodata_create_struct(Repodata *data, Id handle, Id keyname)
 {
   Id newhandle = get_new_struct(data);
-  repodata_add_idarray(data, handle, keyname, newhandle);
+  repodata_add_array(data, handle, keyname, REPOKEY_TYPE_COUNTED, 1);
+  data->attriddata[data->attriddatalen++] = newhandle;
+  data->attriddata[data->attriddatalen++] = 0;
   return newhandle;
 }
 
@@ -1647,12 +1728,133 @@ fprintf(stderr, "addschema: new schema\n");
   return data->nschemata++; 
 }
 
+static void
+repodata_serialize_key(Repodata *data, struct extdata *newincore,
+                      struct extdata *newvincore,
+                      Id *schema, Id *schematacache,
+                      Repokey *key, Id val)
+{
+  /* Otherwise we have a new value.  Parse it into the internal
+     form.  */
+  Id *ida;
+  struct extdata *xd;
+  unsigned int oldvincorelen = 0;
+  Id schemaid, *sp;
+
+  xd = newincore;
+  if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
+    {
+      xd = newvincore;
+      oldvincorelen = xd->len;
+    }
+  switch (key->type)
+    {
+      case REPOKEY_TYPE_VOID:
+      case REPOKEY_TYPE_CONSTANT:
+      case REPOKEY_TYPE_CONSTANTID:
+       break;
+      case REPOKEY_TYPE_STR:
+       data_addblob(xd, data->attrdata + val, strlen((char *)(data->attrdata + val)) + 1);
+       break;
+      case REPOKEY_TYPE_MD5:
+       data_addblob(xd, data->attrdata + val, SIZEOF_MD5);
+       break;
+      case REPOKEY_TYPE_SHA1:
+       data_addblob(xd, data->attrdata + val, SIZEOF_SHA1);
+       break;
+      case REPOKEY_TYPE_ID:
+      case REPOKEY_TYPE_NUM:
+      case REPOKEY_TYPE_DIR:
+       data_addid(xd, val);
+       break;
+      case REPOKEY_TYPE_IDARRAY:
+       for (ida = data->attriddata + val; *ida; ida++)
+         data_addideof(xd, ida[0], ida[1] ? 0 : 1);
+       break;
+      case REPOKEY_TYPE_DIRNUMNUMARRAY:
+       for (ida = data->attriddata + val; *ida; ida += 3)
+         {
+           data_addid(xd, ida[0]);
+           data_addid(xd, ida[1]);
+           data_addideof(xd, ida[2], ida[3] ? 0 : 1);
+         }
+       break;
+      case REPOKEY_TYPE_DIRSTRARRAY:
+       for (ida = data->attriddata + val; *ida; ida += 2)
+         {
+           data_addideof(xd, ida[0], ida[2] ? 0 : 1);
+           data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
+         }
+       break;
+      case REPOKEY_TYPE_COUNTED:
+       {
+         int num = 0;
+         schemaid = 0;
+         for (ida = data->attriddata + val; *ida; ida++)
+           {
+#if 0
+             fprintf(stderr, "serialize struct %d\n", *ida);
+#endif
+             sp = schema;
+             Id *kp = data->structs[*ida];
+             if (!kp)
+               continue;
+             num++;
+             for (;*kp; kp += 2)
+               {
+#if 0
+                 fprintf(stderr, "  %s:%d\n", id2str(data->repo->pool, data->keys[*kp].name), kp[1]);
+#endif
+                 *sp++ = *kp;
+               }
+             *sp = 0;
+             if (!schemaid)
+               schemaid = addschema(data, schema, schematacache);
+             else if (schemaid != addschema(data, schema, schematacache))
+               {
+                 fprintf(stderr, "  not yet implemented: substructs with different schemas\n");
+                 exit(1);
+               }
+#if 0
+             fprintf(stderr, "  schema %d\n", schemaid);
+#endif
+           }
+         if (!num)
+           break;
+         data_addid(xd, num);
+         data_addid(xd, schemaid);
+         for (ida = data->attriddata + val; *ida; ida++)
+           {
+             Id *kp = data->structs[*ida];
+             if (!kp)
+               continue;
+             for (;*kp; kp += 2)
+               {
+                 repodata_serialize_key(data, newincore, newvincore,
+                                        schema, schematacache,
+                                        data->keys + *kp, kp[1]);
+               }
+           }
+         break;
+       }
+      default:
+       fprintf(stderr, "don't know how to handle type %d\n", key->type);
+       exit(1);
+    }
+  if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
+    {
+      /* put offset/len in incore */
+      data_addid(newincore, data->lastverticaloffset + oldvincorelen);
+      oldvincorelen = xd->len - oldvincorelen;
+      data_addid(newincore, oldvincorelen);
+    }
+}
 
 void
 repodata_internalize(Repodata *data)
 {
   Repokey *key;
-  Id id, entry, nentry, *ida;
+  Id entry, nentry;
   Id schematacache[256];
   Id schemaid, *schema, *sp, oldschema, *keyp, *seen;
   unsigned char *dp, *ndp;
@@ -1745,6 +1947,9 @@ fprintf(stderr, "schemadata %p\n", data->schemadata);
       for (keyp = data->schemadata + data->schemata[schemaid]; *keyp; keyp++)
        {
          key = data->keys + *keyp;
+#if 0
+         fprintf(stderr, "internalize %d:%s:%s\n", entry, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type));
+#endif
          ndp = dp;
          if (oldcount)
            {
@@ -1755,7 +1960,7 @@ fprintf(stderr, "schemadata %p\n", data->schemadata);
                  ndp = data_skip(ndp, REPOKEY_TYPE_ID);
                }
              else if (key->storage == KEY_STORAGE_INCORE)
-               ndp = data_skip(dp, key->type);
+               ndp = data_skip_recursive(data, dp, key);
              oldcount--;
            }
          if (seen[*keyp] == -1)
@@ -1771,66 +1976,9 @@ fprintf(stderr, "schemadata %p\n", data->schemadata);
            {
              /* Otherwise we have a new value.  Parse it into the internal
                 form.  */
-             struct extdata *xd;
-             unsigned int oldvincorelen = 0;
-
-             xd = &newincore;
-             if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
-               {
-                 xd = &newvincore;
-                 oldvincorelen = xd->len;
-               }
-             id = seen[*keyp] - 1;
-             switch (key->type)
-               {
-               case REPOKEY_TYPE_VOID:
-               case REPOKEY_TYPE_CONSTANT:
-               case REPOKEY_TYPE_CONSTANTID:
-                 break;
-               case REPOKEY_TYPE_STR:
-                 data_addblob(xd, data->attrdata + id, strlen((char *)(data->attrdata + id)) + 1);
-                 break;
-               case REPOKEY_TYPE_MD5:
-                 data_addblob(xd, data->attrdata + id, SIZEOF_MD5);
-                 break;
-               case REPOKEY_TYPE_SHA1:
-                 data_addblob(xd, data->attrdata + id, SIZEOF_SHA1);
-                 break;
-               case REPOKEY_TYPE_ID:
-               case REPOKEY_TYPE_NUM:
-               case REPOKEY_TYPE_DIR:
-                 data_addid(xd, id);
-                 break;
-               case REPOKEY_TYPE_IDARRAY:
-                 for (ida = data->attriddata + id; *ida; ida++)
-                   data_addideof(xd, ida[0], ida[1] ? 0 : 1);
-                 break;
-               case REPOKEY_TYPE_DIRNUMNUMARRAY:
-                 for (ida = data->attriddata + id; *ida; ida += 3)
-                   {
-                     data_addid(xd, ida[0]);
-                     data_addid(xd, ida[1]);
-                     data_addideof(xd, ida[2], ida[3] ? 0 : 1);
-                   }
-                 break;
-               case REPOKEY_TYPE_DIRSTRARRAY:
-                 for (ida = data->attriddata + id; *ida; ida += 2)
-                   {
-                     data_addideof(xd, ida[0], ida[2] ? 0 : 1);
-                     data_addblob(xd, data->attrdata + ida[1], strlen((char *)(data->attrdata + ida[1])) + 1);
-                   }
-                 break;
-               default:
-                 fprintf(stderr, "don't know how to handle type %d\n", key->type);
-                 exit(1);
-               }
-             if (key->storage == KEY_STORAGE_VERTICAL_OFFSET)
-               {
-                 /* put offset/len in incore */
-                 data_addid(&newincore, data->lastverticaloffset + oldvincorelen);
-                 oldvincorelen = xd->len - oldvincorelen;
-                 data_addid(&newincore, oldvincorelen);
-               }
+             repodata_serialize_key(data, &newincore, &newvincore,
+                                    schema, schematacache,
+                                    key, seen[*keyp] - 1);
            }
          dp = ndp;
        }
index 14e3bd8..9940253 100644 (file)
@@ -103,6 +103,9 @@ data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key)
       dp = data_read_id(dp, &kv->id);
       dp = data_read_id(dp, &kv->num);
       return data_read_ideof(dp, &kv->num2, &kv->eof);
+    case REPOKEY_TYPE_COUNTED:
+      dp = data_read_id(dp, &kv->num);
+      return data_read_id(dp, &kv->id);
     default:
       return 0;
     }
@@ -168,6 +171,13 @@ data_skip(unsigned char *dp, int type)
             return dp + 1;
           dp++;
         }
+    case REPOKEY_TYPE_COUNTED:
+      while ((*dp & 0x80) != 0)
+        dp++;
+      dp++;
+      while ((*dp & 0x80) != 0)
+        dp++;
+      return dp + 1;
     default:
       return 0;
     }
@@ -247,9 +257,19 @@ data_skip_verify(unsigned char *dp, int type, int maxid, int maxdir)
             return dp + 1;
           dp++;
         }
+    case REPOKEY_TYPE_COUNTED:
+      while ((*dp & 0x80) != 0)
+        dp++;
+      dp++;
+      while ((*dp & 0x80) != 0)
+        dp++;
+      return dp + 1;
     default:
       return 0;
     }
 }
 
+unsigned char * data_skip_recursive(Repodata *data, unsigned char *dp,
+                                   Repokey *key);
+
 #endif /* SATSOLVER_REPOPACK */
index d65eda3..aaa8591 100644 (file)
@@ -103,6 +103,9 @@ dump_attr(Repo *repo, Repodata *data, Repokey *key, KeyValue *kv)
     case REPOKEY_TYPE_DIRSTRARRAY:
       printf("%s: %s\n", keyname, repodata_dir2str(data, kv->id, kv->str));
       break;
+    case REPOKEY_TYPE_COUNTED:
+      printf("%s: %s\n", keyname, kv->eof == 0 ? "open" : kv->eof == 1 ? "next" : "close");
+      break;
     default:
       printf("%s: ?\n", keyname);
       break;
@@ -110,11 +113,11 @@ dump_attr(Repo *repo, Repodata *data, Repokey *key, KeyValue *kv)
   return 0;
 }
 
-static int
+/*static int
 dump_repoattrs_cb(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv)
 {
   return dump_attr(s->repo, data, key, kv);
-}
+}*/
 
 /*
  * dump all attributes for Id <p>
@@ -123,7 +126,7 @@ dump_repoattrs_cb(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyV
 void
 dump_repoattrs(Repo *repo, Id p)
 {
-#if 1
+#if 0
   repo_search(repo, p, 0, 0, SEARCH_NO_STORAGE_SOLVABLE, dump_repoattrs_cb, 0);
 #else
   Dataiterator di;
index 42f59aa..f8cd4b3 100644 (file)
@@ -872,6 +872,15 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, const char *language, int fla
            break;
          case CTAG('=', 'C', 'k', 's'):
            set_checksum(data, handle, SOLVABLE_CHECKSUM, line + 6);
+           if (0)
+             {
+               Id sub = repodata_create_struct(data, handle, str2id(pool, "solvable:komisch", 1));
+               repodata_set_poolstr(data, sub, str2id(pool, "sub:key1", 1), line + 6);
+               repodata_set_num(data, sub, str2id(pool, "sub:key2", 1), last_found_pack);
+               sub = repodata_create_struct(data, handle, str2id(pool, "solvable:komisch", 1));
+               repodata_set_poolstr(data, sub, str2id(pool, "sub:key1", 1), line + 7);
+               repodata_set_num(data, sub, str2id(pool, "sub:key2", 1), last_found_pack+1);
+             }
            break;
          case CTAG('=', 'L', 'a', 'n'):
            language = strdup(line + 6);
index ed5e824..5d659c4 100644 (file)
@@ -371,6 +371,7 @@ struct cbdata {
 
   Id *schema;          /* schema construction space */
   Id *sp;              /* pointer in above */
+  Id *oldschema, *oldsp;
 
   Id *myschemata;
   int nmyschemata;
@@ -382,6 +383,9 @@ struct cbdata {
 
   Id *solvschemata;
   Id *extraschemata;
+  Id *subschemata;
+  int nsubschemata;
+  int current_sub;
 
   struct extdata *extdata;
 
@@ -634,7 +638,8 @@ repo_write_collect_needed(struct cbdata *cbdata, Repo *repo, Repodata *data, Rep
   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)
+  if ((key->type != REPOKEY_TYPE_COUNTED || kv->eof == 0)
+      && (cbdata->sp == cbdata->schema || cbdata->sp[-1] != rm))
     *cbdata->sp++ = rm;
   switch(key->type)
     {
@@ -654,6 +659,38 @@ repo_write_collect_needed(struct cbdata *cbdata, Repo *repo, Repodata *data, Rep
        else
          setdirused(cbdata, &data->dirpool, id);
        break;
+      case REPOKEY_TYPE_COUNTED:
+       if (kv->eof == 0)
+         {
+           if (cbdata->oldschema)
+             {
+               fprintf(stderr, "nested structs not yet implemented\n");
+               exit(1);
+             }
+           cbdata->oldschema = cbdata->schema;
+           cbdata->oldsp = cbdata->sp;
+           cbdata->schema = sat_calloc(cbdata->nmykeys, sizeof(Id));
+           cbdata->sp = cbdata->schema;
+         }
+       else if (kv->eof == 1)
+         {
+           cbdata->current_sub++;
+           *cbdata->sp = 0;
+           cbdata->subschemata = sat_extend(cbdata->subschemata, cbdata->nsubschemata, 1, sizeof(Id), SCHEMATA_BLOCK);
+           cbdata->subschemata[cbdata->nsubschemata++] = addschema(cbdata, cbdata->schema);
+#if 0
+           fprintf(stderr, "Have schema %d\n", cbdata->subschemata[cbdata->nsubschemata-1]);
+#endif
+           cbdata->sp = cbdata->schema;
+         }
+       else
+         {
+           sat_free(cbdata->schema);
+           cbdata->schema = cbdata->oldschema;
+           cbdata->sp = cbdata->oldsp;
+           cbdata->oldsp = cbdata->oldschema = 0;
+         }
+       break;
       default:
        break;
     }
@@ -756,6 +793,26 @@ repo_write_adddata(struct cbdata *cbdata, Repodata *data, Repokey *key, KeyValue
        data_addideof(xd, id, kv->eof);
        data_addblob(xd, (unsigned char *)kv->str, strlen(kv->str) + 1);
        break;
+      case REPOKEY_TYPE_COUNTED:
+       if (kv->eof == 0)
+         {
+           if (kv->num)
+             {
+               data_addid(xd, kv->num);
+               data_addid(xd, cbdata->subschemata[cbdata->current_sub]);
+#if 0
+               fprintf(stderr, "writing %d %d\n", kv->num, cbdata->subschemata[cbdata->current_sub]);
+#endif
+             }
+         }
+       else if (kv->eof == 1)
+         {
+           cbdata->current_sub++;
+         }
+       else
+         {
+         }
+       break;
       default:
        fprintf(stderr, "unknown type for %d: %d\n", key->name, key->type);
        exit(1);
@@ -1449,6 +1506,7 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1);
 /********************************************************************/
   cbdata.extdata = sat_calloc(cbdata.nmykeys, sizeof(struct extdata));
   
+  cbdata.current_sub = 0;
   xd = cbdata.extdata;
   maxentrysize = 0;
   for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++)