[sane-devel] SANE V2

Henning Meier-Geinitz henning@meier-geinitz.de
Wed, 11 Dec 2002 00:20:58 +0100


On Tue, Dec 10, 2002 at 01:03:00PM -0500, Matto Marjanovic wrote:
>  >If I understand correctly what happens in the case of auth_callback,
>  >the remote sane_func isn't finished yet, the callback is still running.
>  >
>  >>   o Network backend calls the client frontend's callback with string,
>  >>      then finally returns from "sane_func()" request.
>  >
>  >First the net backend calls the RPC for sane_func again, saned returns
>  >from the clalbach, the remote frontend returns from sane_func() and
>  >give the result back all the way to the local frontend.
> Yeah, this/that occurred to me later last night.  
>   o When the device backend invokes the callback, saned can return an early
>      response to the client backend "I'm not done with the last operation,
>      but please invoke a callback for me."

Exactly, there is a parameter that is returned by saned to the net
backend in every function where a callback can be called. If this
string is !=0, the function isn't finished but the callback must be

>   o The client net backend invokes the real callback, and then sends the
>      return status to saned in another RPC call "Here is the result of the
>      callback; now finish what you were doing.".
>   o Saned returns the result to the device backend, and everything keeps
>      on going as before (i.e. eventually the backend returns from whatever
>      sane_func(), and then saned sends a closing response to the client).
> Is this how it is implemented?  (I took a quick look at the net backend,
>  and discovered that a quick look is not enough.)

I think you described the implementation correctly.

> Neither the current SANE standard nor the v2 draft say anything about
> callbacks.

SANE_NET_AUTHORIZE *is* described in the network part of the standard.
However, the current implementation doesn't match the standard. At
least, that's my understanding. The standard says, that the operation
has to be retried after SANE_NET_AUTHORIZE. I would have thought that
the whole RPC would have to be called again (e.g. SANE_NET_OPEN), but
the implementation shows that only the response is gotten again.

So I would call this a big bug in either the implementation or the
standard. The standard concerning networking doesn't go into taht much
details, anyway.

> The big question I have is:  How is an asynchronous sane_cancel() invoked???

I haven't tried but the code looks like: It isn't. You can't do it.
Cancelling during sane_read seems to work because the data transport
is on a different port. However cancelling sane_start won't work.

>  [getting back to verbose errors...]
>  ...
>  >As far as I understood the comment about thread-safety (from David
>  >Mosberger-Tang) is about interface definition, not implementation.
>  ...
>  >So I guess the following won't hurt:
>  >
>  >void
>  >sane_verbose_error(Sane_Handle h, SANE_String * verbose_message,
>  >                   SANE_Int lenght)
>  >
>  >The the frontend can decide what to do with the string, e.g. print it
>  >later.
> I don't see how it helps, and I think it does hurt:
> a) This doesn't have any impact on thread safety:

I'm really no expert in thread-safety at all. In fact, I don't think I
have ever written a threaded program. So I'm just referring to what
David said.

>     this function still cannot
>     be called while another sane_func(h, ...) is executing --- that other
>     function might be in the middle of rewriting the backend's "verbose
>     message buffer".

It could lock the buffer.

>    Furthermore, without the requirement that this function is called
>     synchronously, it becomes ambiguous which error it refers to.

That's true.

> b) Now the frontend has to preallocate a buffer to receive the message,
>     which will probably only be read once.  How big should that buffer be?
>     How will the frontend know if the message has been truncated because
>     its buffer is too small?
> In the original version, if the frontend wants to keep the string around
>  after the next sane_func(h, ...), it can just strdup() it.
Ok. I don't object. 

> Hmm... you know what, we've overlooked something.
> What about a verbose error message for those functions which don't require
>  a device handle?

True, the handle won't work.

>  >As far as I understood the comment about thread-safety (from David
>  >Mosberger-Tang) is about interface definition, not implementation.
>  >
>  >So even if the current implementation doesn't allow simuktaneous
>  >operation of SANE function, a later one may do. And we are in trouble
>  >then. All the other function definitions seem to be thread-safe.
> Ok, this is worthy of some discussion.

[Long and interesting discussion on which operations can be called at
which times snipped]

Well, my conclusion is: don't do it. I mean: don't call the functions
simultaneously. It just too much chaos in my opinion.
If you want to support more then one device in one backend just fork.

>   Hmmm... so, back to sane_verbose_error(H, ):
>      sane_init(), sane_open(), and sane_get_devices() all return a
>       SANE_Status, and for the first two, at least, one might want to see
>       a more verbose message/explanation from the backend.
>      If these functions are all required to be called synchronously, then
>       we could simply say that
>                  sane_verbose_error(NULL, ...)
>       returns the "most recent global verbose message".

That's a possibility. But it makes it a bit more complicated.

But with the above stated opinion, we could also just use
sane_verbose_error() (no argument) for everything.

Maybe someone else has better ideas :-)