Commit a9fb1e6f authored by Øyvind Kolås's avatar Øyvind Kolås

Made on disk-buffers opened on disk perform locking when invoking

gegl_buffer_set, this allows transparent use of the buffers for writes
since only one write will happen at a time. (At the moment the lock
is implemented in the files header, and a GeglBuffer might get stuck
in a locked state on disk if gegl is aborted when it holds the lock.)
* gegl/buffer/gegl-buffer-access.c: (gegl_buffer_set): lock buffer
on write if the buffer is shared.
* gegl/buffer/gegl-buffer-index.h: fixed flags for header.
* gegl/buffer/gegl-buffer-private.h:
* gegl/buffer/gegl-buffer.c:
(gegl_buffer_is_shared): new function reports if the buffer is shared
(gegl_buffer_try_lock): tries to lock a shared buffer, if failed try
again a bit later.
(gegl_buffer_unlock): unlock a locked buffer, allows other clients to
use the buffer.
* gegl/buffer/gegl-tile-backend-file.[ch]: added _try_lock() _unlock()
* gegl/buffer/gegl-tile-backend.[ch]: added shared flag to backend.

svn path=/trunk/; revision=2258
parent 2d5b2b79
2008-04-28 Øyvind Kolås <pippin@gimp.org>
Made on disk-buffers opened on disk perform locking when invoking
gegl_buffer_set, this allows transparent use of the buffers for writes
since only one write will happen at a time. (At the moment the lock
is implemented in the files header, and a GeglBuffer might get stuck
in a locked state on disk if gegl is aborted when it holds the lock.)
* gegl/buffer/gegl-buffer-access.c: (gegl_buffer_set): lock buffer
on write if the buffer is shared.
* gegl/buffer/gegl-buffer-index.h: fixed flags for header.
* gegl/buffer/gegl-buffer-private.h:
* gegl/buffer/gegl-buffer.c:
(gegl_buffer_is_shared): new function reports if the buffer is shared
(gegl_buffer_try_lock): tries to lock a shared buffer, if failed try
again a bit later.
(gegl_buffer_unlock): unlock a locked buffer, allows other clients to
use the buffer.
* gegl/buffer/gegl-tile-backend-file.[ch]: added _try_lock() _unlock()
* gegl/buffer/gegl-tile-backend.[ch]: added shared flag to backend.
2008-04-28 Øyvind Kolås <pippin@gimp.org>
* gegl/buffer/gegl-tile-backend-file.c:
......
......@@ -579,6 +579,14 @@ gegl_buffer_set (GeglBuffer *buffer,
#if ENABLE_MP
g_static_rec_mutex_lock (&mutex);
#endif
if (gegl_buffer_is_shared(buffer))
{
while (gegl_buffer_try_lock (buffer)==FALSE)
{
g_print ("failed to aquire lock sleeping 1s");
g_usleep (1000000);
}
}
if (format == NULL)
format = buffer->format;
......@@ -602,6 +610,11 @@ gegl_buffer_set (GeglBuffer *buffer,
g_object_unref (sub_buf);
}
if (gegl_buffer_is_shared(buffer))
{
gegl_buffer_flush (buffer);
gegl_buffer_unlock (buffer);
}
#if ENABLE_MP
g_static_rec_mutex_unlock (&mutex);
#endif
......
......@@ -9,7 +9,7 @@ GeglBuffer on disk representation
/* Increase this number when the structures change.*/
#define GEGL_FILE_SPEC_REV 23
#define GEGL_FILE_SPEC_REV 0
#define GEGL_MAGIC {'G','E','G','L'}
#define GEGL_FLAG_TILE 1
......@@ -21,9 +21,9 @@ GeglBuffer on disk representation
/* these flags are used for the header, the lower bits of the
* header store the revision
*/
#define GEGL_FLAG_LOCKED (0xff*(1<<0))
#define GEGL_FLAG_FLUSHED (0xff*(1<<1))
#define GEGL_FLAG_IS_HEADER (0xff*(1<<3))
#define GEGL_FLAG_LOCKED (1<<(8+0))
#define GEGL_FLAG_FLUSHED (1<<(8+1))
#define GEGL_FLAG_IS_HEADER (1<<(8+3))
/* The default header we expect to see on a file is that it is
* flushed, and has the revision the file conforms to written
......
......@@ -91,4 +91,9 @@ void gegl_tile_cache_destroy (void);
GeglTileBackend * gegl_buffer_backend (GeglBuffer *buffer);
gboolean gegl_buffer_is_shared (GeglBuffer *buffer);
gboolean gegl_buffer_try_lock (GeglBuffer *buffer);
gboolean gegl_buffer_unlock (GeglBuffer *buffer);
#endif
......@@ -1009,3 +1009,24 @@ done_with_row:
}
}
}
gboolean gegl_buffer_is_shared (GeglBuffer *buffer)
{
GeglTileBackend *backend = gegl_buffer_backend (buffer);
return backend->shared;
}
gboolean gegl_buffer_try_lock (GeglBuffer *buffer)
{
GeglTileBackend *backend = gegl_buffer_backend (buffer);
if (!backend->shared)
return FALSE;
return gegl_tile_backend_file_try_lock (GEGL_TILE_BACKEND_FILE (backend));
}
gboolean gegl_buffer_unlock (GeglBuffer *buffer)
{
GeglTileBackend *backend = gegl_buffer_backend (buffer);
if (!backend->shared)
return FALSE;
return gegl_tile_backend_file_unlock (GEGL_TILE_BACKEND_FILE (backend));
}
......@@ -681,7 +681,7 @@ load_index (GeglTileBackendFile *self)
GeglBufferHeader new_header;
GList *iter;
GeglTileBackend *backend;
goffset offset;
goffset offset = 0;
goffset max=0;
/* compute total from and next pre alloc by monitoring tiles as they
......@@ -689,6 +689,13 @@ load_index (GeglTileBackendFile *self)
*/
/* reload header */
new_header = gegl_buffer_read_header (self->i, &offset)->header;
while (new_header.flags & GEGL_FLAG_LOCKED)
{
g_usleep (500000);
new_header = gegl_buffer_read_header (self->i, &offset)->header;
}
if (new_header.rev == self->header.rev)
{
GEGL_NOTE(TILE_BACKEND, "header not changed: %s", self->path);
......@@ -827,6 +834,9 @@ gegl_tile_backend_file_constructor (GType type,
self->exist = TRUE;
g_assert (self->i);
g_assert (self->o);
/* to autoflush gegl_buffer_set */
backend->shared = TRUE;
}
else
{
......@@ -928,3 +938,31 @@ gegl_tile_backend_file_init (GeglTileBackendFile *self)
self->next_pre_alloc = 256; /* reserved space for header */
self->total = 256; /* reserved space for header */
}
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;
write_header (self);
g_output_stream_flush (self->o, NULL, NULL);
return TRUE;
}
gboolean gegl_tile_backend_file_unlock (GeglTileBackendFile *self)
{
if (!(self->header.flags & GEGL_FLAG_LOCKED))
{
g_warning ("tried to unlock unlocked buffer");
return FALSE;
}
self->header.flags -= GEGL_FLAG_LOCKED;
write_header (self);
g_output_stream_flush (self->o, NULL, NULL);
return TRUE;
}
......@@ -44,6 +44,9 @@ GType gegl_tile_backend_file_get_type (void) G_GNUC_CONST;
void gegl_tile_backend_file_stats (void);
gboolean gegl_tile_backend_file_try_lock (GeglTileBackendFile *file);
gboolean gegl_tile_backend_file_unlock (GeglTileBackendFile *file);
G_END_DECLS
#endif
......@@ -159,4 +159,5 @@ gegl_tile_backend_class_init (GeglTileBackendClass *klass)
static void
gegl_tile_backend_init (GeglTileBackend *self)
{
self->shared = FALSE;
}
......@@ -43,6 +43,7 @@ struct _GeglTileBackend
/* private */
gpointer header;
gpointer storage;
gboolean shared;
};
struct _GeglTileBackendClass
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment