コード例 #1
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);
}
コード例 #2
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);
}
コード例 #3
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);
}
コード例 #4
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);
}
コード例 #5
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);
}
コード例 #6
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;
}