Improve the page eviction a bit.
authorMichael Matz <matz@suse.de>
Fri, 21 Dec 2007 11:58:38 +0000 (11:58 +0000)
committerMichael Matz <matz@suse.de>
Fri, 21 Dec 2007 11:58:38 +0000 (11:58 +0000)
Add possibility to merge attributes between entities, use it to handle
=Shr susetags headers.

src/attr_store.c
src/attr_store.h
src/attr_store_p.h
tools/repo_susetags.c

index 85978dd..8bc8dc3 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "fastlz.c"
 
-/*#define DEBUG_PAGING*/
+/* #define DEBUG_PAGING */
 
 #define BLOB_BLOCK 65535
 
@@ -272,6 +272,42 @@ add_attr_void (Attrstore *s, unsigned int entry, Id name)
   add_attr (s, entry, nv);
 }
 
+void
+merge_attrs (Attrstore *s, unsigned dest, unsigned src)
+{
+  LongNV *nv;
+  ensure_entry (s, dest);
+  nv = s->attrs[src];
+  if (nv)
+    {
+      for (; nv->key; nv++)
+        if (!find_attr (s, dest, s->keys[nv->key].name))
+         switch (s->keys[nv->key].type)
+           {
+             case TYPE_ATTR_INTLIST:
+               {
+                 unsigned len = 0;
+                 while (nv->v.intlist[len])
+                   add_attr_intlist_int (s, dest, s->keys[nv->key].name, nv->v.intlist[len++]);
+               }
+               break;
+             case TYPE_ATTR_LOCALIDS:
+               {
+                 unsigned len = 0;
+                 while (nv->v.localids[len])
+                   add_attr_localids_id (s, dest, s->keys[nv->key].name, nv->v.localids[len++]);
+               }
+               break;
+             case TYPE_ATTR_STRING:
+               add_attr_string (s, dest, s->keys[nv->key].name, nv->v.str);
+               break;
+             default:
+               add_attr (s, dest, *nv);
+               break;
+           }
+    }
+}
+
 #define pool_debug(a,b,...) fprintf (stderr, __VA_ARGS__)
 
 static Id read_id (FILE *fp, Id max);
@@ -423,6 +459,7 @@ load_page_range (Attrstore *s, unsigned int pstart, unsigned int pend)
   /* And search for cheapest space.  */
   unsigned int best_cost = -1;
   unsigned int best = 0;
+  unsigned int same_cost = 0;
   for (i = 0; i + pend - pstart < s->ncanmap; i++)
     {
       unsigned int c = cost[i];
@@ -431,10 +468,16 @@ load_page_range (Attrstore *s, unsigned int pstart, unsigned int pend)
         c += cost[i+j];
       if (c < best_cost)
         best_cost = c, best = i;
+      else if (c == best_cost)
+        same_cost++;
       /* A null cost won't become better.  */
       if (c == 0)
         break;
     }
+  /* If all places have the same cost we would thrash on slot 0.  Avoid
+     this by doing a round-robin strategy in this case.  */
+  if (same_cost == s->ncanmap - pend + pstart - 1)
+    best = s->rr_counter++ % (s->ncanmap - pend + pstart);
 
   /* So we want to map our pages from [best] to [best+pend-pstart].
      Use a very simple strategy, which doesn't make the best use of
index 657b5b6..0173e6f 100644 (file)
@@ -39,6 +39,7 @@ void add_attr_string (Attrstore *s, unsigned int entry, Id name, const char *val
 void add_attr_intlist_int (Attrstore *s, unsigned int entry, Id name, int val);
 void add_attr_localids_id (Attrstore *s, unsigned int entry, Id name, LocalId id);
 void add_attr_void (Attrstore *s, unsigned int entry, Id name);
+void merge_attrs (Attrstore *s, unsigned dest, unsigned src);
 
 const void * attr_retrieve_blob (Attrstore *s, unsigned int ofs, unsigned int len);
 
index 6258aed..49c1001 100644 (file)
@@ -53,6 +53,7 @@ struct _Attrstore
      otherwise it contains the pagenumber plus one (of the mapped page).  */
   unsigned int *mapped;
   unsigned int nmapped, ncanmap;
+  unsigned int rr_counter;
 
   Stringpool ss;
 
index 96657bd..2e3d1e5 100644 (file)
@@ -45,6 +45,8 @@ struct parsedata {
   char **sources;
   int nsources;
   int last_found_source;
+  char **share_with;
+  int nshare;
 };
 
 static Id
@@ -598,9 +600,18 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int with_attr)
            add_attr_blob (attr, last_found_pack, id_messagedel, line + 6, strlen (line + 6) + 1);
            continue;
           case CTAG('=', 'S', 'h', 'r'):
-           /* XXX Not yet handled.  Two possibilities: either include all
-              referenced data verbatim here, or write out the sharing
-              information.  */
+           if (last_found_pack >= pd.nshare)
+             {
+               if (pd.share_with)
+                 {
+                   pd.share_with = realloc (pd.share_with, (last_found_pack + 256) * sizeof (*pd.share_with));
+                   memset (pd.share_with + pd.nshare, 0, (last_found_pack + 256 - pd.nshare) * sizeof (*pd.share_with));
+                 }
+               else
+                 pd.share_with = calloc (last_found_pack + 256, sizeof (*pd.share_with));
+               pd.nshare = last_found_pack + 256;
+             }
+           pd.share_with[last_found_pack] = strdup (line + 6);
            continue;
           case CTAG('=', 'V', 'e', 'r'):
            last_found_pack = 0;
@@ -615,7 +626,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int with_attr)
     
   if (pd.sources)
     {
-      int i;
+      int i, last_found;
       for (i = 0; i < pd.nsources; i++)
         if (pd.sources[i])
          {
@@ -623,6 +634,41 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int with_attr)
            free (pd.sources[i]);
          }
       free (pd.sources);
+
+      last_found = 0;
+      for (i = 0; i < pd.nshare; i++)
+        if (pd.share_with[i])
+         {
+           if (split(pd.share_with[i], sp, 5) != 4)
+             {
+               fprintf(stderr, "Bad =Shr line: %s\n", pd.share_with[i]);
+               exit(1);
+             }
+
+           Id name = str2id(pool, sp[0], 1);
+           Id evr = makeevr(pool, join(&pd, sp[1], "-", sp[2]));
+           Id arch = str2id(pool, sp[3], 1);
+           unsigned n, nn;
+           Solvable *found = 0;
+           for (n = repo->start, nn = repo->start + last_found;
+                n < repo->end; n++, nn++)
+             {
+               if (nn >= repo->end)
+                 nn = repo->start;
+               found = pool->solvables + nn;
+               if (found->repo == repo
+                   && found->name == name
+                   && found->evr == evr
+                   && found->arch == arch)
+                 {
+                   last_found = nn - repo->start;
+                   break;
+                 }
+             }
+           if (n != repo->end)
+             merge_attrs (attr, i, last_found);
+         }
+      free (pd.share_with);
     }
   if (pd.tmp)
     free(pd.tmp);