gegl r2204 - in trunk: . gegl/buffer



Author: ok
Date: Sun Apr 20 12:10:23 2008
New Revision: 2204
URL: http://svn.gnome.org/viewvc/gegl?rev=2204&view=rev

Log:
* gegl/buffer/gegl-buffer-access.c: (gegl_buffer_flush): invoke the
flush command for the tile infrastructure.
* gegl/buffer/gegl-buffer-index.h: include guards, and added some of
the new private functions from gegl-buffer-save.c
* gegl/buffer/gegl-buffer-load.c: (seekto), (read_header),
(read_block), (gegl_buffer_load): made the loader a bit more tolerant
to nonsequential files, not fully tested.
* gegl/buffer/gegl-buffer-private.h: moved gegl_buffer_flush() ..
* gegl/buffer/gegl-buffer.h: .. here
* gegl/buffer/gegl-buffer-save.c: (gegl_tile_entry_new),
(gegl_tile_entry_destroy), (save_info_destroy),
(gegl_buffer_header_init), (gegl_buffer_save): made some of the struct
preparation code sharable.
* gegl/buffer/gegl-tile-backend-file.c: make use of shared
types from gegl-buffer-index.h for the tile index.
* gegl/buffer/gegl-tile-handler-cache.c: (command): tell all tiles in
our cache to store themself.
* gegl/buffer/gegl-tile-handler-log.c: added flush command.
* gegl/buffer/gegl-tile-source.h: added flush command.


Modified:
   trunk/ChangeLog
   trunk/gegl/buffer/gegl-buffer-access.c
   trunk/gegl/buffer/gegl-buffer-index.h
   trunk/gegl/buffer/gegl-buffer-load.c
   trunk/gegl/buffer/gegl-buffer-private.h
   trunk/gegl/buffer/gegl-buffer-save.c
   trunk/gegl/buffer/gegl-buffer.h
   trunk/gegl/buffer/gegl-tile-backend-file.c
   trunk/gegl/buffer/gegl-tile-handler-cache.c
   trunk/gegl/buffer/gegl-tile-handler-log.c
   trunk/gegl/buffer/gegl-tile-source.h

Modified: trunk/gegl/buffer/gegl-buffer-access.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-access.c	(original)
+++ trunk/gegl/buffer/gegl-buffer-access.c	Sun Apr 20 12:10:23 2008
@@ -33,6 +33,9 @@
 #include "gegl-sampler-linear.h"
 #include "gegl-sampler-cubic.h"
 
+#if ENABLE_MP
+GStaticRecMutex mutex = G_STATIC_REC_MUTEX_INIT;
+#endif
 
 
 #ifdef BABL
@@ -291,6 +294,8 @@
       g_object_unref (buffer->hot_tile);
       buffer->hot_tile = NULL;
     }
+  gegl_tile_source_command (GEGL_TILE_SOURCE (buffer),
+                            GEGL_TILE_FLUSH, 0,0,0,NULL);
 }
 
 

Modified: trunk/gegl/buffer/gegl-buffer-index.h
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-index.h	(original)
+++ trunk/gegl/buffer/gegl-buffer-index.h	Sun Apr 20 12:10:23 2008
@@ -1,3 +1,5 @@
+#ifndef __GEGL_BUFFER_INDEX_H
+#define __GEGL_BUFFER_INDEX_H
 /* File format building blocks 
 
 GeglBuffer on disk representation
@@ -11,7 +13,6 @@
 #define GEGL_FLAG_TILE_IS_FREE 4
 #define GEGL_FLAG_TILE_FREE    (GEGL_FLAG_TILE|GEGL_FLAG_TILE_IS_FREE)
 
-
 /*
  * This header is the first 256 bytes of the GEGL buffer.
  */
@@ -54,15 +55,31 @@
 /* The header is followed by elements describing tiles stored in the swap,
  */
 typedef struct {
-  GeglBufferBlock blockdef; /* The block definition for this tile entry   */
-  gint32  x;                /* upperleft of tile % tile_width coordinates */
+  GeglBufferBlock block; /* The block definition for this tile entry   */
+  gint32  x;             /* upperleft of tile % tile_width coordinates */
   gint32  y;           
 
-  gint32  z;                /* mipmap subdivision level of tile (0=100%)  */
-  guint64 offset;           /* offset into file for this tile             */
+  gint32  z;             /* mipmap subdivision level of tile (0=100%)  */
+  guint64 offset;        /* offset into file for this tile             */
   guint32 padding[23];
 } GeglBufferTile;
 
+GeglBufferTile *
+gegl_tile_entry_new (gint x,
+                     gint y,
+                     gint z);
+
+
+void
+gegl_buffer_header_init (GeglBufferHeader *header,
+                         gint              tile_width,
+                         gint              tile_height,
+                         gint              bpp,
+                         Babl*             format);
+
+void
+gegl_tile_entry_destroy (GeglBufferTile *entry);
+
 /* A convenience union to allow quick and simple casting */
 typedef union {
   guint32           length;
@@ -87,3 +104,4 @@
   struct_check_padding (GeglBufferTile, 128);}
 #define GEGL_BUFFER_SANITY {static gboolean done=FALSE;if(!done){GEGL_BUFFER_STRUCT_CHECK_PADDING;done=TRUE;}}
 
+#endif

Modified: trunk/gegl/buffer/gegl-buffer-load.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-load.c	(original)
+++ trunk/gegl/buffer/gegl-buffer-load.c	Sun Apr 20 12:10:23 2008
@@ -42,6 +42,8 @@
 #include "gegl-region.h"
 #include "gegl-buffer-index.h"
 
+#include <glib/gprintf.h>
+
 typedef struct
 {
   GeglBufferHeader header;
@@ -56,6 +58,13 @@
   gboolean         got_header;
 } LoadInfo;
 
+static void seekto(LoadInfo *info, gint pos)
+{
+  info->pos = pos;
+  g_printf ("seek to %i\n", pos);
+  g_seekable_seek (G_SEEKABLE (info->i), info->pos, G_SEEK_SET, NULL, NULL);
+}
+
 static GeglBufferItem *read_header (LoadInfo *info)
 {
   GeglBufferBlock block;
@@ -65,7 +74,7 @@
 
   if (info->pos != 0)
     {
-      g_print ("%s must seek\n", G_STRFUNC);
+      seekto (info, 0);
     }
 
   info->pos += g_input_stream_read (info->i, &block, sizeof (GeglBufferBlock), NULL, NULL);
@@ -90,6 +99,8 @@
                        NULL, NULL);
     }
   info->next_block = ret->block.next;
+
+  g_printf ("header: next:%i\n", (guint)ret->block.next);
   return ret;
 }
 
@@ -99,9 +110,11 @@
   GeglBufferBlock block;
   GeglBufferItem *ret;
 
+  if (!info->next_block)
+    return NULL;
   if (info->pos != info->next_block)
     {
-      g_print ("must seek\n");
+      seekto (info, info->next_block);
     }
 
   info->pos+= g_input_stream_read (info->i, &block, sizeof (GeglBufferBlock),
@@ -202,11 +215,15 @@
 
   /* load the index */
   {
-    gint i;
-    for (i = 0; i < info->header.entry_count; i++)
+    GeglBufferItem *item; /* = read_block (info);*/
+    for (item = read_block (info); item; item = read_block (info))
       {
-        GeglBufferItem *item = read_block (info);
         g_assert (item);
+        g_print ("%i, %i, %i offset:%i next:%i\n", item->tile.x,
+                                    item->tile.y,
+                                    item->tile.z,
+                                    (guint)item->tile.offset,
+                                    (guint)item->block.next);
         info->tiles = g_list_prepend (info->tiles, item);
       }
     info->tiles = g_list_reverse (info->tiles);
@@ -235,7 +252,7 @@
 
         if (info->pos != entry->offset)
           {
-            g_warning ("%s must seek", G_STRFUNC);
+            seekto (info, entry->offset);
           }
 
         info->pos += g_input_stream_read (info->i, data, info->tile_size,

Modified: trunk/gegl/buffer/gegl-buffer-private.h
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-private.h	(original)
+++ trunk/gegl/buffer/gegl-buffer-private.h	Sun Apr 20 12:10:23 2008
@@ -77,10 +77,6 @@
                                        const gchar         *path,
                                        const GeglRectangle *roi);
 
-/* flush any unwritten data (flushes the hot-cache of a single
- * tile used by gegl_buffer_set for 1x1 pixel sized rectangles
- */
-void           gegl_buffer_flush      (GeglBuffer *buffer);
 
 const gchar *  gegl_swap_dir          (void);
 

Modified: trunk/gegl/buffer/gegl-buffer-save.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-save.c	(original)
+++ trunk/gegl/buffer/gegl-buffer-save.c	Sun Apr 20 12:10:23 2008
@@ -58,12 +58,14 @@
 } SaveInfo;
 
 
-static GeglBufferTile *
-tile_entry_new (gint x,
-                gint y,
-                gint z)
+GeglBufferTile *
+gegl_tile_entry_new (gint x,
+                     gint y,
+                     gint z)
 {
   GeglBufferTile *entry = g_slice_new0 (GeglBufferTile);
+  entry->block.flags = GEGL_FLAG_TILE;
+  entry->block.length = sizeof (GeglBufferTile);
 
   entry->x = x;
   entry->y = y;
@@ -71,8 +73,8 @@
   return entry;
 }
 
-static void
-tile_entry_destroy (GeglBufferTile *entry)
+void
+gegl_tile_entry_destroy (GeglBufferTile *entry)
 {
   g_slice_free (GeglBufferTile, entry);
 }
@@ -116,7 +118,7 @@
     {
       GList *iter;
       for (iter = info->tiles; iter; iter = iter->next)
-        tile_entry_destroy (iter->data);
+        gegl_tile_entry_destroy (iter->data);
       g_list_free (info->tiles);
       info->tiles = NULL;
     }
@@ -162,6 +164,32 @@
 }
 
 
+void
+gegl_buffer_header_init (GeglBufferHeader *header,
+                         gint              tile_width,
+                         gint              tile_height,
+                         gint              bpp,
+                         Babl*             format)
+{
+  strcpy (header->magic, "GEGL");
+
+  header->flags = GEGL_FLAG_HEADER;
+
+  header->tile_width  = tile_width;
+  header->tile_height = tile_height;
+  header->bytes_per_pixel = bpp;
+  header->width = 256;
+  header->height = 256;
+  {
+    gchar buf[64];
+    g_snprintf (buf, 64, "%s%c\n%iÃ%i %ibpp\n\n\n\n\n\n\n\n\n\n", 
+          format->instance.name, 0,
+          header->tile_width,
+          header->tile_height,
+          header->bytes_per_pixel);
+    memcpy ((header->description), buf, 64);
+  }
+}
 
 void
 gegl_buffer_save (GeglBuffer          *buffer,
@@ -171,47 +199,27 @@
   SaveInfo *info = g_slice_new0 (SaveInfo);
 
   glong prediction = 0; 
+  gint bpp;
 
   GEGL_BUFFER_SANITY;
 
-  strcpy (info->header.magic, "GEGL");
-
   /* a header should follow the same structure as a blockdef with
    * respect to the flags and next offsets, thus this is a valid
    * cast shortcut.
    */
-  info->header.flags = GEGL_FLAG_HEADER;
-  info->header.next = (prediction += sizeof (GeglBufferHeader));
 
   info->path = g_strdup (path);
   info->file = g_file_new_for_commandline_arg (info->path);
   info->o    = G_OUTPUT_STREAM (g_file_replace (info->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
-#if 0
-  if (info->fd == -1)
-    {
-      gchar *name = g_filename_display_name (info->path);
-
-      g_message ("Unable to open '%s' when saving a buffer: %s",
-                 name, g_strerror (errno));
-      g_free (name);
-
-      save_info_destroy (info);
-      return;
-    }
-#endif
 
-  info->header.tile_width  = buffer->tile_storage->tile_width;
-  info->header.tile_height = buffer->tile_storage->tile_height;
-  g_object_get (buffer, "px-size", &(info->header.bytes_per_pixel), NULL);
-  {
-    gchar buf[64];
-    g_snprintf (buf, 64, "%s%c\n%iÃ%i %ibpp\n\n\n\n\n\n\n\n\n\n", 
-          ((Babl *) (buffer->tile_storage->format))->instance.name, 0,
-          info->header.tile_width,
-          info->header.tile_height,
-          info->header.bytes_per_pixel);
-    memcpy (info->header.description, buf, 64);
-  }
+  g_object_get (buffer, "px-size", &bpp, NULL);
+  gegl_buffer_header_init (&info->header,
+                           buffer->tile_storage->tile_width,
+                           buffer->tile_storage->tile_height,
+                           bpp,
+                           buffer->tile_storage->format
+                           );
+  info->header.next = (prediction += sizeof (GeglBufferHeader));
 
   info->header.x           = buffer->extent.x;
   info->header.y           = buffer->extent.y;
@@ -267,9 +275,7 @@
                     {
                       GeglBufferTile *entry;
 
-                      entry = tile_entry_new (tx, ty, z);
-                      entry->blockdef.length = sizeof (GeglBufferTile);
-                      entry->blockdef.flags = GEGL_FLAG_TILE;
+                      entry = gegl_tile_entry_new (tx, ty, z);
                       info->tiles = g_list_prepend (info->tiles, entry);
                       info->header.entry_count++;
                     }
@@ -298,8 +304,8 @@
     for (iter = info->tiles; iter; iter = iter->next)
       {
         GeglBufferTile *entry = iter->data;
-        entry->blockdef.next = iter->next?
-                                (prediction += sizeof (GeglBufferTile)):0;
+        entry->block.next = iter->next?
+                            (prediction += sizeof (GeglBufferTile)):0;
         entry->offset = predicted_offset;
         predicted_offset += info->tile_size;
       }

Modified: trunk/gegl/buffer/gegl-buffer.h
==============================================================================
--- trunk/gegl/buffer/gegl-buffer.h	(original)
+++ trunk/gegl/buffer/gegl-buffer.h	Sun Apr 20 12:10:23 2008
@@ -81,7 +81,7 @@
  */
 
 GeglBuffer*     gegl_buffer_open              (const gchar         *uri);
-
+void            gegl_buffer_flush             (GeglBuffer          *buffer);
 
 void
 gegl_buffer_make_uri (gchar       *buf_128,

Modified: trunk/gegl/buffer/gegl-tile-backend-file.c
==============================================================================
--- trunk/gegl/buffer/gegl-tile-backend-file.c	(original)
+++ trunk/gegl/buffer/gegl-tile-backend-file.c	Sun Apr 20 12:10:23 2008
@@ -23,202 +23,297 @@
 #include <errno.h>
 
 #include <glib-object.h>
+#include <glib/gprintf.h>
 
 #include "gegl-tile-backend.h"
 #include "gegl-tile-backend-file.h"
+#include "gegl-buffer-index.h"
+
 
 struct _GeglTileBackendFile
 {
   GeglTileBackend  parent_instance;
 
-  gchar           *path;
-  GFile           *file;
-  GOutputStream   *o;
-  GInputStream    *i;
-  GHashTable      *entries;
-  GSList          *free_list;
-  guint            next_unused;
-  guint            total;
+  gchar           *path;    /* the path to our buffer */
+  GFile           *file;    /* gfile refering to our buffer */
+  GOutputStream   *o;       /* for writing */
+  GInputStream    *i;       /* for reading */
+
+  /*gint             fd;*/
+  GHashTable      *index;   /* hashtable containing all entries
+                               * of buffer, the index is
+                               * written to the swapfile conforming
+                               * to the structures laid out in
+                               * gegl-buffer-index.h
+                               */
+
+  GSList          *free_list; /* list of offsets to tiles that are free */
+
+  guint            next_pre_alloc; /* offset to next pre allocated tile slot */
+  guint            total;          /* total size of file */
+
+  /* duplicated from gegl-buffer-save */
+
+  GeglBufferHeader header;     /* a local copy of the header that will be
+                                * written to the file, in a multiple user
+                                * per buffer scenario, the flags in the
+                                * header might be used for locking/signalling
+                                */
+
+  gint             offset;     /* current offset, used when writing the
+                                * index,
+                                */
+  GeglBufferBlock *in_holding; /* when writing buffer blocks the writer
+                                * keeps one block unwritten at all times
+                                * to be able to keep track of the ->next
+                                * offsets in the blocks.
+                                */
 };
 
-static void dbg_alloc (int size);
-static void dbg_dealloc (int size);
 
-/* These entries are kept in RAM for now, they should be written as an
- * index to the swap file, at a position specified by a header block,
- * making the header grow up to a multiple of the size used in this
- * swap file is probably a good idea
- *
- * Serializing the bablformat is probably also a good idea.
- */
-typedef struct _DiskEntry DiskEntry;
+static gboolean
+write_block (GeglTileBackendFile *self,
+             GeglBufferBlock     *block);
 
-struct _DiskEntry
-{
-  gint x;
-  gint y;
-  gint z;
-  gint offset;
-};
+static void dbg_alloc (int size);
+static void dbg_dealloc (int size);
 
 static void inline
-disk_entry_read (GeglTileBackendFile *disk,
-                 DiskEntry           *entry,
+file_entry_read (GeglTileBackendFile *self,
+                 GeglBufferTile      *entry,
                  guchar              *dest)
 {
-  gint  nleft;
+  gint     to_be_read;
   gboolean success;
-  gint  tile_size = GEGL_TILE_BACKEND (disk)->tile_size;
+  gint     tile_size = GEGL_TILE_BACKEND (self)->tile_size;
+  goffset  offset = entry->offset; /* we need 64bit */
 
-  success = g_seekable_seek (G_SEEKABLE (disk->i), 
-                             (goffset) entry->offset * tile_size, G_SEEK_SET,
+  success = g_seekable_seek (G_SEEKABLE (self->i), 
+                             offset, G_SEEK_SET,
                              NULL, NULL);
   if (success == FALSE)
     {
       g_warning ("unable to seek to tile in buffer: %s", g_strerror (errno));
       return;
     }
-  nleft = tile_size;
+  to_be_read = tile_size;
 
-  while (nleft > 0)
+  while (to_be_read > 0)
     {
       gint read;
 
-      read = g_input_stream_read (G_INPUT_STREAM (disk->i),
-                                 dest + tile_size - nleft, nleft,
+      read = g_input_stream_read (G_INPUT_STREAM (self->i),
+                                 dest + tile_size - to_be_read, to_be_read,
                                  NULL, NULL);
       if (read <= 0)
         {
-          g_message ("unable to read tile data from disk: "
+          g_message ("unable to read tile data from self: "
                      "%s (%d/%d bytes read)",
-                     g_strerror (errno), read, nleft);
+                     g_strerror (errno), read, to_be_read);
           return;
         }
-      nleft -= read;
+      to_be_read -= read;
     }
 }
 
 static void inline
-disk_entry_write (GeglTileBackendFile *disk,
-                  DiskEntry           *entry,
+file_entry_write (GeglTileBackendFile *self,
+                  GeglBufferTile      *entry,
                   guchar              *source)
 {
-  gint     nleft;
+  gint     to_be_written;
   gboolean success;
-  gint     tile_size = GEGL_TILE_BACKEND (disk)->tile_size;
+  gint     tile_size = GEGL_TILE_BACKEND (self)->tile_size;
+  goffset  offset = entry->offset; /* we need 64 bit */
 
-  success = g_seekable_seek (G_SEEKABLE (disk->o), 
-                             (goffset) entry->offset * tile_size, G_SEEK_SET,
+  success = g_seekable_seek (G_SEEKABLE (self->o), 
+                             offset, G_SEEK_SET,
                              NULL, NULL);
   if (success == FALSE)
     {
       g_warning ("unable to seek to tile in buffer: %s", g_strerror (errno));
       return;
     }
-  nleft = tile_size;
+  to_be_written = tile_size;
 
-  while (nleft > 0)
+  while (to_be_written > 0)
     {
       gint wrote;
-          wrote = g_output_stream_write (disk->o, source + tile_size - nleft,
-                                         nleft, NULL, NULL);
+      wrote = g_output_stream_write (self->o,
+                                     source + tile_size - to_be_written,
+                                     to_be_written, NULL, NULL);
 
       if (wrote <= 0)
         {
-          g_message ("unable to write tile data to disk: "
+          g_message ("unable to write tile data to self: "
                      "%s (%d/%d bytes written)",
-                     g_strerror (errno), wrote, nleft);
+                     g_strerror (errno), wrote, to_be_written);
           return;
         }
-      nleft -= wrote;
+      to_be_written -= wrote;
     }
 }
 
-static inline DiskEntry *
-disk_entry_new (GeglTileBackendFile *disk)
+static inline GeglBufferTile *
+file_entry_new (GeglTileBackendFile *self)
 {
-  DiskEntry *self = g_slice_new (DiskEntry);
+  GeglBufferTile *entry = gegl_tile_entry_new (0,0,0);
 
-  if (disk->free_list)
+  if (self->free_list)
     {
-      self->offset    = GPOINTER_TO_INT (disk->free_list->data);
-      disk->free_list = g_slist_remove (disk->free_list, disk->free_list->data);
+      /* XXX: losing precision ? */
+      gint offset = GPOINTER_TO_INT (self->free_list->data);
+      entry->offset = offset;
+      self->free_list = g_slist_remove (self->free_list, self->free_list->data);
     }
   else
     {
-      self->offset = disk->next_unused++;
+      gint tile_size = GEGL_TILE_BACKEND (self)->tile_size;
 
-      if (self->offset >= disk->total)
+      entry->offset = self->next_pre_alloc;
+      self->next_pre_alloc += tile_size;
+
+      if (self->next_pre_alloc >= self->total)
         {
-          gint grow = 32; /* grow 32 tiles of swap space at a time */
-          gint tile_size = GEGL_TILE_BACKEND (disk)->tile_size;
-          g_assert (g_seekable_truncate (G_SEEKABLE (disk->o),
-                    (goffset) (disk->total + grow) * (goffset) tile_size,
-                    NULL,NULL));
-          disk->total = self->offset;
+          self->total = self->total + 32 * tile_size;
+
+          g_assert (g_seekable_truncate (G_SEEKABLE (self->o),
+                    self->total, NULL,NULL));
         }
     }
-  dbg_alloc (GEGL_TILE_BACKEND (disk)->tile_size);
-  return self;
+  dbg_alloc (GEGL_TILE_BACKEND (self)->tile_size);
+  return entry;
 }
 
 static inline void
-disk_entry_destroy (DiskEntry           *entry,
-                    GeglTileBackendFile *disk)
+file_entry_destroy (GeglBufferTile      *entry,
+                    GeglTileBackendFile *self)
 {
-  disk->free_list = g_slist_prepend (disk->free_list,
-                                     GINT_TO_POINTER (entry->offset));
-  g_hash_table_remove (disk->entries, entry);
+  /* XXX: EEEk, throwing away bits */
+  guint offset = entry->offset;
+  self->free_list = g_slist_prepend (self->free_list,
+                                     GUINT_TO_POINTER (offset));
+  g_hash_table_remove (self->index, entry);
 
-  dbg_dealloc (GEGL_TILE_BACKEND (disk)->tile_size);
-  g_slice_free (DiskEntry, entry);
+  dbg_dealloc (GEGL_TILE_BACKEND (self)->tile_size);
+  g_slice_free (GeglBufferTile, entry);
 }
 
+static gboolean write_header (GeglTileBackendFile *self)
+{
+  gboolean success;
+  success = g_seekable_seek (G_SEEKABLE (self->o), 0, G_SEEK_SET,
+                             NULL, NULL);
+  if (success == FALSE)
+    {
+      g_warning ("unable to seek in buffer");
+      return FALSE;
+    }
+  g_output_stream_write (self->o, &(self->header), 256, NULL, NULL);
+  return TRUE;
+}
+
+static gboolean
+write_block (GeglTileBackendFile *self,
+             GeglBufferBlock     *block)
+{
+   if (self->in_holding)
+     {
+       guint64 next_allocation = self->offset + self->in_holding->length;
+
+       /* update the next offset pointer in the previous block */
+       self->in_holding->next = next_allocation;
+
+       if (block == NULL) /* the previous block was the last block */
+         {
+           self->in_holding->next = 0;
+         }
+
+       if(!g_seekable_seek (G_SEEKABLE (self->o),
+                            self->offset, G_SEEK_SET,
+                            NULL, NULL))
+         goto fail;
+
+       self->offset += g_output_stream_write (self->o, self->in_holding,
+                                    self->in_holding->length, 
+                                    NULL, NULL);
+
+       g_assert (next_allocation == self->offset); /* true as long as
+                                                      the simple allocation
+                                                      scheme is used */
+
+       self->offset = next_allocation;
+     }
+   else
+     {
+        /* we're setting up for the first write */
+
+        self->offset = self->next_pre_alloc; /* start writing header at end
+                                              * of file, worry about writing
+                                              * header inside free list later
+                                              */
+
+        if(!g_seekable_seek (G_SEEKABLE (self->o), 
+                             (goffset) self->offset, G_SEEK_SET,
+                             NULL, NULL))
+          goto fail;
+     }
+   self->in_holding = block;
+
+   return TRUE;
+fail:
+   g_warning ("gegl buffer index writing problems for %s",
+              self->path);
+   return FALSE;
+}
 
 G_DEFINE_TYPE (GeglTileBackendFile, gegl_tile_backend_file, GEGL_TYPE_TILE_BACKEND)
 static GObjectClass * parent_class = NULL;
 
+/* this debugging is across all buffers */
 
 static gint allocs         = 0;
-static gint disk_size      = 0;
+static gint file_size      = 0;
 static gint peak_allocs    = 0;
-static gint peak_disk_size = 0;
+static gint peak_file_size = 0;
 
 void
 gegl_tile_backend_file_stats (void)
 {
   g_warning ("leaked: %i chunks (%f mb)  peak: %i (%i bytes %fmb))",
-             allocs, disk_size / 1024 / 1024.0,
-             peak_allocs, peak_disk_size, peak_disk_size / 1024 / 1024.0);
+             allocs, file_size / 1024 / 1024.0,
+             peak_allocs, peak_file_size, peak_file_size / 1024 / 1024.0);
 }
 
 static void
 dbg_alloc (gint size)
 {
   allocs++;
-  disk_size += size;
+  file_size += size;
   if (allocs > peak_allocs)
     peak_allocs = allocs;
-  if (disk_size > peak_disk_size)
-    peak_disk_size = disk_size;
+  if (file_size > peak_file_size)
+    peak_file_size = file_size;
 }
 
 static void
 dbg_dealloc (gint size)
 {
   allocs--;
-  disk_size -= size;
+  file_size -= size;
 }
 
-static inline DiskEntry *
+static inline GeglBufferTile *
 lookup_entry (GeglTileBackendFile *self,
               gint                 x,
               gint                 y,
               gint                 z)
 {
-  DiskEntry key = { x, y, z, 0 };
-
-  return g_hash_table_lookup (self->entries, &key);
+  GeglBufferTile *ret;
+  GeglBufferTile *key = gegl_tile_entry_new (x,y,z);
+  ret = g_hash_table_lookup (self->index, key);
+  gegl_tile_entry_destroy (key);
+  return ret;
 }
 
 /* this is the only place that actually should
@@ -233,14 +328,14 @@
           gint            z)
 {
 
-  GeglTileBackend         *backend;
+  GeglTileBackend     *backend;
   GeglTileBackendFile *tile_backend_file;
-  DiskEntry               *entry;
-  GeglTile                *tile = NULL;
+  GeglBufferTile      *entry;
+  GeglTile            *tile = NULL;
 
-  backend               = GEGL_TILE_BACKEND (self);
+  backend           = GEGL_TILE_BACKEND (self);
   tile_backend_file = GEGL_TILE_BACKEND_FILE (backend);
-  entry                 = lookup_entry (tile_backend_file, x, y, z);
+  entry             = lookup_entry (tile_backend_file, x, y, z);
 
   if (!entry)
     return NULL;
@@ -249,7 +344,7 @@
   tile->stored_rev = 1;
   tile->rev        = 1;
 
-  disk_entry_read (tile_backend_file, entry, tile->data);
+  file_entry_read (tile_backend_file, entry, tile->data);
   return tile;
 }
 
@@ -260,28 +355,27 @@
           gint            y,
           gint            z)
 {
-  GeglTileBackend         *backend;
+  GeglTileBackend     *backend;
   GeglTileBackendFile *tile_backend_file;
-  DiskEntry               *entry;
+  GeglBufferTile      *entry;
 
-  backend               = GEGL_TILE_BACKEND (self);
+  backend           = GEGL_TILE_BACKEND (self);
   tile_backend_file = GEGL_TILE_BACKEND_FILE (backend);
-  entry                 = lookup_entry (tile_backend_file, x, y, z);
-
+  entry             = lookup_entry (tile_backend_file, x, y, z);
 
   if (entry == NULL)
     {
-      entry    = disk_entry_new (tile_backend_file);
+      entry    = file_entry_new (tile_backend_file);
       entry->x = x;
       entry->y = y;
       entry->z = z;
-      g_hash_table_insert (tile_backend_file->entries, entry, entry);
+      g_hash_table_insert (tile_backend_file->index, entry, entry);
     }
 
   g_assert (tile->flags == 0); /* when this one is triggered, dirty pyramid data
                                   has been tried written to persistent tile_storage.
                                 */
-  disk_entry_write (tile_backend_file, entry, tile->data);
+  file_entry_write (tile_backend_file, entry, tile->data);
   tile->stored_rev = tile->rev;
   return NULL;
 }
@@ -293,17 +387,17 @@
            gint            y,
            gint            z)
 {
-  GeglTileBackend         *backend;
+  GeglTileBackend     *backend;
   GeglTileBackendFile *tile_backend_file;
-  DiskEntry               *entry;
+  GeglBufferTile      *entry;
 
-  backend               = GEGL_TILE_BACKEND (self);
+  backend           = GEGL_TILE_BACKEND (self);
   tile_backend_file = GEGL_TILE_BACKEND_FILE (backend);
-  entry                 = lookup_entry (tile_backend_file, x, y, z);
+  entry             = lookup_entry (tile_backend_file, x, y, z);
 
   if (entry != NULL)
     {
-      disk_entry_destroy (entry, tile_backend_file);
+      file_entry_destroy (entry, tile_backend_file);
     }
 
   return NULL;
@@ -318,7 +412,7 @@
 {
   GeglTileBackend         *backend;
   GeglTileBackendFile *tile_backend_file;
-  DiskEntry               *entry;
+  GeglBufferTile               *entry;
 
   backend               = GEGL_TILE_BACKEND (self);
   tile_backend_file = GEGL_TILE_BACKEND_FILE (backend);
@@ -327,6 +421,56 @@
   return entry!=NULL?((gpointer)0x1):NULL;
 }
 
+#include "gegl-buffer-index.h"
+
+static gpointer
+flush (GeglTileSource *source,
+       GeglTile       *tile,
+       gint            x,
+       gint            y,
+       gint            z)
+{
+  GeglTileBackend     *backend;
+  GeglTileBackendFile *self;
+  GList               *tiles;
+
+  backend  = GEGL_TILE_BACKEND (source);
+  self     = GEGL_TILE_BACKEND_FILE (backend);
+
+  g_print ("flushing %s\n", self->path);
+
+  gegl_buffer_header_init (&self->header,
+                           backend->tile_width,
+                           backend->tile_height,
+                           backend->px_size,
+                           backend->format
+                           );
+  self->header.next = self->next_pre_alloc; /* this is the offset
+                                               we start handing
+                                               out headers from*/
+
+  tiles = g_hash_table_get_keys (self->index);
+
+  /* save the index */
+  {
+    GList *iter;
+    for (iter = tiles; iter; iter = iter->next)
+      {
+        GeglBufferItem *item = iter->data;
+
+        write_block (self, &item->block);
+      }
+  }
+  write_block (self, NULL); /* terminate the index */
+  g_output_stream_flush (self->o, NULL, NULL);
+  g_list_free (tiles);
+  write_header (self);
+
+  g_print ("flushed %s\n", self->path);
+
+  return (gpointer)0xf0f;
+}
+
 enum
 {
   PROP_0,
@@ -349,13 +493,18 @@
         return set_tile (self, data, x, y, z);
 
       case GEGL_TILE_IDLE:
-        return NULL;
+        return NULL;       /* we could perhaps lazily be writing indexes
+                              at some intervals, making it work as an
+                              autosave for the buffer?
+                            */
 
       case GEGL_TILE_VOID:
         return void_tile (self, data, x, y, z);
 
       case GEGL_TILE_EXIST:
         return exist_tile (self, data, x, y, z);
+      case GEGL_TILE_FLUSH:
+        return flush (self, data, x, y, z);
 
       default:
         g_assert (command < GEGL_TILE_LAST_COMMAND &&
@@ -411,18 +560,23 @@
 {
   GeglTileBackendFile *self = (GeglTileBackendFile *) object;
 
-  g_hash_table_unref (self->entries);
-
-  g_object_unref (self->i);
-  g_object_unref (self->o);
+  if (self->index)
+    g_hash_table_unref (self->index);
+  if (self->i)
+    g_object_unref (self->i);
+  if (self->o)
+    g_object_unref (self->o);
   /* check if we should nuke the buffer or not */ 
 
   if(0)g_print ("finalizing buffer %s", self->path);
   if (self->path)
-  g_free (self->path);
+    g_free (self->path);
 
-  g_file_delete  (self->file, NULL, NULL);
-  g_object_unref (self->file);
+  if (self->file)
+    {
+      g_file_delete  (self->file, NULL, NULL);
+      g_object_unref (self->file);
+    }
 
   (*G_OBJECT_CLASS (parent_class)->finalize)(object);
 }
@@ -430,7 +584,7 @@
 static guint
 hashfunc (gconstpointer key)
 {
-  const DiskEntry *e = key;
+  const GeglBufferTile *e = key;
   guint            hash;
   gint             i;
   gint             srcA = e->x;
@@ -459,8 +613,8 @@
 equalfunc (gconstpointer a,
            gconstpointer b)
 {
-  const DiskEntry *ea = a;
-  const DiskEntry *eb = b;
+  const GeglBufferTile *ea = a;
+  const GeglBufferTile *eb = b;
 
   if (ea->x == eb->x &&
       ea->y == eb->y &&
@@ -476,26 +630,32 @@
                                     GObjectConstructParam *params)
 {
   GObject      *object;
-  GeglTileBackendFile *disk;
+  GeglTileBackendFile *self;
 
   object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
-  disk   = GEGL_TILE_BACKEND_FILE (object);
+  self   = GEGL_TILE_BACKEND_FILE (object);
+
+  self->file = g_file_new_for_commandline_arg (self->path);
+  self->o = G_OUTPUT_STREAM (g_file_replace (self->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
+  g_output_stream_flush (self->o, NULL, NULL);
+  self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, NULL));
+
+
+  self->next_pre_alloc = 256;  /* reserved space for header */
+  self->total          = 256;  /* reserved space for header */
+  g_assert(g_seekable_seek (G_SEEKABLE (self->o), 256, G_SEEK_SET, NULL, NULL));
 
-  disk->file = g_file_new_for_commandline_arg (disk->path);
-  disk->o = G_OUTPUT_STREAM (g_file_replace (disk->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
-  g_output_stream_flush (disk->o, NULL, NULL);
-  disk->i = G_INPUT_STREAM (g_file_read (disk->file, NULL, NULL));
 
-  if (!disk->file)
+  if (!self->file)
     {
-      g_warning ("Unable to open swap file '%s'\n",disk->path);
+      g_warning ("Unable to open swap file '%s'\n",self->path);
       return NULL;
     }
-  g_assert (disk->file);
-  g_assert (disk->i);
-  g_assert (disk->o);
+  g_assert (self->file);
+  g_assert (self->i);
+  g_assert (self->o);
 
-  disk->entries = g_hash_table_new (hashfunc, equalfunc);
+  self->index = g_hash_table_new (hashfunc, equalfunc);
 
   return object;
 }
@@ -528,12 +688,12 @@
 static void
 gegl_tile_backend_file_init (GeglTileBackendFile *self)
 {
-  self->path        = NULL;
-  self->file        = NULL;
-  self->i           = NULL;
-  self->o           = NULL;
-  self->entries     = NULL;
-  self->free_list   = NULL;
-  self->next_unused = 0;
-  self->total       = 0;
+  self->path           = NULL;
+  self->file           = NULL;
+  self->i              = NULL;
+  self->o              = NULL;
+  self->index          = NULL;
+  self->free_list      = NULL;
+  self->next_pre_alloc = 256;  /* reserved space for header */
+  self->total          = 256;  /* reserved space for header */
 }

Modified: trunk/gegl/buffer/gegl-tile-handler-cache.c
==============================================================================
--- trunk/gegl/buffer/gegl-tile-handler-cache.c	(original)
+++ trunk/gegl/buffer/gegl-tile-handler-cache.c	Sun Apr 20 12:10:23 2008
@@ -192,7 +192,35 @@
     {
       case GEGL_TILE_SET:
         /* nothing to do */
-        break;
+        break; /* chain up */
+      case GEGL_TILE_FLUSH:
+        {
+          /*FIXME*/
+          /* do this for all tiles belonging to this cache */
+          gboolean exist = gegl_tile_handler_cache_has_tile (cache, x, y, z);
+          GeglTile *tile;
+  GList     *link;
+
+  for (link = g_queue_peek_head_link (cache_queue); link; link = link->next)
+    {
+      CacheItem *item = link->data;
+      GeglTile  *tile = item->tile;
+
+      if (tile != NULL &&
+          item->handler == cache)
+        {
+          gegl_tile_store (tile);
+        }
+    }
+
+ /*        
+          if (exist)
+            {
+              tile = get_tile (tile_store, x, y, z);
+              gegl_tile_store (tile);
+            }*/
+        }
+        break; /* chain up */
       case GEGL_TILE_GET:
         /* XXX: we should perhaps store a NIL result, and place the empty
          * generator after the cache, this would have to be possible to disable

Modified: trunk/gegl/buffer/gegl-tile-handler-log.c
==============================================================================
--- trunk/gegl/buffer/gegl-tile-handler-log.c	(original)
+++ trunk/gegl/buffer/gegl-tile-handler-log.c	Sun Apr 20 12:10:23 2008
@@ -38,6 +38,7 @@
   "void bl",
   "void br",
   "flush",
+  "invalidated",
   "last command",
   "eeek",
   NULL

Modified: trunk/gegl/buffer/gegl-tile-source.h
==============================================================================
--- trunk/gegl/buffer/gegl-tile-source.h	(original)
+++ trunk/gegl/buffer/gegl-tile-source.h	Sun Apr 20 12:10:23 2008
@@ -48,6 +48,7 @@
   GEGL_TILE_VOID_BL,
   GEGL_TILE_VOID_BR,
   GEGL_TILE_FLUSH,
+  GEGL_TILE_INVALIDATED,
   GEGL_TILE_LAST_COMMAND
 };
 



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