Imported Upstream version 0.6.9
[platform/upstream/libsolv.git] / src / repodata.c
index 85e9103..4ba1345 100644 (file)
@@ -479,11 +479,11 @@ get_vertical_data(Repodata *data, Repokey *key, Id off, Id len)
   if (off >= data->lastverticaloffset)
     {
       off -= data->lastverticaloffset;
-      if (off + len > data->vincorelen)
+      if ((unsigned int)off + len > data->vincorelen)
        return 0;
       return data->vincore + off;
     }
-  if (off + len > key->size)
+  if ((unsigned int)off + len > key->size)
     return 0;
   /* we now have the offset, go into vertical */
   off += data->verticaloffset[key - data->keys];
@@ -855,7 +855,7 @@ repodata_lookup_id_uninternalized(Repodata *data, Id solvid, Id keyname, Id void
  */
 
 
-int
+const char *
 repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int flags)
 {
   switch (key->type)
@@ -875,26 +875,26 @@ repodata_stringify(Pool *pool, Repodata *data, Repokey *key, KeyValue *kv, int f
          if (*s == ':' && s > kv->str)
            kv->str = s + 1;
        }
-      return 1;
+      return kv->str;
     case REPOKEY_TYPE_STR:
-      return 1;
+      return kv->str;
     case REPOKEY_TYPE_DIRSTRARRAY:
       if (!(flags & SEARCH_FILES))
-       return 1;       /* match just the basename */
+       return kv->str; /* match just the basename */
       if (kv->num)
-       return 1;       /* already stringified */
+       return kv->str; /* already stringified */
       /* Put the full filename into kv->str.  */
       kv->str = repodata_dir2str(data, kv->id, kv->str);
       kv->num = 1;     /* mark stringification */
-      return 1;
+      return kv->str;
     case_CHKSUM_TYPES:
       if (!(flags & SEARCH_CHECKSUMS))
        return 0;       /* skip em */
       if (kv->num)
-       return 1;       /* already stringified */
+       return kv->str; /* already stringified */
       kv->str = repodata_chk2str(data, key->type, (const unsigned char *)kv->str);
       kv->num = 1;     /* mark stringification */
-      return 1;
+      return kv->str;
     default:
       return 0;
     }
@@ -1444,6 +1444,8 @@ dataiterator_filelistcheck(Dataiterator *di)
   if (!needcomplete)
     {
       /* we don't need the complete filelist, so ignore all stubs */
+      if (data->repo->nrepodata == 2)
+       return 1;
       for (j = 1; j < data->nkeys; j++)
        if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
          return 1;
@@ -1736,17 +1738,18 @@ dataiterator_step(Dataiterator *di)
 
       if (di->matcher.match)
        {
+         const char *str;
          /* simple pre-check so that we don't need to stringify */
          if (di->keyname == SOLVABLE_FILELIST && di->key->type == REPOKEY_TYPE_DIRSTRARRAY && (di->matcher.flags & SEARCH_FILES) != 0)
            if (!datamatcher_checkbasename(&di->matcher, di->kv.str))
              continue;
-         if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
+         if (!(str = repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags)))
            {
              if (di->keyname && (di->key->type == REPOKEY_TYPE_FIXARRAY || di->key->type == REPOKEY_TYPE_FLEXARRAY))
                return 1;
              continue;
            }
-         if (!datamatcher_match(&di->matcher, di->kv.str))
+         if (!datamatcher_match(&di->matcher, str))
            continue;
        }
       else
@@ -1970,11 +1973,10 @@ dataiterator_jump_to_repo(Dataiterator *di, Repo *repo)
 int
 dataiterator_match(Dataiterator *di, Datamatcher *ma)
 {
-  if (!repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags))
+  const char *str;
+  if (!(str = repodata_stringify(di->pool, di->data, di->key, &di->kv, di->flags)))
     return 0;
-  if (!ma)
-    return 1;
-  return datamatcher_match(ma, di->kv.str);
+  return ma ? datamatcher_match(ma, str) : 1;
 }
 
 void
@@ -2102,6 +2104,7 @@ repodata_extend_block(Repodata *data, Id start, Id num)
     return;
   if (!data->incoreoffset)
     {
+      /* this also means that data->attrs is NULL */
       data->incoreoffset = solv_calloc_block(num, sizeof(Id), REPODATA_BLOCK);
       data->start = start;
       data->end = start + num;
@@ -2812,6 +2815,10 @@ repodata_swap_attrs(Repodata *data, Id dest, Id src)
   Id *tmpattrs;
   if (!data->attrs || dest == src)
     return;
+  if (dest < data->start || dest >= data->end)
+    repodata_extend(data, dest);
+  if (src < data->start || src >= data->end)
+    repodata_extend(data, src);
   tmpattrs = data->attrs[dest - data->start];
   data->attrs[dest - data->start] = data->attrs[src - data->start];
   data->attrs[src - data->start] = tmpattrs;
@@ -2902,6 +2909,96 @@ data_addblob(struct extdata *xd, unsigned char *blob, int len)
 
 /*********************************/
 
+/* this is to reduct memory usage when internalizing oversized repos */
+static void
+compact_attrdata(Repodata *data, int entry, int nentry)
+{
+  int i;
+  unsigned int attrdatastart = data->attrdatalen;
+  unsigned int attriddatastart = data->attriddatalen;
+  if (attrdatastart < 1024 * 1024 * 4 && attriddatastart < 1024 * 1024)
+    return;
+  for (i = entry; i < nentry; i++)
+    {
+      Id v, *attrs = data->attrs[i];
+      if (!attrs)
+       continue;
+      for (; *attrs; attrs += 2)
+       {
+         switch (data->keys[*attrs].type)
+           {
+           case REPOKEY_TYPE_STR:
+           case REPOKEY_TYPE_BINARY:
+           case_CHKSUM_TYPES:
+             if ((unsigned int)attrs[1] < attrdatastart)
+                attrdatastart = attrs[1];
+             break;
+           case REPOKEY_TYPE_DIRSTRARRAY:
+             for (v = attrs[1]; data->attriddata[v] ; v += 2)
+               if (data->attriddata[v + 1] < attrdatastart)
+                 attrdatastart = data->attriddata[v + 1];
+             /* FALLTHROUGH */
+           case REPOKEY_TYPE_IDARRAY:
+           case REPOKEY_TYPE_DIRNUMNUMARRAY:
+             if ((unsigned int)attrs[1] < attriddatastart)
+               attriddatastart = attrs[1];
+             break;
+           case REPOKEY_TYPE_FIXARRAY:
+           case REPOKEY_TYPE_FLEXARRAY:
+             return;
+           default:
+             break;
+           }
+       }
+    }
+#if 0
+  printf("compact_attrdata %d %d\n", entry, nentry);
+  printf("attrdatastart: %d\n", attrdatastart);
+  printf("attriddatastart: %d\n", attriddatastart);
+#endif
+  if (attrdatastart < 1024 * 1024 * 4 && attriddatastart < 1024 * 1024)
+    return;
+  for (i = entry; i < nentry; i++)
+    {
+      Id v, *attrs = data->attrs[i];
+      if (!attrs)
+       continue;
+      for (; *attrs; attrs += 2)
+       {
+         switch (data->keys[*attrs].type)
+           {
+           case REPOKEY_TYPE_STR:
+           case REPOKEY_TYPE_BINARY:
+           case_CHKSUM_TYPES:
+             attrs[1] -= attrdatastart;
+             break;
+           case REPOKEY_TYPE_DIRSTRARRAY:
+             for (v = attrs[1]; data->attriddata[v] ; v += 2)
+               data->attriddata[v + 1] -= attrdatastart;
+             /* FALLTHROUGH */
+           case REPOKEY_TYPE_IDARRAY:
+           case REPOKEY_TYPE_DIRNUMNUMARRAY:
+             attrs[1] -= attriddatastart;
+             break;
+           default:
+             break;
+           }
+       }
+    }
+  if (attrdatastart)
+    {
+      data->attrdatalen -= attrdatastart;
+      memmove(data->attrdata, data->attrdata + attrdatastart, data->attrdatalen);
+      data->attrdata = solv_extend_resize(data->attrdata, data->attrdatalen, 1, REPODATA_ATTRDATA_BLOCK);
+    }
+  if (attriddatastart)
+    {
+      data->attriddatalen -= attriddatastart;
+      memmove(data->attriddata, data->attriddata + attriddatastart, data->attriddatalen * sizeof(Id));
+      data->attriddata = solv_extend_resize(data->attriddata, data->attriddatalen, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK);
+    }
+}
+
 /* internalalize some key into incore/vincore data */
 
 static void
@@ -3078,6 +3175,11 @@ repodata_internalize(Repodata *data)
   if (!data->attrs && !data->xattrs)
     return;
 
+#if 0
+  printf("repodata_internalize %d\n", data->repodataid);
+  printf("  attr data: %d K\n", data->attrdatalen / 1024);
+  printf("  attrid data: %d K\n", data->attriddatalen / (1024 / 4));
+#endif
   newvincore.buf = data->vincore;
   newvincore.len = data->vincorelen;
 
@@ -3235,8 +3337,22 @@ fprintf(stderr, "schemadata %p\n", data->schemadata);
            }
          dp = ndp;
        }
-      if (entry >= 0 && data->attrs && data->attrs[entry])
-       data->attrs[entry] = solv_free(data->attrs[entry]);
+      if (entry >= 0 && data->attrs)
+       {
+         if (data->attrs[entry])
+           data->attrs[entry] = solv_free(data->attrs[entry]);
+         if (entry && entry % 4096 == 0 && data->nxattrs <= 2 && entry + 64 < nentry)
+           {
+             compact_attrdata(data, entry + 1, nentry);        /* try to free some memory */
+#if 0
+             printf("  attr data: %d K\n", data->attrdatalen / 1024);
+             printf("  attrid data: %d K\n", data->attriddatalen / (1024 / 4));
+             printf("  incore data: %d K\n", newincore.len / 1024);
+             printf("  sum: %d K\n", (newincore.len + data->attrdatalen + data->attriddatalen * 4) / 1024);
+             /* malloc_stats(); */
+#endif
+           }
+       }
     }
   /* free all xattrs */
   for (entry = 0; entry < data->nxattrs; entry++)
@@ -3268,6 +3384,10 @@ fprintf(stderr, "schemadata %p\n", data->schemadata);
   data->attrdatalen = 0;
   data->attriddatalen = 0;
   data->attrnum64datalen = 0;
+#if 0
+  printf("repodata_internalize %d done\n", data->repodataid);
+  printf("  incore data: %d K\n", data->incoredatalen / 1024);
+#endif
 }
 
 void