Re: Plans for gnome-vfs replacement

On Wed, 2006-09-20 at 12:55 +0200, Mathieu Lacage wrote:
> On Wed, 2006-09-20 at 12:31 +0200, Alexander Larsson wrote:
> > Here is my current GInputStream:
> very nice. Comments below.
> > 
> > struct _GInputStreamClass
> > {
> >   GObjectClass parent_class;
> > 
> >   /* Sync ops: */
> >   
> Do you dislike the idea of moving the GError as a member of the
> GInputStream instance ?

Its very uncommon, I'm not sure people will expect that. It will also
break things from language mappings that handle GErrors in a special way
(say, as an exception).

> >   gssize   (* read)        (GInputStream *stream,
> > 			    void         *buffer,
> > 			    gsize         count,
> > 			    GError      **error);
> >   gssize   (* skip)        (GInputStream *stream,
> > 			    gsize         count,
> > 			    GError      **error);
> >   gboolean (* close)	   (GInputStream *stream,
> > 			    GError      **error);
> > 
> 1) Don't you think it might make sense to also add an io priority arg to
> the sync functions ?

Possibly. It wouldn't really be implementable for normal local files,
but could help for e.g. vfs streams from the daemon. It seems much more
useful for async operations though, since its generally only when you
use those that you get multiple outstanding operations at the same time.

> 2) What is the signature of GDestroyNotify ?

Its already in gtypes.h:
typedef void            (*GDestroyNotify)       (gpointer       data);

> 3) Do you expect GDestroyNotify to be invoked afer GAsyncReadCallback
> during normal successful reads ?

Yes. And also after unsuccessful reads. Even cancelled reads (with a
cancelled error). The callback will always be called to avoid the tricky
leaks we have in gnome-vfs. Here is the docs for cancel:

 * g_input_stream_cancel:
 * @stream: A #GInputStream.
 * @tag: a value returned from an async request
 * Tries to cancel an outstanding request for the stream. If it
 * succeeds the outstanding request callback will be called with
 * Generally if a request is cancelled before its callback has been
 * called the cancellation will succeed and the callback will only
 * be called with %G_VFS_ERROR_CANCELLED. However, if multiple threads
 * are in use this cannot be guaranteed, and the cancel may not result
 * in a %G_VFS_ERROR_CANCELLED callback.
 * The asyncronous methods have a default fallback that uses threads to implement
 * asynchronicity, so they are optional for inheriting classes. However, if you
 * override one you must override all.
> > For writing a file things are a bit more complex. An example API set
> > could be:
> > GOutputStream *g_file_append_to (GFile *file);
> > GOutputStream *g_file_create    (GFile *file);
> > GOutputStream *g_file_replace   (GFile *file,
> > 		                 time_t mtime_of_old_version, /* optional */
> > 	                         char *backup_name /* optional */ );
> > 
> > Error handling on open is handled by the stream (to avoid forcing a sync
> > open). The replace operation does the optimal handling of atomic replace
> > and backup for the specific backend.
> Are you saying that _append and _create would not be synchronous
> operations ? If so, what happens if I attempt a sync read after an async
> _append and the async _append fails ? Will the sync read fail and report
> the error of the async _append ? Is there a way to schedule an open
> barrier ? that is, be notified upon open completion with the operation
> status ?

I'm not sure what you mean here. Consider a GFile a wrapper for a
filename. Each of the append_to/create/replace calls constitues an open
of the filename plus a number of writes (to the stream). No operation
returns an Input stream, so you can only write (there is no support for
read/write opens, as this is impossible to implement in many cases). The
operations vary in how they treat a possible already existing file with
the specified name. append_to will append the new data at the end,
create will fail if it already exists, and replace will replace the
contents of the existing file, optionally creating a backup or failing
if the file exiting file isn't the same mtime as you expected.

Parallel opens for write of a file have implementation defined
behaviour. (Things will depend a lot on the exact timing.)

What I mean by async opens is that if I open a non-existing file for
reading, the open will succeed, giving me a input stream that will cause
a no-such-file error when you start reading from it. The alternative
would be that the open call blocks, doing i/o to see if the open
succeeds. That would be bad if you were opening the file for async use.
If you do async read on the new input stream the first async read will
also implicitly do an async open.

As to barriers and stuff, I've taken the simple route. Once a stream is
created you can only have one outstanding request (be it sync or async),
and any other operation during this time will return
G_VFS_ERROR_PENDING. Many streams (take a ftp put for instance) just
doesn't support multiple requests.

 Alexander Larsson                                            Red Hat, Inc 
                   alexl redhat com    alla lysator liu se 
He's an uncontrollable small-town grifter possessed of the uncanny powers of 
an insect. She's a time-travelling renegade mermaid descended from a line of 
powerful witches. They fight crime! 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]