コード例 #1
0
ファイル: gegl-tile-backend-swap.c プロジェクト: bantu/gegl
static GeglTile *
gegl_tile_backend_swap_get_tile (GeglTileSource *self,
                                 gint            x,
                                 gint            y,
                                 gint            z)
{
  GeglTileBackend     *backend;
  GeglTileBackendSwap *tile_backend_swap;
  SwapEntry           *entry;
  GeglTile            *tile = NULL;
  gint                 tile_size;

  backend           = GEGL_TILE_BACKEND (self);
  tile_backend_swap = GEGL_TILE_BACKEND_SWAP (backend);
  entry             = gegl_tile_backend_swap_lookup_entry (tile_backend_swap, x, y, z);

  if (!entry)
    return NULL;

  tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));
  tile      = gegl_tile_new (tile_size);
  gegl_tile_mark_as_stored (tile);

  gegl_tile_backend_swap_entry_read (tile_backend_swap, entry, gegl_tile_get_data (tile));

  return tile;
}
コード例 #2
0
/* this is the only place that actually should
 * instantiate tiles, when the cache is large enough
 * that should make sure we don't hit this function
 * too often.
 */
static GeglTile *
gegl_tile_backend_file_get_tile (GeglTileSource *self,
          gint            x,
          gint            y,
          gint            z)
{
  GeglTileBackend     *backend;
  GeglTileBackendFile *tile_backend_file;
  GeglBufferTile      *entry;
  GeglTile            *tile = NULL;
  gint                 tile_size;

  backend           = GEGL_TILE_BACKEND (self);
  tile_backend_file = GEGL_TILE_BACKEND_FILE (backend);
  entry             = gegl_tile_backend_file_lookup_entry (tile_backend_file, x, y, z);

  if (!entry)
    return NULL;

  tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));
  tile      = gegl_tile_new (tile_size);
  gegl_tile_set_rev (tile, entry->rev);
  gegl_tile_mark_as_stored (tile);

  gegl_tile_backend_file_file_entry_read (tile_backend_file, entry, gegl_tile_get_data (tile));
  return tile;
}
コード例 #3
0
ファイル: gegl-tile-backend.c プロジェクト: dankamongmen/gegl
static void
set_property (GObject      *gobject,
              guint         property_id,
              const GValue *value,
              GParamSpec   *pspec)
{
  GeglTileBackend *backend = GEGL_TILE_BACKEND (gobject);

  switch (property_id)
    {
      case PROP_TILE_WIDTH:
        backend->priv->tile_width = g_value_get_int (value);
        return;

      case PROP_TILE_HEIGHT:
        backend->priv->tile_height = g_value_get_int (value);
        return;

      case PROP_FORMAT:
        backend->priv->format = g_value_get_pointer (value);
        break;

      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
        break;
    }
}
コード例 #4
0
static gpointer
gegl_tile_backend_file_set_tile (GeglTileSource *self,
                                 GeglTile       *tile,
                                 gint            x,
                                 gint            y,
                                 gint            z)
{
  GeglTileBackend     *backend;
  GeglTileBackendFile *tile_backend_file;
  GeglBufferTile      *entry;

  backend           = GEGL_TILE_BACKEND (self);
  tile_backend_file = GEGL_TILE_BACKEND_FILE (backend);
  entry             = gegl_tile_backend_file_lookup_entry (tile_backend_file, x, y, z);

  if (entry == NULL)
    {
      entry    = gegl_tile_backend_file_file_entry_new (tile_backend_file);
      entry->x = x;
      entry->y = y;
      entry->z = z;
      g_hash_table_insert (tile_backend_file->index, entry, entry);
    }
  entry->rev = gegl_tile_get_rev (tile);

  gegl_tile_backend_file_file_entry_write (tile_backend_file, entry, gegl_tile_get_data (tile));
  gegl_tile_mark_as_stored (tile);
  return NULL;
}
コード例 #5
0
ファイル: gegl-tile-backend-swap.c プロジェクト: bantu/gegl
static gpointer
gegl_tile_backend_swap_set_tile (GeglTileSource *self,
                                 GeglTile       *tile,
                                 gint            x,
                                 gint            y,
                                 gint            z)
{
  GeglTileBackend     *backend;
  GeglTileBackendSwap *tile_backend_swap;
  SwapEntry           *entry;

  backend           = GEGL_TILE_BACKEND (self);
  tile_backend_swap = GEGL_TILE_BACKEND_SWAP (backend);
  entry             = gegl_tile_backend_swap_lookup_entry (tile_backend_swap, x, y, z);

  gegl_tile_backend_swap_ensure_exist ();

  if (entry == NULL)
    {
      entry          = gegl_tile_backend_swap_entry_create (x, y, z);
      entry->offset  = gegl_tile_backend_swap_find_offset (gegl_tile_backend_get_tile_size (backend));
      g_hash_table_insert (tile_backend_swap->index, entry, entry);
    }

  gegl_tile_backend_swap_entry_write (tile_backend_swap, entry, tile);

  gegl_tile_mark_as_stored (tile);

  return NULL;
}
コード例 #6
0
ファイル: gegl-tile-backend.c プロジェクト: dankamongmen/gegl
static void
get_property (GObject    *gobject,
              guint       property_id,
              GValue     *value,
              GParamSpec *pspec)
{
  GeglTileBackend *backend = GEGL_TILE_BACKEND (gobject);

  switch (property_id)
    {
      case PROP_TILE_WIDTH:
        g_value_set_int (value, backend->priv->tile_width);
        break;

      case PROP_TILE_HEIGHT:
        g_value_set_int (value, backend->priv->tile_height);
        break;

      case PROP_TILE_SIZE:
        g_value_set_int (value, backend->priv->tile_size);
        break;

      case PROP_PX_SIZE:
        g_value_set_int (value, backend->priv->px_size);
        break;

      case PROP_FORMAT:
        g_value_set_pointer (value, (void*)backend->priv->format);
        break;

      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
        break;
    }
}
コード例 #7
0
static inline GeglBufferTile *
gegl_tile_backend_file_file_entry_new (GeglTileBackendFile *self)
{
  GeglBufferTile *entry = gegl_tile_entry_new (0,0,0);

  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "Creating new entry");

  gegl_tile_backend_file_ensure_exist (self);

  if (self->free_list)
    {
      /* XXX: losing precision ?
       * the free list seems to operate with fixed size datums and
       * only keep track of offsets.
       */
      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);

      GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "  set offset %i from free list", ((gint)entry->offset));
    }
  else
    {
      gint tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));

      entry->offset = self->next_pre_alloc;
      GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "  set offset %i (next allocation)", (gint)entry->offset);
      self->next_pre_alloc += tile_size;

      if (self->next_pre_alloc >= self->total) /* automatic growing ensuring that
                                                  we have room for next allocation..
                                                */
        {
          self->total = self->total + 32 * tile_size;

          GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "growing file to %i bytes", (gint)self->total);

          ftruncate (self->o, self->total);
          self->foffset = -1;
        }
    }
  gegl_tile_backend_file_dbg_alloc (gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)));
  return entry;
}
コード例 #8
0
static inline GeglBufferTile *
gegl_tile_backend_file_file_entry_new (GeglTileBackendFile *self)
{
  GeglBufferTile *entry = gegl_tile_entry_new (0,0,0);

  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "Creating new entry");

  gegl_tile_backend_file_ensure_exist (self);

  if (self->free_list)
    {
      /* 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);

      GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "  set offset %i from free list", ((gint)entry->offset));
    }
  else
    {
      gint tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));

      entry->offset = self->next_pre_alloc;
      GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "  set offset %i (next allocation)", (gint)entry->offset);
      self->next_pre_alloc += tile_size;

      if (self->next_pre_alloc >= self->total)
        {
          self->total = self->total + 32 * tile_size;

          GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "growing file to %i bytes", (gint)self->total);

#if HAVE_GIO
          g_assert (g_seekable_truncate (G_SEEKABLE (self->o),
                                         self->total, NULL,NULL));
#else
          g_assert (ftruncate (self->o, self->total) == 0);
#endif
        }
    }
  gegl_tile_backend_file_dbg_alloc (gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)));
  return entry;
}
コード例 #9
0
ファイル: gegl-tile-backend.c プロジェクト: Distrotech/gegl
static void
constructed (GObject *object)
{
  GeglTileBackend *backend = GEGL_TILE_BACKEND (object);

  G_OBJECT_CLASS (parent_class)->constructed (object);

  g_assert (backend->priv->tile_width > 0 && backend->priv->tile_height > 0);
  g_assert (backend->priv->format);

  backend->priv->px_size = babl_format_get_bytes_per_pixel (backend->priv->format);
  backend->priv->tile_size = backend->priv->tile_width * backend->priv->tile_height * backend->priv->px_size;
}
コード例 #10
0
ファイル: gegl-tile-backend-swap.c プロジェクト: bantu/gegl
static void
gegl_tile_backend_swap_constructed (GObject *object)
{
  GeglTileBackend *backend = GEGL_TILE_BACKEND (object);

  G_OBJECT_CLASS (parent_class)->constructed (object);

  backend->priv->shared = FALSE;

  gegl_tile_backend_set_flush_on_destroy (backend, FALSE);

  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "constructing swap backend");
}
コード例 #11
0
static inline void
gegl_tile_backend_file_file_entry_destroy (GeglBufferTile      *entry,
                                           GeglTileBackendFile *self)
{
  /* 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);

  gegl_tile_backend_file_dbg_dealloc (gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self)));
  g_free (entry);
}
コード例 #12
0
static gpointer
gegl_tile_backend_file_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);

  gegl_tile_backend_file_ensure_exist (self);

  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "flushing %s", self->path);


  self->header.rev ++;
  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);

  if (tiles == NULL)
    self->header.next = 0;
  else
    {
      GList *iter;
      for (iter = tiles; iter; iter = iter->next)
        {
          GeglBufferItem *item = iter->data;

          gegl_tile_backend_file_write_block (self, &item->block);
        }
      gegl_tile_backend_file_write_block (self, NULL); /* terminate the index */
      g_list_free (tiles);
    }

  gegl_tile_backend_file_write_header (self);
#if HAVE_GIO
  g_output_stream_flush (self->o, NULL, NULL);
#else
  fsync (self->o);
#endif

  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "flushed %s", self->path);

  return (gpointer)0xf0f;
}
コード例 #13
0
static inline void
gegl_tile_backend_file_file_entry_read (GeglTileBackendFile *self,
                                        GeglBufferTile      *entry,
                                        guchar              *dest)
{
  gint     to_be_read;
  gboolean success;
  gint     tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));
  goffset  offset = entry->offset;

  gegl_tile_backend_file_ensure_exist (self);

#if HAVE_GIO
  success = g_seekable_seek (G_SEEKABLE (self->i),
                             offset, G_SEEK_SET,
                             NULL, NULL);
#else
  success = (lseek (self->i, offset, SEEK_SET) >= 0);
#endif
  if (success == FALSE)
    {
      g_warning ("unable to seek to tile in buffer: %s", g_strerror (errno));
      return;
    }
  to_be_read = tile_size;

  while (to_be_read > 0)
    {
      gint byte_read;

#if HAVE_GIO
      byte_read = g_input_stream_read (G_INPUT_STREAM (self->i),
                                       dest + tile_size - to_be_read, to_be_read,
                                       NULL, NULL);
#else
      byte_read = read (self->i, dest + tile_size - to_be_read, to_be_read);
#endif
      if (byte_read <= 0)
        {
          g_message ("unable to read tile data from self: "
                     "%s (%d/%d bytes read)",
                     g_strerror (errno), byte_read, to_be_read);
          return;
        }
      to_be_read -= byte_read;
    }


  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "read entry %i,%i,%i at %i", entry->x, entry->y, entry->z, (gint)offset);
}
コード例 #14
0
static inline void
gegl_tile_backend_file_file_entry_write (GeglTileBackendFile *self,
                                         GeglBufferTile      *entry,
                                         guchar              *source)
{
  gint     to_be_written;
  gboolean success;
  gint     tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));
  goffset  offset = entry->offset;

  gegl_tile_backend_file_ensure_exist (self);

#if HAVE_GIO
  success = g_seekable_seek (G_SEEKABLE (self->o),
                             offset, G_SEEK_SET,
                             NULL, NULL);
#else
  success = (lseek (self->o, offset, SEEK_SET) >= 0);
#endif
  if (success == FALSE)
    {
      g_warning ("unable to seek to tile in buffer: %s", g_strerror (errno));
      return;
    }
  to_be_written = tile_size;

  while (to_be_written > 0)
    {
      gint wrote;
#if HAVE_GIO
      wrote = g_output_stream_write (self->o,
                                     source + tile_size - to_be_written,
                                     to_be_written, NULL, NULL);
#else
      wrote = write (self->o,
                     source + tile_size - to_be_written,
                     to_be_written);
#endif
      if (wrote <= 0)
        {
          g_message ("unable to write tile data to self: "
                     "%s (%d/%d bytes written)",
                     g_strerror (errno), wrote, to_be_written);
          return;
        }
      to_be_written -= wrote;
    }
  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "wrote entry %i,%i,%i at %i", entry->x, entry->y, entry->z, (gint)offset);
}
コード例 #15
0
ファイル: gegl-tile-backend-swap.c プロジェクト: bantu/gegl
static gpointer
gegl_tile_backend_swap_exist_tile (GeglTileSource *self,
                                   GeglTile       *tile,
                                   gint            x,
                                   gint            y,
                                   gint            z)
{
  GeglTileBackend     *backend;
  GeglTileBackendSwap *tile_backend_swap;
  SwapEntry           *entry;

  backend           = GEGL_TILE_BACKEND (self);
  tile_backend_swap = GEGL_TILE_BACKEND_SWAP (backend);
  entry             = gegl_tile_backend_swap_lookup_entry (tile_backend_swap, x, y, z);

  return entry!=NULL?((gpointer)0x1):NULL;
}
コード例 #16
0
static gpointer
gegl_tile_backend_file_exist_tile (GeglTileSource *self,
                                   GeglTile       *tile,
                                   gint            x,
                                   gint            y,
                                   gint            z)
{
  GeglTileBackend     *backend;
  GeglTileBackendFile *tile_backend_file;
  GeglBufferTile      *entry;

  backend           = GEGL_TILE_BACKEND (self);
  tile_backend_file = GEGL_TILE_BACKEND_FILE (backend);
  entry             = gegl_tile_backend_file_lookup_entry (tile_backend_file, x, y, z);

  return entry!=NULL?((gpointer)0x1):NULL;
}
コード例 #17
0
static inline void
gegl_tile_backend_file_file_entry_read (GeglTileBackendFile *self,
                                        GeglBufferTile      *entry,
                                        guchar              *dest)
{
  gint     to_be_read;
  gboolean success;
  gint     tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));
  goffset  offset = entry->offset;
  guchar  *tdest = dest;

  gegl_tile_backend_file_ensure_exist (self);

  if (self->foffset != offset)
    {
      success = (lseek (self->i, offset, SEEK_SET) >= 0);

      if (success == FALSE)
        {
          g_warning ("unable to seek to tile in buffer: %s", g_strerror (errno));
          return;
        }
      self->foffset = offset;
    }
  to_be_read = tile_size;

  while (to_be_read > 0)
    {
      GError *error = NULL;
      gint byte_read;

      byte_read = read (self->i, tdest + tile_size - to_be_read, to_be_read);
      if (byte_read <= 0)
        {
          g_message ("unable to read tile data from self: "
                     "%s (%d/%d bytes read) %s",
                     g_strerror (errno), byte_read, to_be_read, error?error->message:"--");
          return;
        }
      to_be_read -= byte_read;
      self->foffset += byte_read;
    }

  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "read entry %i,%i,%i at %i", entry->x, entry->y, entry->z, (gint)offset);
}
コード例 #18
0
ファイル: gegl-tile-backend.c プロジェクト: dankamongmen/gegl
static GObject *
constructor (GType                  type,
             guint                  n_params,
             GObjectConstructParam *params)
{
  GObject         *object;
  GeglTileBackend *backend;

  object  = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
  backend = GEGL_TILE_BACKEND (object);

  g_assert (backend->priv->tile_width > 0 && backend->priv->tile_height > 0);
  g_assert (backend->priv->format);

  backend->priv->px_size = babl_format_get_bytes_per_pixel (backend->priv->format);
  backend->priv->tile_size = backend->priv->tile_width * backend->priv->tile_height * backend->priv->px_size;

  return object;
}
コード例 #19
0
static void
gegl_tile_backend_swap_entry_write (GeglTileBackendSwap *self,
                                    SwapEntry           *entry,
                                    guchar              *source)
{
  ThreadParams *params;
  gint          length = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));
  guchar       *new_source;

  gegl_tile_backend_swap_ensure_exist ();

  if (entry->link)
    {
      g_mutex_lock (&mutex);

      if (entry->link)
        {
          params = entry->link->data;
          memcpy (params->source, source, length);
          g_mutex_unlock (&mutex);

          GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "overwrote queue entry %i, %i, %i at %i", entry->x, entry->y, entry->z, (gint)entry->offset);

          return;
        }

      g_mutex_unlock (&mutex);
    }

  new_source = g_malloc (length);
  memcpy (new_source, source, length);

  params            = g_slice_new0 (ThreadParams);
  params->operation = OP_WRITE;
  params->length    = length;
  params->source    = new_source;
  params->entry     = entry;

  gegl_tile_backend_swap_push_queue (params);

  GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "pushed write of entry %i, %i, %i at %i", entry->x, entry->y, entry->z, (gint)entry->offset);
}
コード例 #20
0
static GObject *
gegl_tile_backend_swap_constructor (GType                  type,
                                    guint                  n_params,
                                    GObjectConstructParam *params)
{
  GObject             *object;
  GeglTileBackendSwap *self;
  GeglTileBackend     *backend;

  object  = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
  self    = GEGL_TILE_BACKEND_SWAP (object);
  backend = GEGL_TILE_BACKEND (object);

  self->index = g_hash_table_new (gegl_tile_backend_swap_hashfunc,
                                  gegl_tile_backend_swap_equalfunc);

  backend->priv->shared = FALSE;

  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "constructing swap backend");

  return object;
}
コード例 #21
0
ファイル: gegl-tile-backend-swap.c プロジェクト: bantu/gegl
static void
gegl_tile_backend_swap_entry_write (GeglTileBackendSwap *self,
                                    SwapEntry           *entry,
                                    GeglTile            *tile)
{
  ThreadParams *params;
  gint          length = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));

  gegl_tile_backend_swap_ensure_exist ();

  if (entry->link)
    {
      g_mutex_lock (&mutex);

      if (entry->link)
        {
          params = entry->link->data;
          gegl_tile_unref (params->tile);
          params->tile = gegl_tile_dup (tile);
          g_mutex_unlock (&mutex);

          GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "tile %i, %i, %i at %i is already enqueued, changed data", entry->x, entry->y, entry->z, (gint)entry->offset);

          return;
        }

      g_mutex_unlock (&mutex);
    }

  params            = g_slice_new0 (ThreadParams);
  params->operation = OP_WRITE;
  params->length    = length;
  params->tile      = gegl_tile_dup (tile);
  params->entry     = entry;

  gegl_tile_backend_swap_push_queue (params);

  GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "pushed write of entry %i, %i, %i at %i", entry->x, entry->y, entry->z, (gint)entry->offset);
}
コード例 #22
0
static gpointer
gegl_tile_backend_file_void_tile (GeglTileSource *self,
                                  GeglTile       *tile,
                                  gint            x,
                                  gint            y,
                                  gint            z)
{
  GeglTileBackend     *backend;
  GeglTileBackendFile *tile_backend_file;
  GeglBufferTile      *entry;

  backend           = GEGL_TILE_BACKEND (self);
  tile_backend_file = GEGL_TILE_BACKEND_FILE (backend);
  entry             = gegl_tile_backend_file_lookup_entry (tile_backend_file, x, y, z);

  if (entry != NULL)
    {
      gegl_tile_backend_file_file_entry_destroy (entry, tile_backend_file);
    }

  return NULL;
}
コード例 #23
0
static void
gegl_tile_backend_file_ensure_exist (GeglTileBackendFile *self)
{
  if (!self->exist)
    {
      GeglTileBackend *backend;
      self->exist = TRUE;

      backend = GEGL_TILE_BACKEND (self);

      GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "creating swapfile  %s", self->path);

      self->o = g_open (self->path, O_RDWR|O_CREAT, 0770);
      if (self->o == -1)
        g_warning ("%s: Could not open '%s': %s", G_STRFUNC, self->path, g_strerror (errno));

      self->next_pre_alloc = 256;  /* reserved space for header */
      self->total          = 256;  /* reserved space for header */
      self->foffset        = 0;
      gegl_buffer_header_init (&self->header,
                               backend->priv->tile_width,
                               backend->priv->tile_height,
                               backend->priv->px_size,
                               backend->priv->format
                               );
      gegl_tile_backend_file_write_header (self);
      self->foffset       = 256;
      fsync (self->o);
      self->i = dup (self->o);

      /*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 (self->i != -1);
      g_assert (self->o != -1);
    }
}
コード例 #24
0
ファイル: gegl-tile-backend-swap.c プロジェクト: bantu/gegl
static gpointer
gegl_tile_backend_swap_void_tile (GeglTileSource *self,
                                  GeglTile       *tile,
                                  gint            x,
                                  gint            y,
                                  gint            z)
{
  GeglTileBackend     *backend;
  GeglTileBackendSwap *tile_backend_swap;
  SwapEntry           *entry;

  backend           = GEGL_TILE_BACKEND (self);
  tile_backend_swap = GEGL_TILE_BACKEND_SWAP (backend);
  entry             = gegl_tile_backend_swap_lookup_entry (tile_backend_swap, x, y, z);

  if (entry != NULL)
    {
      GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "void tile %i, %i, %i", x, y, z);

      gegl_tile_backend_swap_entry_destroy (tile_backend_swap, entry);
    }

  return NULL;
}
コード例 #25
0
static GObject *
gegl_tile_backend_file_constructor (GType                  type,
                                    guint                  n_params,
                                    GObjectConstructParam *params)
{
  GObject             *object;
  GeglTileBackendFile *self;
  GeglTileBackend     *backend;

  object  = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
  self    = GEGL_TILE_BACKEND_FILE (object);
  backend = GEGL_TILE_BACKEND (object);

  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "constructing file backend: %s", self->path);

  self->file = g_file_new_for_commandline_arg (self->path);
  self->i = self->o = -1;
  self->index = g_hash_table_new (gegl_tile_backend_file_hashfunc, gegl_tile_backend_file_equalfunc);


  /* If the file already exists open it, assuming it is a GeglBuffer. */
  if (g_access (self->path, F_OK) != -1)
    {
      goffset offset = 0;

      /* Install a monitor for changes to the file in case other applications
       * might be writing to the buffer
       */
      self->monitor = g_file_monitor_file (self->file, G_FILE_MONITOR_NONE,
                                           NULL, NULL);
      g_signal_connect (self->monitor, "changed",
                        G_CALLBACK (gegl_tile_backend_file_file_changed),
                        self);

      self->o = g_open (self->path, O_RDWR|O_CREAT, 0770);
      if (self->o == -1)
        {
          /* Try again but this time with only read access. This is
           * a quick-fix for make distcheck, where img_cmp fails
           * when it opens a GeglBuffer file in the source tree
           * (which is read-only).
           */
          self->o = g_open (self->path, O_RDONLY, 0770);

          if (self->o == -1)
            g_warning ("%s: Could not open '%s': %s", G_STRFUNC, self->path, g_strerror (errno));
        }
      self->i = dup (self->o);

      self->header = gegl_buffer_read_header (self->i, &offset)->header;
      self->header.rev = self->header.rev -1;

      /* we are overriding all of the work of the actual constructor here,
       * a really evil hack :d
       */
      backend->priv->tile_width = self->header.tile_width;
      backend->priv->tile_height = self->header.tile_height;
      backend->priv->format = babl_format (self->header.description);
      backend->priv->px_size = babl_format_get_bytes_per_pixel (backend->priv->format);
      backend->priv->tile_size = backend->priv->tile_width *
                                    backend->priv->tile_height *
                                    backend->priv->px_size;

      /* insert each of the entries into the hash table */
      gegl_tile_backend_file_load_index (self, TRUE);
      self->exist = TRUE;
      g_assert (self->i != -1);
      g_assert (self->o != -1);

      /* to autoflush gegl_buffer_set */

      /* XXX: poking at internals, icky */
      backend->priv->shared = TRUE;
    }
  else
    {
      self->exist = FALSE; /* this is also the default, the file will be created on demand */
    }

  g_assert (self->file);

  backend->priv->header = &self->header;

  return object;
}
コード例 #26
0
static void
gegl_tile_backend_file_ensure_exist (GeglTileBackendFile *self)
{
  if (!self->exist)
    {
      GeglTileBackend *backend;
#if HAVE_GIO
      GError *error = NULL;

      if (self->io)
        {
          g_print ("we already existed\n");
          return;
        }
#endif
      self->exist = TRUE;

      backend = GEGL_TILE_BACKEND (self);

      GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "creating swapfile  %s", self->path);

#if HAVE_GIO
      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);
      g_output_stream_close (self->o, NULL, NULL);

      self->io = G_IO_STREAM (g_file_open_readwrite (self->file, NULL, &error));
      if (error)
        {
          g_warning ("%s: %s", G_STRLOC, error->message);
          g_error_free (error);
          error = NULL;
        }
      self->o = g_io_stream_get_output_stream (self->io);
      self->i = g_io_stream_get_input_stream (self->io);

#else
      self->o = open (self->path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
#endif

      self->next_pre_alloc = 256;  /* reserved space for header */
      self->total          = 256;  /* reserved space for header */
#if HAVE_GIO
      g_assert(g_seekable_seek (G_SEEKABLE (self->o), 256, G_SEEK_SET, NULL, NULL));
#endif
      gegl_buffer_header_init (&self->header,
                               backend->priv->tile_width,
                               backend->priv->tile_height,
                               backend->priv->px_size,
                               backend->priv->format
                               );
      gegl_tile_backend_file_write_header (self);
#if HAVE_GIO
      g_output_stream_flush (self->o, NULL, NULL);
#else
      fsync (self->o);
      self->i = dup (self->o);
#endif

      /*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 */
#if HAVE_GIO
      g_assert (self->io);
      g_assert (self->i);
      g_assert (self->o);
#else
      g_assert (self->i != -1);
      g_assert (self->o != -1);
#endif
    }
}
コード例 #27
0
ファイル: gegl-tile-backend-swap.c プロジェクト: bantu/gegl
static void
gegl_tile_backend_swap_entry_destroy (GeglTileBackendSwap *self,
                                      SwapEntry           *entry)
{
  guint64  start, end;
  gint     tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));
  GList   *hlink;

  if (entry->link)
    {
      GList *link;

      g_mutex_lock (&mutex);

      if ((link = entry->link))
        {
          ThreadParams *queued_op = link->data;
          g_queue_delete_link (queue, link);
          gegl_tile_unref (queued_op->tile);
          g_slice_free (ThreadParams, queued_op);
        }

      g_mutex_unlock (&mutex);
    }

  start = entry->offset;
  end = start + tile_size;

  if ((hlink = gap_list))
    while (hlink)
      {
        GList *llink = hlink->prev;
        SwapGap *lgap, *hgap;

        if (llink)
          lgap = llink->data;

        hgap = hlink->data;

        /* attempt to merge lower, upper and this gap */
        if (llink != NULL && lgap->end == start &&
            hgap->start == end)
          {
            llink->next = hlink->next;
            if (hlink->next)
              hlink->next->prev = llink;
            lgap->end = hgap->end;

            g_slice_free (SwapGap, hgap);
            hlink->next = NULL;
            hlink->prev = NULL;
            g_list_free (hlink);
            break;
          }
        /* attempt to merge with upper gap */
        else if (hgap->start == end)
          {
            hgap->start = start;
            break;
          }
        /* attempt to merge with lower gap */
        else if (llink != NULL && lgap->end == start)
          {
            lgap->end = end;
            break;
          }
        /* create new gap */
        else if (hgap->start > end)
          {
            lgap = gegl_tile_backend_swap_gap_new (start, end);
            gap_list = g_list_insert_before (gap_list, hlink, lgap);
            break;
          }

        /* if there's no more elements in the list after this */
        else if (hlink->next == NULL)
          {
            /* attempt to merge with the last gap */
            if (hgap->end == start)
              {
                hgap->end = end;
              }
            /* create a new gap in the end of the list */
            else
              {
                GList *new_link;
                hgap = gegl_tile_backend_swap_gap_new (start, end);
                new_link = g_list_alloc ();
                new_link->next = NULL;
                new_link->prev = hlink;
                new_link->data = hgap;
                hlink->next = new_link;
              }
            break;
          }

        hlink = hlink->next;
      }
  else
    gap_list = g_list_prepend (NULL,
                               gegl_tile_backend_swap_gap_new (start, end));

  g_hash_table_remove (self->index, entry);
  g_slice_free (SwapEntry, entry);
}
コード例 #28
0
ファイル: gegl-tile-backend-swap.c プロジェクト: bantu/gegl
static void
gegl_tile_backend_swap_entry_read (GeglTileBackendSwap *self,
                                   SwapEntry           *entry,
                                   guchar              *dest)
{
  gint    tile_size  = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));
  gint    to_be_read = tile_size;
  guint64 offset     = entry->offset;

  gegl_tile_backend_swap_ensure_exist ();

  if (entry->link || in_progress)
    {
      ThreadParams *queued_op = NULL;
      g_mutex_lock (&mutex);

      if (entry->link)
        queued_op = entry->link->data;
      else if (in_progress && in_progress->entry == entry)
        queued_op = in_progress;

      if (queued_op)
        {
          memcpy (dest, gegl_tile_get_data (queued_op->tile), to_be_read);
          g_mutex_unlock (&mutex);

          GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "read entry %i, %i, %i from queue", entry->x, entry->y, entry->z);

          return;
        }

      g_mutex_unlock (&mutex);
    }

  if (in_offset != offset)
    {
      if (lseek (in_fd, offset, SEEK_SET) < 0)
        {
          g_warning ("unable to seek to tile in buffer: %s", g_strerror (errno));
          return;
        }
      in_offset = offset;
    }

  while (to_be_read > 0)
    {
      GError *error = NULL;
      gint    byte_read;

      byte_read = read (in_fd, dest + tile_size - to_be_read, to_be_read);
      if (byte_read <= 0)
        {
          g_message ("unable to read tile data from swap: "
                     "%s (%d/%d bytes read) %s",
                     g_strerror (errno), byte_read, to_be_read, error?error->message:"--");
          return;
        }
      to_be_read -= byte_read;
      in_offset  += byte_read;
    }

  GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "read entry %i, %i, %i from %i", entry->x, entry->y, entry->z, (gint)offset);
}
コード例 #29
0
static GObject *
gegl_tile_backend_file_constructor (GType                  type,
                                    guint                  n_params,
                                    GObjectConstructParam *params)
{
  GObject             *object;
  GeglTileBackendFile *self;
  GeglTileBackend     *backend;

  object  = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
  self    = GEGL_TILE_BACKEND_FILE (object);
  backend = GEGL_TILE_BACKEND (object);

  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "constructing file backend: %s", self->path);
#if HAVE_GIO
  self->file = g_file_new_for_commandline_arg (self->path);
#else
  self->i = self->o = -1;
#endif
  self->index = g_hash_table_new (gegl_tile_backend_file_hashfunc, gegl_tile_backend_file_equalfunc);


  /* If the file already exists open it, assuming it is a GeglBuffer. */
#if HAVE_GIO
  if (g_file_query_exists (self->file, NULL))
#else
  if (access (self->path, F_OK) != -1)
#endif
    {
      goffset offset = 0;

#if HAVE_GIO
      /* Install a monitor for changes to the file in case other applications
       * might be writing to the buffer
       */
      self->monitor = g_file_monitor_file (self->file, G_FILE_MONITOR_NONE,
                                           NULL, NULL);
      g_signal_connect (self->monitor, "changed",
                        G_CALLBACK (gegl_tile_backend_file_file_changed),
                        self);

      {
        GError *error = NULL;
        self->io = G_IO_STREAM (g_file_open_readwrite (self->file, NULL, &error));
        if (error)
          {
            /* Try again but this time with only read access. This is
             * a quick-fix for make distcheck, where img_cmp fails
             * when it opens a GeglBuffer file in the source tree
             * (which is read-only).
             */
            g_error_free (error);
            error = NULL;
            self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, &error));

            if (error)
              {
                g_warning ("%s: %s", G_STRLOC, error->message);
                g_error_free (error);
                error = NULL;
              }
          }
        else
          {
            self->o = g_io_stream_get_output_stream (self->io);
            self->i = g_io_stream_get_input_stream (self->io);
          }
      }

#else
      self->o = open (self->path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
      self->i = dup (self->o);
#endif
      /*self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, NULL));*/
      self->header = gegl_buffer_read_header (self->i, &offset)->header;
      self->header.rev = self->header.rev -1;

      /* we are overriding all of the work of the actual constructor here,
       * a really evil hack :d
       */
      backend->priv->tile_width = self->header.tile_width;
      backend->priv->tile_height = self->header.tile_height;
      backend->priv->format = babl_format (self->header.description);
      backend->priv->px_size = babl_format_get_bytes_per_pixel (backend->priv->format);
      backend->priv->tile_size = backend->priv->tile_width *
                                    backend->priv->tile_height *
                                    backend->priv->px_size;

      /* insert each of the entries into the hash table */
      gegl_tile_backend_file_load_index (self, TRUE);
      self->exist = TRUE;
#if HAVE_GIO
      /* We can only assert input stream, we won't have an output
       * stream on read-only files
       */
      g_assert (self->i);
#else
      g_assert (self->i != -1);
      g_assert (self->o != -1);
#endif

      /* to autoflush gegl_buffer_set */

      /* XXX: poking at internals, icky */
      backend->priv->shared = TRUE;
    }
  else
    {
      self->exist = FALSE; /* this is also the default, the file will be created on demand */
    }

#if HAVE_GIO
  g_assert (self->file);
#endif

  backend->priv->header = &self->header;

  return object;
}
コード例 #30
0
static void
gegl_tile_backend_file_load_index (GeglTileBackendFile *self,
                                   gboolean             block)
{
  GeglBufferHeader new_header;
  GList           *iter;
  GeglTileBackend *backend;
  goffset offset = 0;
  goffset max=0;
  gint tile_size;

  /* compute total from and next pre alloc by monitoring tiles as they
   * are added here
   */
  /* reload header */
  new_header = gegl_buffer_read_header (self->i, &offset)->header;
  self->foffset = 256;

  while (new_header.flags & GEGL_FLAG_LOCKED)
    {
      g_usleep (50000);
      new_header = gegl_buffer_read_header (self->i, &offset)->header;
      self->foffset = 256;
    }

  if (new_header.rev == self->header.rev)
    {
      GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "header not changed: %s", self->path);
      return;
    }
  else
    {
      self->header=new_header;
      GEGL_NOTE(GEGL_DEBUG_TILE_BACKEND, "loading index: %s", self->path);
    }

  tile_size = gegl_tile_backend_get_tile_size (GEGL_TILE_BACKEND (self));
  offset      = self->header.next;
  self->tiles = gegl_buffer_read_index (self->i, &offset);
  self->foffset = -1;
  backend     = GEGL_TILE_BACKEND (self);

  for (iter = self->tiles; iter; iter=iter->next)
    {
      GeglBufferItem *item = iter->data;

      GeglBufferItem *existing = g_hash_table_lookup (self->index, item);

      if (item->tile.offset > max)
        max = item->tile.offset + tile_size;

      if (existing)
        {
          if (existing->tile.rev == item->tile.rev)
            {
              g_assert (existing->tile.offset == item->tile.offset);
              existing->tile = item->tile;
              g_free (item);
              continue;
            }
          else
            {
              GeglTileStorage *storage =
                (void*)gegl_tile_backend_peek_storage (backend);
              GeglRectangle rect;
              g_hash_table_remove (self->index, existing);

              gegl_tile_source_refetch (GEGL_TILE_SOURCE (storage),
                                        existing->tile.x,
                                        existing->tile.y,
                                        existing->tile.z);

              if (existing->tile.z == 0)
                {
                  rect.width = self->header.tile_width;
                  rect.height = self->header.tile_height;
                  rect.x = existing->tile.x * self->header.tile_width;
                  rect.y = existing->tile.y * self->header.tile_height;
                }
              g_free (existing);

              g_signal_emit_by_name (storage, "changed", &rect, NULL);
            }
        }
      g_hash_table_insert (self->index, iter->data, iter->data);
    }
  g_list_free (self->tiles);
  g_slist_free (self->free_list);
  self->free_list      = NULL;
  self->next_pre_alloc = max; /* if bigger than own? */
  self->total          = max;
  self->tiles          = NULL;
}