static gboolean gegl_tile_backend_file_write_header (GeglTileBackendFile *self) { gboolean success; gegl_tile_backend_file_ensure_exist (self); #if HAVE_GIO success = g_seekable_seek (G_SEEKABLE (self->o), 0, G_SEEK_SET, NULL, NULL); #else success = (lseek (self->o, 0, SEEK_SET) != -1); #endif if (success == FALSE) { g_warning ("unable to seek in buffer"); return FALSE; } #if HAVE_GIO g_output_stream_write (self->o, &(self->header), 256, NULL, NULL); #else write (self->o, &(self->header), 256); #endif GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "Wrote header, next=%i", (gint)self->header.next); return TRUE; }
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; }
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); }
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); }
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); }
static gboolean gegl_tile_backend_file_write_header (GeglTileBackendFile *self) { gboolean success; gegl_tile_backend_file_ensure_exist (self); success = (lseek (self->o, 0, SEEK_SET) != -1); if (success == FALSE) { g_warning ("unable to seek in buffer"); return FALSE; } write (self->o, &(self->header), 256); self->foffset = 256; GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "Wrote header, next=%i", (gint)self->header.next); return TRUE; }
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; }
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; }
static gboolean gegl_tile_backend_file_write_block (GeglTileBackendFile *self, GeglBufferBlock *block) { gegl_tile_backend_file_ensure_exist (self); if (self->in_holding) { guint64 next_allocation = self->offset + self->in_holding->length; /* update the next offset pointer in the previous block */ if (block == NULL) /* the previous block was the last block */ self->in_holding->next = 0; else self->in_holding->next = next_allocation; if (self->foffset != self->offset) { if(lseek (self->o, self->offset, G_SEEK_SET) == -1) goto fail; self->foffset = self->offset; } /* XXX: should promiscuosuly try to compress here as well,. if revisions are not matching.. */ GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "Wrote block: length:%i flags:%i next:%i at offset %i", self->in_holding->length, self->in_holding->flags, (gint)self->in_holding->next, (gint)self->offset); { ssize_t written = write (self->o, self->in_holding, self->in_holding->length); if(written != -1) { self->offset += written; self->foffset += written; } } 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 (self->foffset != self->offset) { if(lseek (self->o, self->offset, G_SEEK_SET) == -1) goto fail; self->foffset = self->offset; } } self->in_holding = block; return TRUE; fail: g_warning ("gegl buffer index writing problems for %s", self->path); return FALSE; }
static gboolean gegl_tile_backend_file_write_block (GeglTileBackendFile *self, GeglBufferBlock *block) { gegl_tile_backend_file_ensure_exist (self); 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 HAVE_GIO if(!g_seekable_seek (G_SEEKABLE (self->o), self->offset, G_SEEK_SET, NULL, NULL)) #else if(lseek (self->o, self->offset, G_SEEK_SET) == -1) #endif goto fail; GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "Wrote block: length:%i flags:%i next:%i at offset %i", self->in_holding->length, self->in_holding->flags, (gint)self->in_holding->next, (gint)self->offset); #if HAVE_GIO self->offset += g_output_stream_write (self->o, self->in_holding, self->in_holding->length, NULL, NULL); #else { ssize_t written = write (self->o, self->in_holding, self->in_holding->length); if(written != -1) self->offset += written; } #endif 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 HAVE_GIO if(!g_seekable_seek (G_SEEKABLE (self->o), (goffset) self->offset, G_SEEK_SET, NULL, NULL)) #else if(lseek (self->o, self->offset, G_SEEK_SET) == -1) #endif goto fail; } self->in_holding = block; return TRUE; fail: g_warning ("gegl buffer index writing problems for %s", self->path); return FALSE; }