- some pieces of code for the unified lookup/search interface
[platform/upstream/libsolv.git] / src / repo.c
index b9bdc28..0a18895 100644 (file)
@@ -20,6 +20,7 @@
 #include "pool.h"
 #include "poolid_private.h"
 #include "util.h"
+#include "attr_store_p.h"
 
 #define IDARRAY_BLOCK     4095
 
@@ -41,6 +42,7 @@ repo_create(Pool *pool, const char *name)
   repo->name = name ? strdup(name) : 0;
   repo->pool = pool;
   repo->start = pool->nsolvables;
+  repo->end = pool->nsolvables;
   repo->nsolvables = 0;
   return repo;
 }
@@ -246,54 +248,56 @@ repo_reserve_ids(Repo *repo, Offset olddeps, int num)
 
 
 /*
- * remove repo from pool
+ * remove repo from pool, zero out solvables 
  * 
  */
 
 void
-repo_free(Repo *repo)
+repo_free(Repo *repo, int reuseids)
 {
   Pool *pool = repo->pool;
-  int i, nsolvables;
+  Solvable *s;
+  int i;
 
   pool_freewhatprovides(pool);
 
-  for (i = 0; i < pool->nrepos; i++)   /* find repo in pool */
+  if (reuseids && repo->end == pool->nsolvables)
     {
-      if (pool->repos[i] == repo)
-       break;
+      /* it's ok to reuse the ids. As this is the last repo, we can
+         just shrink the solvable array */
+      for (i = repo->end - 1, s = pool->solvables + i; i >= repo->start; i--, s--)
+       if (s->repo != repo)
+         break;
+      repo->end = i + 1;
+      pool->nsolvables = i + 1;
     }
+  /* zero out solvables belonging to this repo */
+  for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++)
+    if (s->repo == repo)
+      memset(s, 0, sizeof(*s));
+  for (i = 0; i < pool->nrepos; i++)   /* find repo in pool */
+    if (pool->repos[i] == repo)
+      break;
   if (i == pool->nrepos)              /* repo not in pool, return */
     return;
-
-  /* close gap
-   * all repos point into pool->solvables _relatively_ to repo->start
-   * so closing the gap only needs adaption of repo->start for all
-   * other repos.
-   */
-  
-  nsolvables = repo->nsolvables;
-  if (pool->nsolvables > repo->start + nsolvables)
-    memmove(pool->solvables + repo->start, pool->solvables + repo->start + nsolvables, (pool->nsolvables - repo->start - nsolvables) * sizeof(Solvable));
-  pool->nsolvables -= nsolvables;
-
-  for (; i < pool->nrepos - 1; i++)
-    {
-      pool->repos[i] = pool->repos[i + 1];   /* remove repo */
-      pool->repos[i]->start -= nsolvables;     /* adapt start offset of remaining repos */
-    }
-  pool->nrepos = i;
+  if (i < pool->nrepos - 1)
+    memmove(pool->repos + i, pool->repos + i + 1, (pool->nrepos - 1 - i) * sizeof(Repo *));
+  pool->nrepos--;
   repo_freedata(repo);
 }
 
 void
-pool_freeallrepos(Pool *pool)
+repo_freeallrepos(Pool *pool, int reuseids)
 {
   int i;
+
+  pool_freewhatprovides(pool);
   for (i = 0; i < pool->nrepos; i++)
     repo_freedata(pool->repos[i]);
   pool->repos = xfree(pool->repos);
   pool->nrepos = 0;
+  /* the first two solvables don't belong to a repo */
+  pool_free_solvable_block(pool, 2, pool->nsolvables - 2, reuseids);
 }
 
 Offset
@@ -441,4 +445,215 @@ repo_fix_legacy(Repo *repo, Offset provides, Offset supplements)
   return supplements;
 }
 
+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_str(Repodata *data, Id entry, Id key)
+{
+  Id schema;
+  Id id, k, *kp, *keyp;
+  unsigned char *dp;
+
+  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;
+  switch (data->keys[key].storage)
+    {
+    case KEY_STORAGE_VERTICAL_OFFSET:
+    case KEY_STORAGE_INCORE:
+      dp = data->incoredata + data->incoreoffset[entry];
+      while ((k = *keyp++) != 0)
+       {
+         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
+    }
+  return 0;
+}
+
+const char *
+repo_lookup_str(Solvable *s, Id key)
+{
+  Repo *repo = s->repo;
+  Pool *pool = repo->pool;
+  Repodata *data;
+  int i, j, n;
+
+  switch(key)
+    {
+    case SOLVABLE_NAME:
+      return id2str(pool, s->name);
+    case SOLVABLE_ARCH:
+      return id2str(pool, s->arch);
+    case SOLVABLE_EVR:
+      return id2str(pool, s->evr);
+    case SOLVABLE_VENDOR:
+      return id2str(pool, s->vendor);
+    }
+  n = s - pool->solvables;
+  for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
+    {
+      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 || data->keys[j].type == TYPE_STR))
+           return repodata_lookup_str(data, n - data->start, j);
+       }
+    }
+  return 0;
+}
+
+
+static int
+key_cmp (const void *pa, const void *pb)
+{
+  Repokey *a = (Repokey *)pa;
+  Repokey *b = (Repokey *)pb;
+  return a->name - b->name;
+}
+
+void
+repo_add_attrstore (Repo *repo, Attrstore *s, const char *location)
+{
+  unsigned i;
+  Repodata *data;
+  /* If this is meant to be the embedded attributes, make sure we don't
+     have them already.  */
+  if (!location)
+    {
+      for (i = 0; i < repo->nrepodata; i++)
+        if (repo->repodata[i].location == 0)
+         break;
+      if (i != repo->nrepodata)
+        {
+         pool_debug (repo->pool, SAT_FATAL, "embedded attribs added twice\n");
+         exit (1);
+       }
+    }
+  repo->nrepodata++;
+  repo->repodata = xrealloc (repo->repodata, repo->nrepodata * sizeof (*data));
+  data = repo->repodata + repo->nrepodata - 1;
+  memset (data, 0, sizeof (*data));
+  data->s = s;
+  data->nkeys = s->nkeys;
+  if (data->nkeys)
+    {
+      data->keys = xmalloc(data->nkeys * sizeof(data->keys[0]));
+      for (i = 1; i < data->nkeys; i++)
+        {
+          data->keys[i].name = s->keys[i].name;
+         data->keys[i].type = s->keys[i].type;
+       }
+      if (data->nkeys > 2)
+        qsort(data->keys + 1, data->nkeys - 1, sizeof(data->keys[0]), key_cmp);
+    }
+  if (location)
+    data->location = strdup(location);
+}
+
 // EOF