[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]
Subject: Re: [wsbpel] Issue 6 - Rough draft of proposal for vote
Danny van der Rijn wrote: > i apologize for not being more explicit to begin with but imagine the > following scenario, based on your example. to borrow a phrase, this > is based on my lay understanding of the spec, and i apologize again in > advance if this reasoning is incorrect. > > - outer scope initializes and sets counter to 0. > - flow initializes. > - each of 3 scopes initializes in parallel > - the ... section of the first 2 scopes completes at the same time; > the 3rd one hangs "forever," or for close enough to forever to satisfy > the forever test. > - the assigns of the first 2 scopes evaluate the "from" portion > simultaneously, yielding a value of 1. > - the "to" portions of the assign happen in some order. doeesn't matter. Wouldn't happen, since the assign is atomic. Assaf > > now counter has miscounted, since 2 branches have completed, yet only > 1 completion is "recorded." > > the flow will "never" complete. > > this would be solved if the leaf scopes were serializable. have some > implicit concurrency control would be the huge advantage IMO, of > having built-in N of M syntax. not that i'm necessarily advocating > that complexity, but i think that if it is a common enough use case > (which i think is really the crux of the issue) then asking people to > get this right on their own is giving them enough rope to hang > themselves, as well as giving them a boy scout knot-tying manual. > > > > > Yaron Y. Goland wrote: > >> What the code implements is a 'at least N out of M'. >> >> Generally when we have N out of M scenarios (which are pretty rare, >> most of our flow + break scenarios tend to be 'first to finish') the >> goal is to make sure that at least N happens. If more than N happens >> that's o.k. too. >> >> Put another way, try to imagine a scenario where you want exactly N >> out of M. Why is 'exactly' important? Heck, what does 'exactly' even >> mean? My suspicion is that any scenario where 'at least N out of M' >> doesn't work requires either full serialization of all the code or 2PC. >> >> Just a guess, >> >> Yaron >> >> Danny van der Rijn wrote: >> >>> >>> >>> in that case, don't you have some serious concurrency issues? >>> >>> Yaron Y. Goland wrote: >>> >>> > Actually no. I just meant them as generic wrappers. I could just as >>> > easily have used sequence instead of scope. >>> > >>> > Danny van der Rijn wrote: >>> > >>> >> >>> >> >>> >> i assume that the leaf scopes are serializable and that's why >>> they're >>> >> there? >>> >> >>> >> Yaron Y. Goland wrote: >>> >> >>> >> > Below is an example of 2 out of 3, it is generalizable from >>> there. >>> >> > >>> >> > scope >>> >> > variables >>> >> > variable name="counter" type="xs:int" >>> >> > sequence >>> >> > assign >>> >> > copy >>> >> > from literal="true" >>> >> > "0" >>> >> > to >>> >> > $counter >>> >> > flow >>> >> > scope >>> >> > ... >>> >> > assign >>> >> > copy >>> >> > from >>> >> > $counter + 1 >>> >> > to >>> >> > $counter >>> >> > switch >>> >> > case >>> >> > condition >>> >> > $counter >= 2 >>> >> > break >>> >> > scope >>> >> > ... >>> >> > assign >>> >> > copy >>> >> > from >>> >> > $counter + 1 >>> >> > to >>> >> > $counter >>> >> > switch >>> >> > case >>> >> > condition >>> >> > $counter >= 2 >>> >> > break >>> >> > scope >>> >> > ... >>> >> > assign >>> >> > copy >>> >> > from >>> >> > $counter + 1 >>> >> > to >>> >> > $counter >>> >> > switch >>> >> > case >>> >> > condition >>> >> > $counter >= 2 >>> >> > break >>> >> > >>> >> > >>> >> > Trickovic, Ivana wrote: >>> >> > >>> >> >> >>> >> >> >>> >> >> Yaron, >>> >> >> >>> >> >> Would you illustrate how break activity could be used? How >>> does it >>> >> >> resolve problems tackled by proposals we have on table at the >>> >> moment? >>> >> >> >>> >> >> Regards, >>> >> >> >>> >> >> Ivana >>> >> >> >>> >> >> > -----Original Message----- >>> >> >> > From: Yaron Y. Goland [mailto:ygoland@bea.com] >>> >> >> > Sent: Dienstag, 14. September 2004 00:01 >>> >> >> > To: Alex Yiu >>> >> >> > Cc: Trickovic, Ivana; Axel Martens; Frank Leymann; Dieter >>> >> >> > Roller; Dieter >>> >> >> > Koenig1; edwink@collaxa.com; satisht@microsoft.com; >>> >> >> > wsbpel@lists.oasis-open.org >>> >> >> > Subject: Re: [wsbpel] Issue 6 - Rough draft of proposal >>> for vote >>> >> >> > >>> >> >> > >>> >> >> > I believe that the complexity of the current proposal is >>> well >>> >> >> > above the >>> >> >> > capabilities of what I expect to be the average BPEL >>> programmer. >>> >> >> > Completion conditions, ignorable faults, new XPATH >>> functions, >>> >> etc. >>> >> >> > introduces a lot of complexity that I believe that >>> average BPEL >>> >> >> > programmer would not be interested in dealing with. >>> >> >> > >>> >> >> > We know from many decades of language experience that >>> average >>> >> >> > programmers can deal with break/continue. I know from at >>> >> >> > least our own >>> >> >> > experience at BEA that users can deal with the concept of a >>> >> >> > flow where a >>> >> >> > break in the flow results in the other members of the >>> flow being >>> >> >> > terminated in the BPEL meaning of the term. >>> >> >> > >>> >> >> > Defining a break activity and specifying that if break is >>> used >>> >> in the >>> >> >> > context of flow then this means that the flow activity ends >>> >> and any >>> >> >> > uncompleted members of the flow are terminated would both >>> fit >>> >> >> > directly >>> >> >> > into BPEL's existing syntax and semantics and I believe be >>> >> >> > simple enough >>> >> >> > that the average programmer can handle it. I would therefore >>> >> >> > offer break >>> >> >> > (and it's relative 'continue') as an alternative. >>> >> >> > >>> >> >> > Thanks, >>> >> >> > >>> >> >> > Yaron >>> >> >> > >>> >> >> > Alex Yiu wrote: >>> >> >> > >>> >> >> > > >>> >> >> > > Hi, >>> >> >> > > >>> >> >> > > Ivana, thanks for sending out this proposal. >>> >> >> > > I believe a number of us (including me) like the >>> >> >> > <completionConditon> >>> >> >> > > construct from your proposal high level speaking. >>> >> >> > > >>> >> >> > > After reading the proposal, I guess we need to work on a >>> >> number of >>> >> >> > > details. I would like to ask a few questions / mention >>> a few >>> >> >> points: >>> >> >> > > >>> >> >> > > * Minor syntax and semantics questions : >>> >> >> > > o Do we want to allow expression for branch >>> >> >> > attribute? instead >>> >> >> > > of just a constant integer? >>> >> >> > > o We may need to some minor syntax adjustment >>> for >>> >> >> > expression >>> >> >> > > attribute because we have passed Isseu 13 >>> already. >>> >> >> > > o If answers to the above question are yes, then >>> >> >> > the condition >>> >> >> > > syntax may become a choice (xsd:choice) of the >>> >> >> > following two: >>> >> >> > > <condition >>> >> >> > > > >>> >> >> expressionLanguage="anyURI"?>boolean-expression</condition> >>> >> >> > > <branchCondition >>> >> >> > > > >>> >> >> expressionLanguage="anyURI"?>integer-expression</condition> >>> >> >> > > >>> >> >> > > * About completionConditionFailure : it looks like a >>> >> >> > nice idea so >>> >> >> > > far ... >>> >> >> > > >>> >> >> > > * About the new "isCompleted()" function : I am not >>> >> >> > against this >>> >> >> > > function. But, I tend to think there are usually >>> BPEL >>> >> >> > variables >>> >> >> > > being modifed as the execution result of a flow >>> >> >> > activity. (See the >>> >> >> > > train-or-plane-and-hotel example). Is it more >>> typical >>> >> to have >>> >> >> > > completionCondition to be evaluated on those >>> variables? >>> >> >> > > Also, after the completion of the whole flow, it is >>> >> >> > not uncommon >>> >> >> > > for people to have logic to find out which branch is >>> >> finished >>> >> >> > > (especially when "or" is involved in the >>> condition). The >>> >> >> > > "isComplete()" function would be available only >>> within >>> >> the >>> >> >> > > completionCondition within the flow. People may get >>> >> >> > confused and >>> >> >> > > attempt to use the "isComplete()" function outside >>> >> >> > the flow. If >>> >> >> > > the completionCondition relies on variables, the >>> same >>> >> >> logic is >>> >> >> > > applicable outside of the flow. >>> >> >> > > >>> >> >> > > * About the IgnoreFault semantics: I recall this >>> >> >> > ignoreFault idea >>> >> >> > > back to March F2F. With ignoreFault semantics, it >>> >> essentially >>> >> >> > > introduces two brand new semantics. >>> >> >> > > o It turns <flow> into a semi-<scope> like >>> construct >>> >> >> > > o It adds this new "ignoreFault" semantics: >>> which >>> >> catches >>> >> >> > > certain fault and the catching action will not >>> >> cause >>> >> >> any >>> >> >> > > scope to be marked as faulted. >>> >> >> > > >>> >> >> > > I tend to think this "ignoreFault" functionality has >>> >> >> > quite a heavy >>> >> >> > > weight impact to <flow> and fault handling picture in >>> >> >> > BPEL. If there >>> >> >> > > is an alternative way to achieve similar business >>> >> >> > logic, I would go >>> >> >> > > for the alternative way. >>> >> >> > > >>> >> >> > > Quoted from Ivana's email: >>> >> >> > > " Not all activities must complete in order the >>> >> enclosing flow >>> >> >> > > activity to complete. The way to identify that an >>> >> >> > enclosed activity >>> >> >> > > did not complete is to propagate faults. " >>> >> >> > > >>> >> >> > > I agree with the first sentence. But, I am not sure >>> >> >> > that propagating >>> >> >> > > fault is the only way to identify an enclosed activity >>> >> did not >>> >> >> > > complete. I would rather use a scope as an activity >>> >> enclosed by >>> >> >> > > flow. If we wish to suppress any minor fault which >>> >> >> > happens during >>> >> >> > > the execution of the scope, then we can just add a >>> >> >> > fault handler. If >>> >> >> > > the fault that happen, the scope will be marked as >>> >> "faulted". >>> >> >> > > >>> >> >> > > The completeConditon can identify the "incomplete" >>> state >>> >> of the >>> >> >> > > scope by two ways: >>> >> >> > > >>> >> >> > > * completeCondition can be evaluated based on BPEL >>> >> >> > variables, >>> >> >> > > which are set to "incomplete" state by pre-flow >>> >> >> > initialization >>> >> >> > > or related fault-handler logic. >>> >> >> > > * branch-based condition will interprete a faulted >>> >> scope as >>> >> >> > > "incomplete" branch and will not count them into >>> >> >> > the required >>> >> >> > > N branches. >>> >> >> > > >>> >> >> > > This will allow us to suppress minor fault with or >>> >> without the >>> >> >> > > <completionCondition> construct. Please see the >>> >> >> > following example. >>> >> >> > > It is already legal and working today. It shows how to >>> >> suppress >>> >> >> > > "foo:barFault" without the <completeCondition> >>> construct >>> >> >> > > >>> >> >> > > <flow> >>> >> >> > > <scope name="A"> >>> >> >> > > <faultHandler> >>> >> >> > > <catch faultName="foo:barFault" ... > ... >>> </catch> >>> >> >> > > </faultHandler> >>> >> >> > > <sequence> >>> >> >> > > ... <invoke name="doA" ... /> ... >>> >> >> > > </sequence> >>> >> >> > > </scope> >>> >> >> > > <scope name="B"> ... <!-- similar to A --> ... >>> </scope> >>> >> >> > > </flow> >>> >> >> > > >>> >> >> > > If the invoke of "doA" triggers "foo:barFault", the >>> >> >> > scope "A" will >>> >> >> > > be marked as faulted. On the other hand, scope "B" >>> will >>> >> >> > be allowed >>> >> >> > > to continue and complete. After scope "B" is >>> completed, the >>> >> >> > > compensation handler of scope "B" will be installed. >>> >> And, the >>> >> >> > > overall execution of flow is still considered a normal >>> >> >> > completion. >>> >> >> > > >>> >> >> > > I hope I have illustrated we can achieve similar logic >>> >> without >>> >> >> > > introducing a new "ignoreFault" construct and >>> concept to >>> >> BPEL. >>> >> >> > > >>> >> >> > > What "completionCondition" does should be just >>> >> >> > providing a way to >>> >> >> > > pro-actively cancel/terminate other flows without >>> >> >> > waiting to them to >>> >> >> > > complete or to be faulted. >>> >> >> > > >>> >> >> > > * About "Cancel-other-flows": (Let me consolidate >>> what >>> >> I am >>> >> >> > > leaning towards so far.) We need to formal define >>> the >>> >> >> > notion of a >>> >> >> > > " cancel-other-flows " mechanism. This mechanism is >>> >> >> > specified and >>> >> >> > > attached to <flow> construct (and future parallel >>> forEach >>> >> >> > > construct). When this mechanism is triggered by one >>> >> >> > of parallel >>> >> >> > > flows, it will cancel/terminate other parallel flows >>> >> which >>> >> >> are >>> >> >> > > still running, after the triggering flow is >>> completed. >>> >> If the >>> >> >> > > other flow activties are scope activities, the scope >>> >> will be >>> >> >> > > marked as cancelled. >>> >> >> > > >>> >> >> > > This mechanism will be triggered upon the >>> >> >> > completionCondition is >>> >> >> > > evaluated to be true. >>> >> >> > > >>> >> >> > > [Note: (a) since this mechanism is triggered by >>> >> >> > without using any >>> >> >> > > fault directly. This will again decrease the need of >>> >> >> > "ignoreFault" >>> >> >> > > construct (b) This mechanism will affect the >>> wordings >>> >> >> > of Issue 135 >>> >> >> > > to an extent.] >>> >> >> > > >>> >> >> > > [Question: again, should we enforce scope-only >>> >> activity when >>> >> >> > > completionCondition is used? I tend to say yes.] >>> >> >> > > >>> >> >> > > >>> >> >> > > >>> >> >> > > Thank you all for following and reading this email >>> thread!!! >>> >> >> > > >>> >> >> > > >>> >> >> > > >>> >> >> > > Regards, >>> >> >> > > Alex Yiu >>> >> >> > > > > >>> >> >> > > >>> >> >> > > Trickovic, Ivana wrote: >>> >> >> > > >>> >> >> > >> > >> >>> >> >> > >> Here is a proposal for the completion condition - it >>> >> >> > addresses some >>> >> >> > >> issues not tackled so far (at least not in case of >>> >> >> > >> <completeCondition>). It is a version of the proposal for >>> >> >> > completion >>> >> >> > >> condition for the bundle element. This proposal includes >>> >> >> > comments from >>> >> >> > >> many people including Frank Leymann, Dieter Koenig, >>> Dieter >>> >> >> > Roller and >>> >> >> > >> Satish Thatte. It does not mean that they completely >>> >> support the >>> >> >> > >> proposal - they may have issues with any part of the >>> proposal. >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> > >> >>> >> >> > >> Completion condition >>> >> >> > >> >>> >> >> > >> ===================== >>> >> >> > >> >>> >> >> > >> The current semantics of the flow activity is that it >>> >> >> > waits for all >>> >> >> > >> concurrent activities to complete. The completion also >>> >> >> > means that an >>> >> >> > >> enclosed activity/scope may end abnormally or be skipped >>> >> (e.g. the >>> >> >> > >> join condition of the activity evaluated to false). If a >>> >> fault is >>> >> >> > >> thrown within an enclosed activity/scope and one of the >>> >> >> > local fault >>> >> >> > >> handlers catch the fault (and does not rethrow the >>> fault), the >>> >> >> > >> enclosed activity/scope will be deemed to be completed >>> >> >> > (although ended >>> >> >> > >> abnormally). If a fault is not caught by any local fault >>> >> >> > handler (or >>> >> >> > >> is rethrown) the flow activity will terminate all active >>> >> >> > concurrent >>> >> >> > >> activities and corresponding fault handler may be >>> initiated. >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> A completion condition for the flow activity is needed >>> for >>> >> >> > scenarios >>> >> >> > >> where not all concurrent activities of a flow activity >>> >> >> > must complete >>> >> >> > >> in order the flow activity to complete. Note: We are not >>> >> >> > talking about >>> >> >> > >> "successful completion" of enclosed concurrent activities >>> >> >> > because that >>> >> >> > >> would not be consistent with the semantics of the current >>> >> >> > flow activity. >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> The completion condition may have different flavors, >>> such as: >>> >> >> > >> >>> >> >> > >> (1) N out of M >>> >> >> > >> >>> >> >> > >> (2) The two most important requests completed >>> >> >> > >> >>> >> >> > >> (3) A Boolean condition operating upon process variables >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> Not all activities must complete in order the enclosing >>> >> >> > flow activity >>> >> >> > >> to complete. The way to identify that an enclosed >>> activity >>> >> did not >>> >> >> > >> complete is to propagate faults. We may distinguish >>> between >>> >> severe >>> >> >> > >> faults and those that can be ignored. Severe faults >>> cause the >>> >> >> > >> enclosing flow activity (or more precisely, enclosing >>> >> scope) to >>> >> >> > >> terminate the flow activity, including all active >>> concurrent >>> >> >> > >> activities, and corresponding fault handler may be >>> >> >> > initiated. Other >>> >> >> > >> faults may be ignored - the flow activity is >>> "informed" that a >>> >> >> > >> concurrent activity did not complete but still allows >>> other >>> >> active >>> >> >> > >> concurrent activities to continue with execution. >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> Ignore semantics >>> >> >> > >> >>> >> >> > >> ================= >>> >> >> > >> >>> >> >> > >> Faults thrown within enclosed concurrent >>> activities/scopes >>> >> and not >>> >> >> > >> handled by local fault handlers are rethrown. Enclosing >>> >> >> > <flow> element >>> >> >> > >> decides which of these rethrown faults can be ignored. >>> This >>> >> new >>> >> >> > >> "ignore" semantics should be part of the completion >>> >> condition and >>> >> >> > >> should apply to all enclosed activities. This new >>> >> >> > semantics does not >>> >> >> > >> introduce a new fault handling mechanism. It is needed >>> for >>> >> >> > identifying >>> >> >> > >> how many of the enclosed activities failed. >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> > >> >>> >> >> > >> Proposed syntax >>> >> >> > >> >>> >> >> > >> ================ >>> >> >> > >> >>> >> >> > >> <flow standard-attributes> >>> >> >> > >> >>> >> >> > >> standard-elements >>> >> >> > >> >>> >> >> > >> <completionCondition/>? >>> >> >> > >> >>> >> >> > >> <links>? >>> >> >> > >> >>> >> >> > >> <link name="ncname">+ >>> >> >> > >> >>> >> >> > >> </links> >>> >> >> > >> >>> >> >> > >> activity+ >>> >> >> > >> >>> >> >> > >> </flow> >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> <completionCondition> >>> >> >> > >> >>> >> >> > >> <conditions branch="xsd:integer"? >>> >> >> > >> >>> >> >> > >> expression=xpath?/>? >>> >> >> > >> >>> >> >> > >> <ignoreFaults>? >>> >> >> > >> >>> >> >> > >> <fault name="qname"? value="ncname"?/>* >>> >> >> > >> >>> >> >> > >> <ignoreAll/>? >>> >> >> > >> >>> >> >> > >> </ignoreFaults> >>> >> >> > >> >>> >> >> > >> </completionCondition> >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> Attribute branch is used to specify a condition of flavor >>> >> >> > "wait for >>> >> >> > >> /N/ out of /M/ activities to complete", or more precisely >>> >> value N. >>> >> >> > >> Attribute expression is used to specify a Boolean >>> >> >> > condition operating >>> >> >> > >> upon process variables or a condition of flavor "the >>> two most >>> >> >> > >> important requests completed". >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> Both conditions ( branch and expression) may be specified >>> >> >> > at the same >>> >> >> > >> time. They will be checked when one instance of the scope >>> >> activity >>> >> >> > >> reaches the end. If at least one condition evaluates to >>> >> true all >>> >> >> > >> active instances will be terminated. >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> Element <ignoreFaults> specifies faults that may be >>> >> >> > ignored. Element >>> >> >> > >> fault is used to specify a fault which may be ignored >>> >> >> > (fault name and >>> >> >> > >> fault data may be specified). Element <ignoreAll> would >>> >> >> > mean that all >>> >> >> > >> faults thrown/rethrown by any concurrent >>> activity/scope may be >>> >> >> > >> ignored. If this element is specified <fault> element >>> must >>> >> >> > be omitted. >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> Completion condition failure >>> >> >> > >> >>> >> >> > >> ============================= >>> >> >> > >> >>> >> >> > >> A new standard fault, e.g. completionConditionFailure, >>> >> should be >>> >> >> > >> introduced to notify that the completion condition of a >>> >> >> > flow activity >>> >> >> > >> evaluated to false (note: all concurrent activities >>> have been >>> >> >> > >> completed). The fault is thrown in the scope enclosing >>> the >>> >> >> > flow element. >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> Completion condition and links >>> >> >> > >> >>> >> >> > >> ============================== >>> >> >> > >> >>> >> >> > >> There should be no difference between a flow activity >>> with a >>> >> >> > >> completion condition and a flow activity without >>> >> >> > completion condition. >>> >> >> > >> For example, if the completion condition fails all links >>> >> >> > leaving the >>> >> >> > >> flow activity should have value "false" (or be >>> reverted to >>> >> >> > a negative >>> >> >> > >> status). >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> There are just a few additional rules: >>> >> >> > >> >>> >> >> > >> (1) Let's assume enclosed activity A is the source of a >>> >> >> > link. If the >>> >> >> > >> completion condition evaluates to true and activity A is >>> >> >> > not completed >>> >> >> > >> it will be terminated and the value of the link will be >>> >> >> > set to "false". >>> >> >> > >> >>> >> >> > >> (2) Let's assume enclosed activity A is the source of a >>> >> >> > link and the >>> >> >> > >> activity failed but the fault is "ignored" by the >>> enclosing >>> >> flow >>> >> >> > >> activity. The value of the link will be set to "false". >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> New function for completion condition of flavor "the >>> two most >>> >> >> > >> important requests completed" >>> >> >> > >> >>> >> >> > >> >>> >> >> > >>> ============================================================== >>> >> >> > ============================== >>> >> >> > >> >>> >> >> > >> >>> >> >> > >> For completion conditions of flavor "the two most >>> >> >> > important requests >>> >> >> > >> completed" standard attribute "name" must be specified >>> for all >>> >> >> > >> enclosing activities in order to be able to distinguish >>> >> them. In >>> >> >> > >> addition a new function, e.g. isCompleted('activityName') >>> >> must be >>> >> >> > >> introduced. The semantics of the function is: if activity >>> >> >> > completed >>> >> >> > >> successfully the function returns value true. >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> Example >>> >> >> > >> >>> >> >> > >> <completionCondition expression= >>> >> >> > >> >>> >> >> > >> "isCompleted('A') AND >>> isCompleted('B')" >> > >> >>> >> >> > >> </completionConditions> >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> > >> >>> >> >> > >> Regards, >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> Ivana >>> >> >> > >> >>> >> >> > >> > >> >>> >> >> > >> -----Original Message----- >>> >> >> > >> *From:* Alex Yiu [mailto:alex.yiu@oracle.com] >>> >> >> > >> *Sent:* Samstag, 11. September 2004 00:49 >>> >> >> > >> *To:* Axel Martens >>> >> >> > >> *Cc:* 'edwink@collaxa.com >>> >> >> > <mailto:edwink@collaxa.com>'; Trickovic, >>> >> >> > >> Ivana; 'satisht@microsoft.com >>> >> <mailto:satisht@microsoft.com>'; >>> >> >> > >> 'wsbpel@lists.oasis-open.org >>> >> >> > >> <mailto:wsbpel@lists.oasis-open.org>'; Alex Yiu >>> >> >> > >> *Subject:* Re: [wsbpel] Issue 6 - Rough draft of >>> >> >> > proposal for vote >>> >> >> > >> >>> >> >> > >> >>> >> >> > >> Hi, Axel, >>> >> >> > >> >>> >> >> > >> Thanks for liking parts of my proposal so far. >>> >> >> > >> Actually, the idea of my proposal is borrowed from a >>> >> part of >>> >> >> > >> presentation from Ivana and Dieter Roller in March >>> F2F. >>> >> I just >>> >> >> > >> generalize it to apply to <flow> also. >>> >> >> > >> >>> >> >> > >> About using links or not: >>> >> >> > >> I don't have a huge opposition to Axel's proposal >>> >> >> > which enriches >>> >> >> > >> the semantics of joinCondition evaluation. >>> However, it >>> >> >> > is not that >>> >> >> > >> difficult for people to make mistakes in >>> joinCondition. >>> >> >> Look at >>> >> >> > >> the 2-out-of-3 example. The join condition already >>> gets so >>> >> >> > >> complicated. If people make a mistake in their >>> >> >> > joinCondition, the >>> >> >> > >> whole flow can get struck for no good reasons. (The >>> >> >> > >> completeCondition approach will less likely to have >>> >> >> > the whole flow >>> >> >> > >> struck. Because, it does not introduce a new parallel >>> >> >> > activity in >>> >> >> > >> the flow). But, if this is what Petri-net-oriented >>> and >>> >> >> > >> control-link-oriented audience really want, I can >>> >> >> > accept it in a >>> >> >> > >> sense, as long as this is not the only way to achieve >>> >> similar >>> >> >> > >> business logic. >>> >> >> > >> >>> >> >> > >> About static vs dynamic parallelism: >>> >> >> > >> Static parallelism is basically <flow> construct in >>> >> >> > BPEL. Dynamic >>> >> >> > >> parallelism is "parallel forEach" or "bundle". >>> Issue 4 >>> >> >> > and 147 are >>> >> >> > >> related issues. >>> >> >> > >> > >>> >> >> >>> http://www.choreology.com/external/WS_BPEL_issues_list.html#Issue4 >>> >> >> > >> > >>> >> >> >>> http://www.choreology.com/external/WS_BPEL_issues_list.html#Issue147 >>> >> >> > >> >>> >> >> > >> About "Terminating still running tasks versus >>> >> proceeding in >>> >> >> > >> control flow while those tasks are >>> >> >> > >> still running": >>> >> >> > >> I am not 100% that I understand your question. Let me >>> >> try to >>> >> >> > >> answer it anyway. The completeCondition is about >>> >> triggering >>> >> >> > >> termination of still-running tasks. The >>> "proceeding in >>> >> control >>> >> >> > >> flow" (if I understand you correctly) will be handled >>> >> >> > by an outter >>> >> >> > >> flow. [I guess it is related to (hotel and (train or >>> >> >> > plane)) flow??] >>> >> >> > >> >>> >> >> > >> About changes of "forcedTermination" fault handler: >>> >> >> > >> If you got a chance to see some recent emails on >>> Issue >>> >> >> > 135, Satish >>> >> >> > >> has recently suggested to remove the notion >>> >> >> "forcedTermination" >>> >> >> > >> fault and replace its fault handler with >>> cancelHandler. >>> >> Frank, >>> >> >> > >> Yaron, Edwin and I all agree with this direction. >>> Because, >>> >> >> > >> overloading fault with the concept of >>> >> "forcedTermination" is a >>> >> >> > >> "false economy" and it creates quite a bit of >>> >> >> > unnecessary confusion. >>> >> >> > >> >>> >> >> > >> I don't think we should go back to this route or even >>> >> further >>> >> >> > >> overload the "forcedTermination" fault handler >>> >> >> > semantics. Because, >>> >> >> > >> fault handling is way too generic and the changes you >>> >> >> mentioned >>> >> >> > >> will create even more confusion. (e.g. Will this >>> >> >> > change of marking >>> >> >> > >> as "completed" apply to all "forcedTermination" fault >>> >> >> handler / >>> >> >> > >> cancel handler of all scopes? ) >>> >> >> > >> >>> >> >> > >> I guess most of us agree that we should have a new >>> >> >> mechanism to >>> >> >> > >> kill / do an early completion of a flow in a nice and >>> >> >> > clean way. >>> >> >> > >> However, overloading a standard fault handler does >>> not >>> >> >> > seem to be >>> >> >> > >> the best one. I would rather introduce a construct >>> >> >> > which is very >>> >> >> > >> specific to <flow> or parallel-forEach. For >>> example, this >>> >> >> > >> <completeCondition> construct or maybe a new activity >>> >> called >>> >> >> > >> <completeFlow />. I will send out more emails on >>> >> >> > joint thinking >>> >> >> > >> of both Issue 6 and Issue 135. Please stay tuned. >>> >> >> > >> >>> >> >> > >> >>> >> >> > >> Thanks! >>> >> >> > >> >>> >> >> > >> >>> >> >> > >> >>> >> >> > >> Regards, >>> >> >> > >> Alex Yiu >>> >> >> > >> >>> >> >> > >> >>> >> >> > >> Axel Martens wrote: >>> >> >> > >> >>> >> >> > >>> >>> >> >> > >>> Hi, >>> >> >> > >>> >>> >> >> > >>> I like the simplicity of the syntax of Alex's >>> >> >> > proposal. Although, >>> >> >> > >>> for me it is quite easy to model in terms of >>> links and >>> >> join >>> >> >> > >>> conditions, and I want to keep my proposal alive >>> >> >> > (because of the >>> >> >> > >>> minimal changes to BPEL's syntax and semantics), it >>> >> >> > looks like a >>> >> >> > >>> nice macro to provide more convenience to the >>> customers. >>> >> >> > >>> >>> >> >> > >>> Alex, could you shortly explain to me, what do you >>> >> >> > mean by static >>> >> >> > >>> and dynamic parallelism? How do you handle the two >>> >> >> > different cases >>> >> >> > >>> after evaluating the completeCondition: Terminating >>> >> >> > still running >>> >> >> > >>> tasks versus proceeding in control flow while those >>> >> tasks are >>> >> >> > >>> still running (Sorry, I missed your previous >>> emails)? >>> >> >> > >>> >>> >> >> > >>> I agree to Alex's opinion, that we need a >>> mechanism to >>> >> kill >>> >> >> > >>> parallel flow nice and clean. This could be done >>> >> >> > either by a new >>> >> >> > >>> mechanism which does not throw a fault or by >>> changing >>> >> the way >>> >> >> > >>> fault are handled. I have discussed already an >>> example >>> >> of the >>> >> >> > >>> second case with Ivana, and I like to tell you, >>> what I >>> >> >> have in >>> >> >> > >>> mind. Look at the following example: >>> >> >> > >>> >>> >> >> > >>> <scope name="scopeFlow"> >>> >> >> > >>> ... >>> >> >> > >>> <flow> >>> >> >> > >>> <link name="linkA"/> >>> >> >> > >>> <link name="linkB"/> >>> >> >> > >>> >>> >> >> > >>> <scope name="scopeA"> >>> >> >> > >>> ... >>> >> >> > >>> <invoke name="A" ...> >>> >> >> > >>> <source linkName="linkA" ...> >>> >> >> > >>> </invoke> >>> >> >> > >>> </scope> >>> >> >> > >>> >>> >> >> > >>> <scope name="scopeB"> >>> >> >> > >>> ... >>> >> >> > >>> <invoke name="B" ...> >>> >> >> > >>> <source linkName="linkB" ...> >>> >> >> > >>> </invoke> >>> >> >> > >>> </scope> >>> >> >> > >>> >>> >> >> > >>> <throw name="C" >>> faultName="bpws:forcedCompletion" >>> >> >> > >>> joinCondition="linkA OR linkB" >>> >> >> > >>> joinEvaluation="immediate"> >>> >> >> > >>> <target linkName="linkA" ...> >>> >> >> > >>> <target linkName="linkB" ...> >>> >> >> > >>> </throw> >>> >> >> > >>> >>> >> >> > >>> </flow> >>> >> >> > >>> </scope> >>> >> >> > >>> >>> >> >> > >>> First, I explain the situation: In the example >>> above, >>> >> >> > activity C >>> >> >> > >>> will be executed if one of the two activities A >>> and B was >>> >> >> > >>> successfully completed. Activity C throws the fault >>> >> >> > >>> "forcedCompletion". Like each other fault, this >>> >> >> > forces the scope >>> >> >> > >>> "scopeFlow" to terminate still running activities. >>> >> >> > Assume, there >>> >> >> > >>> was a fault handler defined in this scope which >>> >> >> > catches the fault >>> >> >> > >>> "forcedCompletion" (omitted in here), the process >>> >> >> > continues after >>> >> >> > >>> scope "scopeFlow". A problem arises, if scope >>> >> >> > "scopeFlow" should >>> >> >> > >>> be compensated. Because it was exited from a fault >>> >> >> handler, no >>> >> >> > >>> compensation handler was installed. >>> >> >> > >>> >>> >> >> > >>> Now, I explain my solution: In the example, I have >>> >> >> > chosen a new >>> >> >> > >>> "standard" fault name: "forcedCompletion". The only >>> >> necessary >>> >> >> > >>> change is to allow a fault handler that catches this >>> >> fault to >>> >> >> > >>> install a compensation handler for the same scope, >>> >> >> > i.e. to mark >>> >> >> > >>> the scope "scopeFlow" as "completed" instead of >>> "exited". >>> >> >> > >>> >>> >> >> > >>> The standard compensation mechanism will only >>> undo those >>> >> >> > >>> ("scoped") activities within the scope, which >>> >> >> > actually have been >>> >> >> > >>> successfully completed, i.e. scopeA or scopeB or may >>> >> be both. >>> >> >> > >>> >>> >> >> > >>> Axel. >>> >> >> > >>> ---------------------------------------- >>> >> >> > >>> Axel Martens >>> >> >> > >>> >>> >> >> > >>> Post Doc Researcher >>> >> >> > >>> Component Systems Group >>> >> >> > >>> IBM TJ Watson Research Center >>> >> >> > >>> Hawthorne, NY (USA) >>> >> >> > >>> Phone: (914) 784-7480 >>> >> >> > >>> E-mail: amarten@us.ibm.com >>> <mailto:amarten@us.ibm.com> >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> *Alex Yiu <alex.yiu@oracle.com> >>> >> <mailto:alex.yiu@oracle.com>* >>> >> >> > >>> >>> >> >> > >>> 09/10/2004 12:10 AM >>> >> >> > >>> >>> >> >> > >>> > >>> To >>> >> >> > >>> Alex Yiu <alex.yiu@oracle.com> >>> >> >> > <mailto:alex.yiu@oracle.com> >>> >> >> > >>> cc >>> >> >> > >>> "Trickovic, Ivana" <ivana.trickovic@sap.com> >>> >> >> > >>> <mailto:ivana.trickovic@sap.com>, Axel >>> >> >> > Martens/Watson/IBM@IBMUS, >>> >> >> > >>> "'edwink@collaxa.com'" >>> <mailto:%27edwink@collaxa.com%27> >>> >> >> > >>> <edwink@collaxa.com> <mailto:edwink@collaxa.com>, >>> >> >> > >>> "'satisht@microsoft.com'" >>> >> >> <mailto:%27satisht@microsoft.com%27> >>> >> >> > >>> <satisht@microsoft.com> >>> <mailto:satisht@microsoft.com>, >>> >> >> > >>> "'wsbpel@lists.oasis-open.org'" >>> >> >> > >>> <mailto:%27wsbpel@lists.oasis-open.org%27> >>> >> >> > >>> <wsbpel@lists.oasis-open.org> >>> >> >> > >>> <mailto:wsbpel@lists.oasis-open.org>, Alex Yiu >>> >> >> > >>> <alex.yiu@oracle.com> <mailto:alex.yiu@oracle.com> >>> >> >> > >>> Subject >>> >> >> > >>> Re: [wsbpel] Issue 6 - Rough draft of proposal >>> >> for vote >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> > >>> >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> Hi, >>> >> >> > >>> >>> >> >> > >>> Here are some examples how to use >>> completeCondition to >>> >> >> express >>> >> >> > >>> similar business logic in Axel's previous email: >>> >> >> > >>> >>> >> >> > >>> (A) "Select one out of three" example: >>> >> >> > >>> <flow> >>> >> >> > >>> <completeCondition *branch="1"* /> >>> >> >> > >>> <invoke name="CheckAirlineA" ... /> >>> >> >> > >>> <invoke name="CheckAirlineB" ... /> >>> >> >> > >>> <invoke name="CheckAirlineC" ... /> >>> >> >> > >>> </flow> >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> (B) "Select two out of three" example: >>> >> >> > >>> <flow> >>> >> >> > >>> <completeCondition *branch="2"* /> >>> >> >> > >>> <invoke name="AskRefereeA" ... /> >>> >> >> > >>> <invoke name="AskRefereeB" ... /> >>> >> >> > >>> <invoke name="AskRefereeC" ... /> >>> >> >> > >>> </flow> >>> >> >> > >>> >>> >> >> > >>> As you guys can see, the completeCondition >>> declaration is >>> >> >> very >>> >> >> > >>> straight forward and simple. No complicated links >>> and >>> >> >> > >>> joinCondition usage. >>> >> >> > >>> >>> >> >> > >>> (C) "(Plane or Train) and Hotel" example: It would >>> >> become two >>> >> >> > >>> flow constructed (nested). >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> <assign> ... <to variable="planeResult"></assign> >>> >> >> > >>> <!-- initialize "planeResult" with NOT-OK value >>> --> >>> >> >> > >>> <assign> ... <to variable="trainResult"></assign> >>> >> >> > >>> <!-- initialize "trainResult" with NOT-OK value >>> --> * >>> >> >> > >>> <flow name="checkIterinary">* >>> >> >> > >>> *<flow name="PlaneOrPlane">* >>> >> >> > >>> <completeCondition> >>> >> >> > >>> fn:planeOK(planeResult) *or* >>> >> >> > fn:trainOK(trainResult) >>> >> >> > >>> </completeCondition> >>> >> >> > >>> <invoke name="CheckPlane" >>> >> >> > outputVariable="planeResult" ... /> >>> >> >> > >>> <invoke name="CheckTrain" >>> >> >> > outputVariable="trainResult" ... /> >>> >> >> > >>> *</flow> * >>> >> >> > >>> <invoke name="checkHotel" /> * >>> >> >> > >>> </flow> >>> >> >> > >>> <switch name="bookingSwitch">* >>> >> >> > >>> <case> >>> >> >> > >>> <condition> >>> >> >> > >>> (fn:planeOK(planeResult) *or* >>> >> fn:trainOK(trainResult)) >>> >> >> > >>> *and* fn:hotelOK(hotelResult) >>> >> >> > >>> </condition> >>> >> >> > >>> <invoke name="invokeBooking" ... /> >>> >> >> > >>> </case> >>> >> >> > >>> <otherwise> >>> >> >> > >>> <invoke name="writeInformation" ... /> >>> >> >> > >>> </otherwise> * >>> >> >> > >>> </switch>* >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> Please note that regardless whether we pick a >>> >> link-oriented >>> >> >> > >>> approach or completeCondition approach: >>> >> >> > >>> >>> >> >> > >>> * The initialization of result variables are >>> >> >> > needed because >>> >> >> > >>> of potential cancellation of one of the invoke >>> >> between >>> >> >> > >>> train and plane >>> >> >> > >>> * The "fn:*()" represents the logic to determine >>> >> >> whether a >>> >> >> > >>> traveling resource is available. They are >>> used in >>> >> >> either >>> >> >> > >>> the transitionCondition of links or the >>> >> condition of >>> >> >> > >>> switch/case. >>> >> >> > >>> >>> >> >> > >>> As you guys see, we don't need declare to six >>> links. The >>> >> >> > >>> completeCondition and case-condition are much >>> simpler >>> >> >> > and easier >>> >> >> > >>> to understand. >>> >> >> > >>> >>> >> >> > >>> I attach a diagram to illustrate the above flows. >>> >> >> > >>> >>> >> >> > >>> I guess we can still more time in terms of >>> refiniment of >>> >> >> > >>> joinCondition evaluation. However, I don't think >>> that >>> >> >> > should be >>> >> >> > >>> the only approach to achieve complete condition >>> related >>> >> >> logic. >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> Thanks!!! >>> >> >> > >>> >>> >> >> > >>> Regards, >>> >> >> > >>> Alex Yiu >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> Alex Yiu wrote: >>> >> >> > >>> >>> >> >> > >>> Hi, >>> >> >> > >>> >>> >> >> > >>> +1 to what Ivana said in general. >>> >> >> > >>> >>> >> >> > >>> Few points to add: >>> >> >> > >>> >>> >> >> > >>> * Axel's proposed enhancement to control links >>> >> evaluation >>> >> >> > >>> works to an extent for static parallelism >>> > (e.g. >>> >> >> <flow>). >>> >> >> > >>> However, control links do not work well in >>> dynamic >>> >> >> > >>> parallelism (e.g. "parallel forEach" or >>> >> >> > "bundle"). I think >>> >> >> > >>> the notion of completeCondition (borrowed from >>> >> Ivana >>> >> >> and >>> >> >> > >>> DK) is general enough and it should be applied >>> >> to both >>> >> >> > >>> static and dynamic parallelism. A general >>> >> >> > completeCondition >>> >> >> > >>> mechanism will be easier for BPEL users to >>> learn. >>> >> >> > >>> * Even in a pure static parallelism case, >>> >> >> > completeCondition >>> >> >> > >>> has much better code clarity. It is more >>> >> declarative >>> >> >> and >>> >> >> > >>> easier for BPEL users to understand. It will >>> >> eliminate >>> >> >> > >>> significant amount of joinCondition >>> >> >> > programming, which may >>> >> >> > >>> be error prone. (I will send another email >>> later to >>> >> >> show >>> >> >> > >>> how completeCondition can be used to >>> express the >>> >> same >>> >> >> > >>> semantics of Axel's example). >>> >> >> > >>> * In one of my previous emails, I also tried to >>> >> >> > use a "macro" >>> >> >> > >>> way to illustrate how outstanding running >>> flows >>> >> can be >>> >> >> > >>> cancelled by throwing a fault within a >>> scope. The >>> >> >> > >>> illustration has the same compensation handler >>> >> >> > installation >>> >> >> > >>> problem that Ivana has pointed out. The >>> >> "illustraction >>> >> >> > >>> macro" does NOT carry a desirable and intended >>> >> >> > semantics. >>> >> >> > >>> We need to create / describe a new >>> mechanism to >>> >> cancel >>> >> >> > >>> parallel flow without throwing a fault. (That >>> >> >> > was discussed >>> >> >> > >>> briefly between Edwin and me at Oracle). >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> Thanks! >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> Regards, >>> >> >> > >>> Alex Yiu >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> >>> >> >> > >>> Trickovic, Ivana wrote: >>> >> >> > >>> Axel, >>> >> >> > >>> > >>> I find the idea interesting. In fact, >>> I was >>> >> >> discussing the >>> >> >> > >>> completion condition issue with Dieter Koenig during >>> >> >> > the last f2f >>> >> >> > >>> meeting and his suggestion was also to try to >>> resolve >>> >> >> > this issue >>> >> >> > >>> using links. And we identified that several >>> changes need >>> >> >> to be >>> >> >> > >>> done, including removing restriction for >>> >> >> > jonCondition, that "the >>> >> >> > >>> join condition is evaluated as soon as all incoming >>> >> >> > links of the >>> >> >> > >>> activity are determined" - so definitely "immediate" >>> >> >> semantics >>> >> >> > >>> needs to be introduced. >>> >> >> > >>> > >>> I have the following comments on your >>> >> proposal. >>> >> >> > >>> 1. In your proposal you are using a fault >>> >> >> > >>> (bpws:forcedTermination) to terminate all active >>> parallel >>> >> >> > >>> branches. But this changes the outcome of the flow >>> >> >> > activity. It >>> >> >> > >>> will always end abnormally and compensation handler >>> >> (if it is >>> >> >> > >>> defined) will never be installed. Although >>> completion >>> >> >> > condition >>> >> >> > >>> has evaluated to true and needed activities have >>> >> completed >>> >> >> the >>> >> >> > >>> enclosing flow activity will end abnormally. Is this >>> >> really >>> >> >> > >>> intended semantics? >>> >> >> > >>> > >>> 2. Your proposal does not address some >>> pain >>> >> >> points. >>> >> >> > For example, >>> >> >> > >>> in case of "N out of M", N<M there many possible >>> >> >> "variations": >>> >> >> > >>> (A) One enclosed activity may experience problems >>> but >>> >> >> > the <flow> >>> >> >> > >>> activity may succeed >>> >> >> > >>> (B) One of enclosed activities may experience a >>> severe >>> >> error, >>> >> >> > >>> which may have impact on the <flow> activity >>> >> >> > >>> The question is what to do with running activities? >>> >> >> > In the latter >>> >> >> > >>> case, reasonable behavior would be: if one enclosed >>> >> >> > activity does >>> >> >> > >>> not succeed other running activities should be >>> >> >> > cancelled and the >>> >> >> > >>> flow activity should try to recover. In the former >>> >> case, we >>> >> >> > >>> should allow active parallel activities to complete >>> >> >> > their work. >>> >> >> > >>> This is not supported in your proposal. >>> >> >> > >>> > >>> Regards, >>> >> >> > >>> > >>> >>> >> >> > >>> Ivana >>> >> >> > >>> >>> >> >> > >> [stuff deleted] >>> >> >> > >> >>> >> >> > > >>> >> >> > >>> >> >> > To unsubscribe from this mailing list (and be removed from >>> >> >> > the roster of the OASIS TC), go to >>> >> >> > >>> http://www.oasis-open.org/apps/org/workgroup/wsbpel/members/le >>> >> >> > ave_workgroup.php. >>> >> >> > >>> >> >> >>> >> >> To unsubscribe from this mailing list (and be removed from the >>> >> roster >>> >> >> of the OASIS TC), go to >>> >> >> >>> >> >>> http://www.oasis-open.org/apps/org/workgroup/wsbpel/members/leave_workgroup.php. >>> >>> >> >>> >> >> >>> >> >> >>> >> > >>> >> > To unsubscribe from this mailing list (and be removed from >>> the roster >>> >> > of the OASIS TC), go to >>> >> > >>> >> >>> http://www.oasis-open.org/apps/org/workgroup/wsbpel/members/leave_workgroup.php. >>> >>> >> >>> >> > >>> >> > >>> >> > >>> >> >>> >> To unsubscribe from this mailing list (and be removed from the >>> roster >>> >> of the OASIS TC), go to >>> >> >>> http://www.oasis-open.org/apps/org/workgroup/wsbpel/members/leave_workgroup.php. >>> >>> >> >>> >> >>> > >>> >>> To unsubscribe from this mailing list (and be removed from the >>> roster of the OASIS TC), go to >>> http://www.oasis-open.org/apps/org/workgroup/wsbpel/members/leave_workgroup.php. >>> >>> >> > > To unsubscribe from this mailing list (and be removed from the roster > of the OASIS TC), go to > http://www.oasis-open.org/apps/org/workgroup/wsbpel/members/leave_workgroup.php. > >
S/MIME Cryptographic Signature
[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]