> > After tracing through the w3lib code, I realise that the status
> > code returned by the MIME stream to the Tee stream could be the
> > reason. The Tee stream would only return a HT_OK if both of its
> > streams return HT_OK or a HT_ERROR if both of its stream return
> > HT_ERROR. HT_WOULDBLOCK is returned otherwise.
This is correct - H&kon mentioned this to me the other day while working on
Arena and he provided a patch _very_ similar to yours!
> > In my case, the MIME stream returns a HT_LOADED while the CACHE
> > stream returns a HT_OK. This cause the Tee stream to return a
> > HT_WOULDBLOCK. I'm not clear why the MIME should return a HT_LOADED
> > at times intead of a generic HT_OK. Any pointers on how I can remedy
> > the situation?
> I had a similar problem just a couple of days ago. Indeed, it's the code in HTTee.c
> which is making all the trouble. The rule to compute the return value from two streams
> is (for me) very strange. The same rule is used in almost all HTTee_ functions, here I
> give HTTee_put_character as an example:
>
> PRIVATE int HTTee_put_character (HTStream * me, char c)
> {
> int ret1 = (*me->s1->isa->put_character)(me->s1, c);
> int ret2 = (*me->s2->isa->put_character)(me->s2, c);
> return (!(ret1+ret2) ? HT_OK :
> (ret1==HT_ERROR || ret2==HT_ERROR) ? HT_ERROR :
> HT_WOULD_BLOCK);
> }
Very good observation and good patch!
> If we use the cache, the HTTee stream is used to pass data to MIME and
> Cache streams. MIME stream returns HT_LOADED after all the data has been
> loaded. In HTUtils.h HT_LOADED is defined as a success code. Cache stream
> returns HT_OK, which obviously also signifies the success. According to the rule
> given above, these two success codes merge into HT_WOULD_BLOCK, which is
> defined as a failure code!
>
> HT_WOULD_BLOCK is actually not a "real" failure, but also not a success. After
> receiving such a code functions which put the data into the stream stack enter the
> waiting state. They are waiting for some event to put them out of that state, however
> nothing comes, since all data has been already transmitted.
A stream can now return "control" information by using the return codes of the
method. This is an easy way to propagate control information upstream. Another
method is to use the Error object but this makes it harder to analyse and
often this would be too heavy weight a solution.
However, "abort" is normally a result of an error that may propagete all the
way back to the user, for example, disk full etc. This is the reason why the
abort element has a list object as part of the calling parameters. This list
can be used to pass a list of error objects so that each stream can add its
explanation to why things went wrong.
A stream has 3 possibilities when returning a status code:
ERROR < 0 Write error, would block etc.
OK = 0 Everything OK
SUCCESS > 0 Document loaded, etc.
Your patch looks like:
> int merge_results (int ret1, int ret2)
> {
> if (ret1 == HT_OK)
> return ret2;
> else if (ret2 == HT_OK)
> return ret1;
> else if (ret1 == HT_ERROR || ret2 == HT_ERROR)
> return HT_ERROR;
> else
> return ret1;
> }
The patch from H&kon uses this information like this:
if (ret1 < HT_OK) /* howcome 6 dec 95 */
return ret1;
if (ret2 < HT_OK)
return ret2;
if (ret1 == HT_OK)
return ret2;
return ret1;
> The merge_results functions treats streams asymmetrically. It assumes that the
> ret1 is more important than ret2 (see the last line: return ret1). This is indeed the case
> of the MIME/Cache pair, where writing to cache is obviously less important than
> presenting the document to the user.
Again, ret1 is the most important code.
> In this particular situation my rule works perfectly, however it's tricky and perhaps not
> suitable in some cases. I think the problem deserves a deeper study (and discussion).
> Frankly speaking, I can't imagine any reasonable general-purpose rule for merging
> results from two streams. Perhaps the whole mechanism of passing result codes
> should be changed? To what? Or simply rethinking and changing the set of result
> codes would solve the problem?
We can either say that this is a problem with a T stream or change the status
code numbers and use bitflags instead. Error codes can still be negative by
haing the MSB set to 1. This way you can easily check for error/success _and_
at the same time return multiple return codes. Does anybody see a problem with
this except that you need to use binary operations on the return values?
--
Henrik Frystyk Nielsen, <frystyk@w3.org>
World-Wide Web Consortium, MIT/LCS NE43-356
545 Technology Square, Cambridge MA 02139, USA