gboolean gegl_tile_backend_file_try_lock (GeglTileBackendFile *self) { GeglBufferHeader new_header; new_header = gegl_buffer_read_header (self->i, NULL)->header; if (new_header.flags & GEGL_FLAG_LOCKED) { return FALSE; } self->header.flags += GEGL_FLAG_LOCKED; gegl_tile_backend_file_write_header (self); fsync (self->o); return TRUE; }
gboolean gegl_tile_backend_file_try_lock (GeglTileBackendFile *self) { GeglBufferHeader new_header; new_header = gegl_buffer_read_header (self->i, NULL)->header; if (new_header.flags & GEGL_FLAG_LOCKED) { return FALSE; } self->header.flags += GEGL_FLAG_LOCKED; gegl_tile_backend_file_write_header (self); #if HAVE_GIO g_output_stream_flush (self->o, NULL, NULL); #else fsync (self->o); #endif return TRUE; }
GeglBuffer * gegl_buffer_load (const gchar *path) { GeglBuffer *ret; LoadInfo *info = g_slice_new0 (LoadInfo); info->path = g_strdup (path); info->i = g_open (info->path, O_RDONLY, 0770); GEGL_NOTE (GEGL_DEBUG_BUFFER_LOAD, "starting to load buffer %s", path); if (info->i == -1) { GEGL_NOTE (GEGL_DEBUG_BUFFER_LOAD, "failed top open %s for reading", path); return NULL; } { GeglBufferItem *header = gegl_buffer_read_header (info->i, &info->offset); g_assert (header); /*memcpy (&(info->header), header, sizeof (GeglBufferHeader));*/ info->header = *(&header->header); info->offset = info->header.next; /*g_free (header);*/ /* is there a pointer to a string or something we're missing? */ } info->tile_size = info->header.tile_width * info->header.tile_height * info->header.bytes_per_pixel; info->format = babl_format (info->header.description); ret = g_object_new (GEGL_TYPE_BUFFER, "format", info->format, "tile-width", info->header.tile_width, "tile-height", info->header.tile_height, "height", info->header.height, "width", info->header.width, "path", path, NULL); /* sanity check, should probably report error condition and return safely instead */ g_assert (babl_format_get_bytes_per_pixel (info->format) == info->header.bytes_per_pixel); info->tiles = gegl_buffer_read_index (info->i, &info->offset); /* load each tile */ { GList *iter; gint i = 0; for (iter = info->tiles; iter; iter = iter->next) { GeglBufferTile *entry = iter->data; guchar *data; GeglTile *tile; tile = gegl_tile_source_get_tile (GEGL_TILE_SOURCE (ret), entry->x, entry->y, entry->z); if (info->offset != entry->offset) { seekto (info, entry->offset); } /*g_assert (info->offset == entry->offset);*/ g_assert (tile); gegl_tile_lock (tile); data = gegl_tile_get_data (tile); g_assert (data); { ssize_t sz_read = read (info->i, data, info->tile_size); if(sz_read != -1) info->offset += sz_read; } /*g_assert (info->offset == entry->offset + info->tile_size);*/ gegl_tile_unlock (tile); gegl_tile_unref (tile); i++; } GEGL_NOTE (GEGL_DEBUG_BUFFER_LOAD, "%i tiles loaded",i); } GEGL_NOTE (GEGL_DEBUG_BUFFER_LOAD, "buffer loaded %s", info->path); load_info_destroy (info); return ret; }
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; }
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; }
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; }