Scott,

So just to reiterate what your saying... in the case of the uriloader, 
the setup done in OnStartRequest would always have to be done in order 
to handle a OnStopRequest... so, in this case there is no way to bypass 
OnStartRequest.  If we allowed OnStopRequest to occur without a 
preceding OnStartRequest, then the uriloader would have to check for 
this condition and then call OnStartRequest itself.  Am I correct so 
far?  This seems like it would overly complicate the uriloader... which 
leads me to think that we should probably just forget about trying to 
decouple OnStartRequest and OnStopRequest.  Anyways, we are talking 
about how to optimize an error path.... probably not the most important 
thing right now :)

Darin



Scott MacGregor wrote:

> The uri loader requires an OnStartRequest in order to find an 
> appropriate consumer for the content. Until an OnStart is issued, the 
> uriloader is the only one receiving nsIStreamListener notifications. 
> So if you try to bypass the OnStart and call using a new OnFailure 
> method or just the OnStopRequest your operation will fall on the 
> floor. The uriloader will get the OnStop/OnFailure notification, 
> notice that it doesn't have a consumer for the stream to forward these 
> notifications to and will just stop processing things.
> 
> So I'm not sure what we'd gain with bypassing OnStartRequest withouht 
> over hauling the uriloader as well.
> 
> Hope that helps,
> -Scott
> 
> Judson Valeski wrote:
> 
>> Scott, talk to us about the docloader.
>> 
>> Darin Fisher wrote:
>> 
>>> Judson Valeski wrote:
>>> 
>>>> Doug's got it :-). Rick Potts and I just got off the phone and he 
>>>> refreshed my memory a bit.
>>>> 
>>>> The "original" semantics of nsIStreamObserver were such that 
>>>> OnStart was called to indicate that the data trying to be reached 
>>>> (the URI) had been reached (the file:// file had successfully ben 
>>>> fopen'd, the http:// host socket had been connected. the definition 
>>>> of "reach" is up to the transport). You'd get an OnStop indicating 
>>>> the transaction was complete (whether for connection failure 
>>>> reasons, data transport failure reasons (timeout)).
>>> 
>>> 
>>> 
>>> 
>>> Right, this makes sense.  But, what if "the data trying to
>>> be reached had [NOT] been reached?" 
>> 
>> 
>> 
>> If you resolve the server and connect (or open the file), you get an 
>> OnStart(). If you fail from that point forward (read timeout for 
>> example) you go straight to OnStop() w/ an error code. If the connect 
>> failed, you would not get an onstart, and you'd go straight to onstop.
>> 
>>>> So, Darin, if we break the semantics of *always* coupling an 
>>>> OnStart w/  an OnStop, we can use OnStop to do what you're 
>>>> proposing. The consumer  would only do setup type stuff in OnStart 
>>>> (w/ out fear of doing it for  no good reason), and their OnStop 
>>>> would always check the nsresult passed  in to decide whether or not 
>>>> to finish the transaction and clean up their  init'd stuff.
>>> 
>>> 
>>> 
>>> 
>>> So you are suggesting that a particular set of nsresult
>>> values would indicate failure _without_ the need to clean
>>> up their init'd stuff?  And, that another set of nsresult
>>> values would indicate failure _with_ the need to clean up
>>> their init'd stuff?  This sounds complicated. 
>> 
>> 
>> 
>> No, that's up to the consumer's impl. Here's mine.
>> 
>> judsimpl::OnStart() {
>> // the transaction has "started"
>> mMyPrivateData = new foo();
>> }
>> 
>> judsimpl::OnStop(..., status) {
>> 
>> if (NS_FAILED(status)) {
>>   // shit hit the fan, if we had started the transaction, be sure to 
>> clean up.
>>   if (mMyPrivateData) {
>>       // transaction had started because my otherwise null private 
>> data has been allocated.
>>       delete mMyPrivateData;
>>       // do whatever else cleanup I need to do now that the 
>> transaction is over
>>   } else {
>>       // transaction never even started.
>>       // don't have to cleanup my init data.
>>   }
>> } else {
>>   // all went well.
>>   if (mMyPrivateData) { // mMyPrivate data will always be non-null 
>> here, but I'm being safe.
>>       // transaction had started because my otherwise null private 
>> data has been allocated.
>>       delete mMyPrivateData;
>>       // do whatever else cleanup I need to do now that the 
>> transaction is over         }
>>   return rv;
>> }
>> 
>> As you can see, you can almost ignore the status code in this case 
>> and just use the mMyPrivateData var as a boolean check as well. I'm 
>> not seeing any complexity here. nsresult codes already are broken 
>> into failure and non-failure ranges (macro'ized via NS_FAILED() & 
>> NS_SUCCEEDED())
>> 
>>> Perhaps it would be just simpler for the listener to keep
>>> track of whether or not OnStartRequest was called.  This
>>> need not be an explicit variable... the listener could
>>> just check to see if something was init'd or not. 
>> 
>> 
>> 
>> lol. why oh why don't I read all my email before diving in :-). You 
>> got it! The error code can be useful though (say you wanted to throw 
>> a dialog indicating what the error was for example).
>> 
>>>> We tried to enforce these semantics in the past and were pushed to  
>>>> provide the OnStart/OnStop coupling semantics, but we should 
>>>> probably  move back to OnStart on successful "start" followed by 
>>>> OnStop (so OnStop  can act alone).
>>> 
>>> 
>>> 
>>> 
>>> The problem, as I understand it, is that if we allow OnStop
>>> acting alone, we are going to get many crashes... as the
>>> code in the various OnStop's tend to assume OnStart has been
>>> called.  But, these could be considered bugs and then fixed. 
>> 
>> 
>> 
>> exactly!
>> 
>>>> Scott,
>>>>     Does the docloader propegate OnStart's in failure cases? If so, 
>>>> do you think it's heavy to change that?
>>>> 
>>>> Doug,
>>>>     Currently FTP fires OnStart's in error cases, we'd need to 
>>>> change that?
>>> 
>>> 
>>> 
>>> 
>>> HTTP does this too. 
>> 
>> 
>> 
>> we'd need to clean that up too obviously.
>> 
>> Jud
>> 
> 


Reply via email to