[babl] babl: cache state between babl runs



commit 9e1f58146508dfc462ca68246582d1136ee8191d
Author: Øyvind Kolås <pippin gimp org>
Date:   Mon Nov 14 00:45:15 2016 +0100

    babl: cache state between babl runs
    
    Store the contents of discovered babl_paths between runs, for now in
    /tmp/babl.db , should move to a per-user dir to make it survive reboots.
    
    The code should also check a versioning string at the start and bail if there
    is any mismatch... since the data should be reconstructable; and more reliable
    when reconstructed than a possibly old version.

 babl/babl-fish-path.c |   31 ++++---
 babl/babl.c           |  245 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 262 insertions(+), 14 deletions(-)
---
diff --git a/babl/babl-fish-path.c b/babl/babl-fish-path.c
index bf9c520..f15d0e2 100644
--- a/babl/babl-fish-path.c
+++ b/babl/babl-fish-path.c
@@ -88,11 +88,11 @@ get_conversion_path (PathContext *pc,
                      int current_length,
                      int max_length);
 
-static char *
-create_name (char       *buf,
-             const Babl *source,
-             const Babl *destination,
-             int         is_reference);
+char *
+_babl_fish_create_name (char       *buf,
+                        const Babl *source,
+                        const Babl *destination,
+                        int         is_reference);
 
 static double legal_error (void);
 
@@ -238,11 +238,11 @@ get_conversion_path (PathContext *pc,
    }
 }
 
-static char *
-create_name (char       *buf,
-             const Babl *source,
-             const Babl *destination,
-             int         is_reference)
+char *
+_babl_fish_create_name (char       *buf,
+                        const Babl *source,
+                        const Babl *destination,
+                        int         is_reference)
 {
   /* fish names are intentionally kept short */
   snprintf (buf, BABL_MAX_NAME_LEN, "%s %p %p", "",
@@ -250,8 +250,11 @@ create_name (char       *buf,
   return buf;
 }
 
-static int
-babl_fish_path_destroy (void *data)
+int
+_babl_fish_path_destroy (void *data);
+
+int
+_babl_fish_path_destroy (void *data)
 {
   Babl *babl=data;
   if (babl->fish_path.conversion_list)
@@ -267,7 +270,7 @@ babl_fish_path (const Babl *source,
   Babl *babl = NULL;
   char name[BABL_MAX_NAME_LEN];
 
-  create_name (name, source, destination, 1);
+  _babl_fish_create_name (name, source, destination, 1);
   babl = babl_db_exist_by_name (babl_fish_db (), name);
   if (babl)
     {
@@ -279,7 +282,7 @@ babl_fish_path (const Babl *source,
 
   babl = babl_calloc (1, sizeof (BablFishPath) +
                       strlen (name) + 1);
-  babl_set_destructor (babl, babl_fish_path_destroy);
+  babl_set_destructor (babl, _babl_fish_path_destroy);
 
   babl->class_type                = BABL_FISH_PATH;
   babl->instance.id               = babl_fish_get_id (source, destination);
diff --git a/babl/babl.c b/babl/babl.c
index 0484d30..1287383 100644
--- a/babl/babl.c
+++ b/babl/babl.c
@@ -124,6 +124,244 @@ babl_dir_list (void)
   return ret;
 }
 
+static char *
+babl_fish_serialize (Babl *fish, char *dest, int n)
+{
+  switch (fish->class_type)
+  {
+    case BABL_FISH_PATH:
+      {
+        char *d = dest;
+                              
+        snprintf (d, n, "%s\n%s\n",
+        babl_get_name (fish->fish.source),
+        babl_get_name (fish->fish.destination));
+        n -= strlen (d);d += strlen (d);
+
+        snprintf (d, n, "\terror=%f", fish->fish.error);
+        n -= strlen (d);d += strlen (d);
+
+        snprintf (d, n, " processings=%i", fish->fish.processings);
+        n -= strlen (d);d += strlen (d);
+
+        snprintf (d, n, " pixels=%li", fish->fish.pixels);
+        n -= strlen (d);d += strlen (d);
+
+        snprintf (d, n, " cost=%f", fish->fish_path.cost);
+        n -= strlen (d);d += strlen (d);
+
+        snprintf (d, n, " loss=%f", fish->fish_path.loss);
+        n -= strlen (d);d += strlen (d);
+
+        snprintf (d, n, "\n");
+        n -= strlen (d);d += strlen (d);
+
+        for (int i = 0; i < fish->fish_path.conversion_list->count; i++)
+        {
+          snprintf (d, n, "\t%s\n", 
+            babl_get_name(fish->fish_path.conversion_list->items[i]  ));
+          n -= strlen (d);
+          d += strlen (d);
+        }
+      }
+      break;
+    case BABL_FISH_SIMPLE:   
+      return NULL;
+      break;
+    case BABL_FISH_REFERENCE:
+      return NULL; break;
+    default:
+      break;
+  }
+
+  return dest;
+}
+
+static const char *fish_cache_path (void)
+{
+  return "/tmp/babl.db"; // XXX: a $HOME/.cache/babl/fishes path might be better
+}
+
+static void babl_store_db (void)
+{
+  BablDb *db = babl_fish_db ();
+  int i;
+  FILE *dbfile = fopen (fish_cache_path (), "w");
+  if (!dbfile)
+    return;
+  fprintf (dbfile, "#babl 0 %i fishes\n", db->babl_list->count);
+  for (i = 0; i< db->babl_list->count; i++)
+  {
+    Babl *fish = db->babl_list->items[i];
+    char tmp[8192];
+    if (babl_fish_serialize (fish, tmp, 4096))
+      fprintf (dbfile, "%s----\n", tmp);
+  }
+  fclose (dbfile);
+}
+
+static int
+babl_file_get_contents (const char  *path,
+                        char       **contents,
+                        long        *length,
+                        void        *error)
+{
+  FILE *file;
+  long  size;
+  char *buffer;
+
+  file = fopen (path,"rb");
+
+  if (!file)
+    return -1;
+
+  fseek (file, 0, SEEK_END);
+  size = ftell (file);
+  if (length) *length = size;
+  rewind (file);
+  buffer = malloc(size + 8);
+
+  if (!buffer)
+    {
+      fclose(file);
+      return -1;
+    }
+
+  size -= fread (buffer, 1, size, file);
+  if (size)
+    {
+      fclose (file);
+      free (buffer);
+      return -1;
+    }
+  fclose (file);
+  *contents = buffer;
+  return 0;
+}
+
+int
+_babl_fish_path_destroy (void *data);
+
+char *
+_babl_fish_create_name (char       *buf,
+                        const Babl *source,
+                        const Babl *destination,
+                        int         is_reference);
+
+static void babl_init_db (const char *path)
+{
+  long  length = -1;
+  char  seps[] = "\n";
+  Babl *babl   = NULL;
+  char *contents = NULL;
+  char *token;
+  char *tokp;
+  const Babl  *from_format = NULL;
+  const Babl  *to_format   = NULL;
+#ifdef _WIN32  // XXX: fixme - make this work on windows
+  return;
+#endif
+
+  babl_file_get_contents (path, &contents, &length, NULL);
+  if (!contents)
+    return;
+
+  token = strtok_r (contents, seps, &tokp);
+  while( token != NULL )
+    {
+      switch (token[0])
+      {
+        case '-': /* finalize */
+          //fprintf (stderr, "%p %p\n", from_format, to_format);
+          if (babl)
+            babl_db_insert (babl_fish_db(), babl);
+          from_format = NULL;
+          to_format = NULL;
+          babl=NULL;
+          break;
+        case '#':
+          break;
+        case '\t':
+          if (strchr (token, '='))
+          {
+            char seps2[] = " ";
+            char *tokp2;
+            char *token2;
+            char name[4096];
+
+            _babl_fish_create_name (name, from_format, to_format, 1);
+            babl = babl_db_exist_by_name (babl_fish_db (), name);
+            if (babl)
+            {
+              fprintf (stderr, "%s:%i: loading of cache failed\n",
+                              __FUNCTION__, __LINE__);
+              return;
+            }
+
+            babl = babl_calloc (1, sizeof (BablFishPath) +
+                      strlen (name) + 1);
+            babl_set_destructor (babl, _babl_fish_path_destroy);
+
+            babl->class_type     = BABL_FISH_PATH;
+            babl->instance.id    = babl_fish_get_id (from_format, to_format);
+            babl->instance.name  = ((char *) babl) + sizeof (BablFishPath);
+            strcpy (babl->instance.name, name);
+            babl->fish.source               = from_format;
+            babl->fish.destination          = to_format;
+            babl->fish_path.conversion_list = babl_list_init_with_size (10);
+
+            token2 = strtok_r (&token[1], seps2, &tokp2);
+            while( token2 != NULL )
+            {
+              if (!strncmp (token2, "error=", 6))
+              {
+                babl->fish.error = strtod (token2 + 6, NULL);
+              }
+              else if (!strncmp (token2, "cost=", 5))
+              {
+                babl->fish_path.cost = strtod (token2 + 5, NULL);
+              }
+              else if (!strncmp (token2, "loss=", 5))
+              {
+                babl->fish_path.loss = strtod (token2 + 5, NULL);
+              }
+              else if (!strncmp (token2, "pixels=", 7))
+              {
+                babl->fish.pixels = strtol (token2 + 7, NULL, 10);
+              }
+              else if (!strncmp (token2, "processings=", 12))
+              {
+                babl->fish.processings = strtol (token2 + 12, NULL, 10);
+              }
+              token2 = strtok_r (NULL, seps2, &tokp2);
+            }
+          }
+          else
+          {
+            Babl *conv =
+                    (void*)babl_db_find(babl_conversion_db(), &token[1]);
+            if (!conv)
+            {
+              return;
+            }
+            else
+              babl_list_insert_last (babl->fish_path.conversion_list, conv);
+          }
+          break;
+        default:
+          if (!from_format)
+            from_format = babl_format (token);
+          else
+            to_format = babl_format (token);
+
+          break;
+      }
+      token = strtok_r (NULL, seps, &tokp);
+    }
+  if (contents)
+    free (contents);
+}
+
 void
 babl_init (void)
 {
@@ -150,6 +388,8 @@ babl_init (void)
       dir_list = babl_dir_list ();
       babl_extension_load_dir_list (dir_list);
       babl_free (dir_list);
+
+      babl_init_db (fish_cache_path());
     }
 }
 
@@ -158,6 +398,11 @@ babl_exit (void)
 {
   if (!-- ref_count)
     {
+#ifdef _WIN32  // XXX: fixme - make this work on windows
+#else
+      babl_store_db ();
+#endif
+
       if (getenv ("BABL_STATS"))
         {
           char  logfile_name[] = "/tmp/babl-stats.html";


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]