support medianr in lookup_deltalocation, change lookup_location to return medianr...
[platform/upstream/libsolv.git] / src / pool.c
index 89c6c1a..4b6ab43 100644 (file)
@@ -54,25 +54,34 @@ pool_create(void)
   pool->nsolvables = 2;
   memset(pool->solvables, 0, 2 * sizeof(Solvable));
 
+  queue_init(&pool->vendormap);
+
+#if defined(DEBIAN)
+  pool->disttype = DISTTYPE_DEB;
+  pool->noarchid = ARCH_ALL;
+#elif defined(ARCHLINUX)
+  pool->disttype = DISTTYPE_ARCH;
+  pool->noarchid = ARCH_ANY;
+#else
+  pool->disttype = DISTTYPE_RPM;
+  pool->noarchid = ARCH_NOARCH;
+#endif
+
   /* initialize the system solvable */
   s = pool->solvables + SYSTEMSOLVABLE;
   s->name = SYSTEM_SYSTEM;
-  s->arch = ARCH_NOARCH;
+  s->arch = pool->noarchid;
   s->evr = ID_EMPTY;
 
-  queue_init(&pool->vendormap);
-
   pool->debugmask = SOLV_DEBUG_RESULT; /* FIXME */
 #ifdef FEDORA
   pool->obsoleteusescolors = 1;
 #endif
-#ifdef DEBIAN 
-  pool->allowselfconflicts = 1;
-  pool->disttype = DISTTYPE_DEB;
-#endif
 #ifdef RPM5
+  pool->forbidselfconflicts = 1;
   pool->obsoleteusesprovides = 1;
   pool->implicitobsoleteusesprovides = 1;
+  pool->havedistepoch = 1;
 #endif
   return pool;
 }
@@ -100,6 +109,8 @@ pool_free(Pool *pool)
     free((char *)pool->languages[i]);
   solv_free(pool->languages);
   solv_free(pool->languagecache);
+  solv_free(pool->errstr);
+  solv_free(pool->rootdir);
   solv_free(pool);
 }
 
@@ -124,9 +135,75 @@ void
 pool_setdisttype(Pool *pool, int disttype)
 {
   pool->disttype = disttype;
+  if (disttype == DISTTYPE_RPM)
+    pool->noarchid = ARCH_NOARCH;
+  if (disttype == DISTTYPE_DEB)
+    pool->noarchid = ARCH_ALL;
+  if (disttype == DISTTYPE_ARCH)
+    pool->noarchid = ARCH_ANY;
+  pool->solvables[SYSTEMSOLVABLE].arch = pool->noarchid;
 }
 #endif
 
+int
+pool_get_flag(Pool *pool, int flag)
+{
+  switch (flag)
+    {
+    case POOL_FLAG_PROMOTEEPOCH:
+      return pool->promoteepoch;
+    case POOL_FLAG_FORBIDSELFCONFLICTS:
+      return pool->forbidselfconflicts;
+    case POOL_FLAG_OBSOLETEUSESPROVIDES:
+      return pool->obsoleteusesprovides;
+    case POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES:
+      return pool->implicitobsoleteusesprovides;
+    case POOL_FLAG_OBSOLETEUSESCOLORS:
+      return pool->obsoleteusescolors;
+    case POOL_FLAG_NOINSTALLEDOBSOLETES:
+      return pool->noinstalledobsoletes;
+    case POOL_FLAG_HAVEDISTEPOCH:
+      return pool->havedistepoch;
+    default:
+      break;
+    }
+  return -1;
+}
+
+int
+pool_set_flag(Pool *pool, int flag, int value)
+{
+  int old = pool_get_flag(pool, flag);
+  switch (flag)
+    {
+    case POOL_FLAG_PROMOTEEPOCH:
+      pool->promoteepoch = value;
+      break;
+    case POOL_FLAG_FORBIDSELFCONFLICTS:
+      pool->forbidselfconflicts = value;
+      break;
+    case POOL_FLAG_OBSOLETEUSESPROVIDES:
+      pool->obsoleteusesprovides = value;
+      break;
+    case POOL_FLAG_IMPLICITOBSOLETEUSESPROVIDES:
+      pool->implicitobsoleteusesprovides = value;
+      break;
+    case POOL_FLAG_OBSOLETEUSESCOLORS:
+      pool->obsoleteusescolors = value;
+      break;
+    case POOL_FLAG_NOINSTALLEDOBSOLETES:
+      pool->noinstalledobsoletes = value;
+      break;
+    case POOL_FLAG_HAVEDISTEPOCH:
+      pool->havedistepoch = value;
+      break;
+    default:
+      break;
+    }
+  return old;
+}
+
+
 Id
 pool_add_solvable(Pool *pool)
 {
@@ -181,10 +258,6 @@ pool_shrink_whatprovides_sortcmp(const void *ap, const void *bp, void *dp)
   ob = pool->whatprovides[*(Id *)bp];
   if (oa == ob)
     return *(Id *)ap - *(Id *)bp;
-  if (!oa)
-    return -1;
-  if (!ob)
-    return 1;
   da = pool->whatprovidesdata + oa;
   db = pool->whatprovidesdata + ob;
   while (*db)
@@ -204,7 +277,7 @@ pool_shrink_whatprovides_sortcmp(const void *ap, const void *bp, void *dp)
 static void
 pool_shrink_whatprovides(Pool *pool)
 {
-  Id i, id;
+  Id i, n, id;
   Id *sorted;
   Id lastid, *last, *dp, *lp;
   Offset o;
@@ -213,17 +286,17 @@ pool_shrink_whatprovides(Pool *pool)
   if (pool->ss.nstrings < 3)
     return;
   sorted = solv_malloc2(pool->ss.nstrings, sizeof(Id));
-  for (id = 0; id < pool->ss.nstrings; id++)
-    sorted[id] = id;
-  solv_sort(sorted + 1, pool->ss.nstrings - 1, sizeof(Id), pool_shrink_whatprovides_sortcmp, pool);
+  for (i = id = 0; id < pool->ss.nstrings; id++)
+    if (pool->whatprovides[id] && pool->whatprovides[id] != 1)
+      sorted[i++] = id;
+  n = i;
+  solv_sort(sorted, n, sizeof(Id), pool_shrink_whatprovides_sortcmp, pool);
   last = 0;
   lastid = 0;
-  for (i = 1; i < pool->ss.nstrings; i++)
+  for (i = 0; i < n; i++)
     {
       id = sorted[i];
       o = pool->whatprovides[id];
-      if (o == 0 || o == 1)
-       continue;
       dp = pool->whatprovidesdata + o;
       if (last)
        {
@@ -300,8 +373,11 @@ pool_createwhatprovides(Pool *pool)
   unsigned int now;
 
   now = solv_timems(0);
-  POOL_DEBUG(SOLV_DEBUG_STATS, "number of solvables: %d\n", pool->nsolvables);
+  POOL_DEBUG(SOLV_DEBUG_STATS, "number of solvables: %d, memory used: %d K\n", pool->nsolvables, pool->nsolvables * (int)sizeof(Solvable) / 1024);
   POOL_DEBUG(SOLV_DEBUG_STATS, "number of ids: %d + %d\n", pool->ss.nstrings, pool->nrels);
+  POOL_DEBUG(SOLV_DEBUG_STATS, "string memory used: %d K array + %d K data,  rel memory used: %d K array\n", pool->ss.nstrings / (1024 / (int)sizeof(Id)), pool->ss.sstrings / 1024, pool->nrels * (int)sizeof(Reldep) / 1024);
+  if (pool->ss.stringhashmask || pool->relhashmask)
+    POOL_DEBUG(SOLV_DEBUG_STATS, "string hash memory: %d K, rel hash memory : %d K\n", (pool->ss.stringhashmask + 1) / (int)(1024/sizeof(Id)), (pool->relhashmask + 1) / (int)(1024/sizeof(Id)));
 
   pool_freeidhashes(pool);     /* XXX: should not be here! */
   pool_freewhatprovides(pool);
@@ -452,7 +528,7 @@ pool_queuetowhatprovides(Pool *pool, Queue *q)
 
 #if defined(MULTI_SEMANTICS)
 # define EVRCMP_DEPCMP (pool->disttype == DISTTYPE_DEB ? EVRCMP_COMPARE : EVRCMP_MATCH_RELEASE)
-#elif defined(DEBIAN_SEMANTICS)
+#elif defined(DEBIAN)
 # define EVRCMP_DEPCMP EVRCMP_COMPARE
 #else
 # define EVRCMP_DEPCMP EVRCMP_MATCH_RELEASE
@@ -474,7 +550,10 @@ pool_match_nevr_rel(Pool *pool, Solvable *s, Id d)
        {
        case REL_ARCH:
          if (s->arch != evr)
-           return 0;
+           {
+             if (evr != ARCH_SRC || s->arch != ARCH_NOSRC)
+               return 0;
+           }
          return pool_match_nevr(pool, s, name);
        case REL_OR:
          if (pool_match_nevr(pool, s, name))
@@ -492,15 +571,26 @@ pool_match_nevr_rel(Pool *pool, Solvable *s, Id d)
   if (!pool_match_nevr(pool, s, name))
     return 0;
   if (evr == s->evr)
-    return flags & 2 ? 1 : 0;
+    return (flags & REL_EQ) ? 1 : 0;
   if (!flags)
     return 0;
   if (flags == 7)
     return 1;
-  if (flags != 2 && flags != 5)
-    flags ^= 5;
-  if ((flags & (1 << (1 + pool_evrcmp(pool, s->evr, evr, EVRCMP_DEPCMP)))) != 0)
-    return 1;
+  switch (pool_evrcmp(pool, s->evr, evr, EVRCMP_DEPCMP))
+    {
+    case -2:
+      return 1;
+    case -1:
+      return (flags & REL_LT) ? 1 : 0;
+    case 0:
+      return (flags & REL_EQ) ? 1 : 0;
+    case 1:
+      return (flags & REL_GT) ? 1 : 0;
+    case 2:
+      return (flags & REL_EQ) ? 1 : 0;
+    default:
+      break;
+    }
   return 0;
 }
 
@@ -512,18 +602,24 @@ pool_match_flags_evr(Pool *pool, int pflags, Id pevr, int flags, int evr)
     return 0;
   if (flags == 7 || pflags == 7)
     return 1;          /* rel provides every version */
-  if ((pflags & flags & 5) != 0)
+  if ((pflags & flags & (REL_LT | REL_GT)) != 0)
     return 1;          /* both rels show in the same direction */
   if (pevr == evr)
+    return (flags & pflags & REL_EQ) ? 1 : 0;
+  switch (pool_evrcmp(pool, pevr, evr, EVRCMP_DEPCMP))
     {
-      if ((pflags & flags & 2) != 0)
-       return 1;       /* both have '=', match */
-    }
-  else
-    {
-      int f = flags == 5 ? 5 : flags == 2 ? pflags : (flags ^ 5) & (pflags | 5);
-      if ((f & (1 << (1 + pool_evrcmp(pool, pevr, evr, EVRCMP_DEPCMP)))) != 0)
-       return 1;
+    case -2:
+      return (pflags & REL_EQ) ? 1 : 0;
+    case -1:
+      return (flags & REL_LT) || (pflags & REL_GT) ? 1 : 0;
+    case 0:
+      return (flags & pflags & REL_EQ) ? 1 : 0;
+    case 1:
+      return (flags & REL_GT) || (pflags & REL_LT) ? 1 : 0;
+    case 2:
+      return (flags & REL_EQ) ? 1 : 0;
+    default:
+      break;
     }
   return 0;
 }
@@ -648,12 +744,14 @@ pool_addrelproviders(Pool *pool, Id d)
           * we have to iterate over the solvables as src packages do not
           * provide anything, thus they are not indexed in our
           * whatprovides hash */
-         if (evr == ARCH_SRC)
+         if (evr == ARCH_SRC || evr == ARCH_NOSRC)
            {
              Solvable *s;
              for (p = 1, s = pool->solvables + p; p < pool->nsolvables; p++, s++)
                {
-                 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
+                 if (!s->repo)
+                   continue;
+                 if (s->arch != evr && s->arch != ARCH_NOSRC)
                    continue;
                  if (pool_match_nevr(pool, s, name))
                    queue_push(&plist, p);
@@ -724,14 +822,14 @@ pool_addrelproviders(Pool *pool, Id d)
          pidp = s->repo->idarraydata + s->provides;
          while ((pid = *pidp++) != 0)
            {
-             if (pid == name)
+             if (!ISRELDEP(pid))
                {
+                 if (pid != name)
+                   continue;           /* wrong provides name */
                  if (pool->disttype == DISTTYPE_DEB)
                    continue;           /* unversioned provides can never match versioned deps */
                  break;
                }
-             if (!ISRELDEP(pid))
-               continue;               /* wrong provides name */
              prd = GETRELDEP(pool, pid);
              if (prd->name != name)
                continue;               /* wrong provides name */
@@ -780,15 +878,56 @@ pool_debug(Pool *pool, int type, const char *format, ...)
       return;
     }
   vsnprintf(buf, sizeof(buf), format, args);
+  va_end(args);
   pool->debugcallback(pool, pool->debugcallbackdata, type, buf);
 }
 
+int
+pool_error(Pool *pool, int ret, const char *format, ...)
+{
+  va_list args;
+  int l;
+  va_start(args, format);
+  if (!pool->errstr)
+    {
+      pool->errstra = 1024;
+      pool->errstr = solv_malloc(pool->errstra);
+    }
+  if (!*format)
+    {
+      *pool->errstr = 0;
+      l = 0;
+    }
+  else
+    l = vsnprintf(pool->errstr, pool->errstra, format, args);
+  va_end(args);
+  if (l >= 0 && l + 1 > pool->errstra)
+    {
+      pool->errstra = l + 256;
+      pool->errstr = solv_realloc(pool->errstr, pool->errstra);
+      va_start(args, format);
+      l = vsnprintf(pool->errstr, pool->errstra, format, args);
+      va_end(args);
+    }
+  if (l < 0)
+    strcpy(pool->errstr, "unknown error");
+  if (pool->debugmask & SOLV_ERROR)
+    pool_debug(pool, SOLV_ERROR, "%s\n", pool->errstr);
+  return ret;
+}
+
+char *
+pool_errstr(Pool *pool)
+{
+  return pool->errstr ? pool->errstr : "no error";
+}
+
 void
 pool_setdebuglevel(Pool *pool, int level)
 {
   int mask = SOLV_DEBUG_RESULT;
   if (level > 0)
-    mask |= SOLV_DEBUG_STATS|SOLV_DEBUG_ANALYZE|SOLV_DEBUG_UNSOLVABLE|SOLV_DEBUG_SOLVER|SOLV_DEBUG_TRANSACTION;
+    mask |= SOLV_DEBUG_STATS|SOLV_DEBUG_ANALYZE|SOLV_DEBUG_UNSOLVABLE|SOLV_DEBUG_SOLVER|SOLV_DEBUG_TRANSACTION|SOLV_ERROR;
   if (level > 1)
     mask |= SOLV_DEBUG_JOB|SOLV_DEBUG_SOLUTIONS|SOLV_DEBUG_POLICY;
   if (level > 2)
@@ -1078,7 +1217,7 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru
 }
 
 void
-pool_addfileprovides_queue(Pool *pool, Queue *idq)
+pool_addfileprovides_queue(Pool *pool, Queue *idq, Queue *idqinst)
 {
   Solvable *s;
   Repo *installed, *repo;
@@ -1096,6 +1235,8 @@ pool_addfileprovides_queue(Pool *pool, Queue *idq)
 
   if (idq)
     queue_empty(idq);
+  if (idqinst)
+    queue_empty(idqinst);
   isfp = installed ? &isf : 0;
   for (i = 1, s = pool->solvables + i; i < pool->nsolvables; i++, s++)
     {
@@ -1131,6 +1272,9 @@ pool_addfileprovides_queue(Pool *pool, Queue *idq)
       if (idq)
         for (i = 0; i < sf.nfiles; i++)
          queue_push(idq, sf.ids[i]);
+      if (idqinst)
+        for (i = 0; i < sf.nfiles; i++)
+         queue_push(idqinst, sf.ids[i]);
       solv_free(sf.ids);
       for (i = 0; i < sf.nfiles; i++)
        {
@@ -1148,6 +1292,9 @@ pool_addfileprovides_queue(Pool *pool, Queue *idq)
 #endif
       if (installed)
         pool_addfileprovides_search(pool, &cbd, &isf, installed);
+      if (installed && idqinst)
+        for (i = 0; i < isf.nfiles; i++)
+         queue_pushunique(idqinst, isf.ids[i]);
       solv_free(isf.ids);
       for (i = 0; i < isf.nfiles; i++)
        {
@@ -1165,7 +1312,7 @@ pool_addfileprovides_queue(Pool *pool, Queue *idq)
 void
 pool_addfileprovides(Pool *pool)
 {
-  pool_addfileprovides_queue(pool, 0);
+  pool_addfileprovides_queue(pool, 0, 0);
 }
 
 void
@@ -1625,7 +1772,7 @@ pool_calc_installsizechange(Pool *pool, Map *installedmap)
        continue;
       if (!MAPTST(installedmap, sp))
        continue;
-      change += solvable_lookup_num(s, SOLVABLE_INSTALLSIZE, 0);
+      change += solvable_lookup_sizek(s, SOLVABLE_INSTALLSIZE, 0);
     }
   if (oldinstalled)
     {
@@ -1633,7 +1780,7 @@ pool_calc_installsizechange(Pool *pool, Map *installedmap)
        {
          if (MAPTST(installedmap, sp))
            continue;
-         change -= solvable_lookup_num(s, SOLVABLE_INSTALLSIZE, 0);
+         change -= solvable_lookup_sizek(s, SOLVABLE_INSTALLSIZE, 0);
        }
     }
   return change;
@@ -1877,12 +2024,12 @@ pool_lookup_id(Pool *pool, Id entry, Id keyname)
   return solvable_lookup_id(pool->solvables + entry, keyname);
 }
 
-unsigned int
-pool_lookup_num(Pool *pool, Id entry, Id keyname, unsigned int notfound)
+unsigned long long
+pool_lookup_num(Pool *pool, Id entry, Id keyname, unsigned long long notfound)
 {
   if (entry == SOLVID_POS && pool->pos.repo)
     {
-      unsigned int value;
+      unsigned long long value;
       if (repodata_lookup_num(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, &value))
        return value;
       return notfound;
@@ -1925,6 +2072,21 @@ pool_lookup_checksum(Pool *pool, Id entry, Id keyname, Id *typep)
   return solvable_lookup_checksum(pool->solvables + entry, keyname, typep);
 }
 
+const char *
+pool_lookup_deltalocation(Pool *pool, Id entry, unsigned int *medianrp)
+{
+  const char *loc;
+  if (medianrp)
+    *medianrp = 0;
+  if (entry != SOLVID_POS)
+    return 0;
+  loc = pool_lookup_str(pool, entry, DELTA_LOCATION_DIR);
+  loc = pool_tmpjoin(pool, loc, loc ? "/" : 0, pool_lookup_str(pool, entry, DELTA_LOCATION_NAME));
+  loc = pool_tmpappend(pool, loc, "-", pool_lookup_str(pool, entry, DELTA_LOCATION_EVR));
+  loc = pool_tmpappend(pool, loc, ".", pool_lookup_str(pool, entry, DELTA_LOCATION_SUFFIX));
+  return loc;
+}
+
 void
 pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts)
 {
@@ -1957,4 +2119,37 @@ pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts)
     pool_freeidhashes(pool);
 }
 
+char *
+pool_prepend_rootdir(Pool *pool, const char *path)
+{
+  if (!path)
+    return 0;
+  if (!pool->rootdir)
+    return solv_strdup(path);
+  return solv_dupjoin(pool->rootdir, "/", *path == '/' ? path + 1 : path);
+}
+
+const char *
+pool_prepend_rootdir_tmp(Pool *pool, const char *path)
+{
+  if (!path)
+    return 0;
+  if (!pool->rootdir)
+    return path;
+  return pool_tmpjoin(pool, pool->rootdir, "/", *path == '/' ? path + 1 : path);
+}
+
+void
+pool_set_rootdir(Pool *pool, const char *rootdir)
+{
+  solv_free(pool->rootdir);
+  pool->rootdir = solv_strdup(rootdir);
+}
+
+const char *
+pool_get_rootdir(Pool *pool)
+{
+  return pool->rootdir;
+}
+
 /* EOF */