[MUD-Dev] C&C and Event Rescheduling

Shawn Halpenny malachai at iname.com
Fri Jul 18 16:13:34 New Zealand Standard Time 1997


clawrenc at cup.hp.com wrote:
> 
> In <33C69FC6.41C67EA6 at iname.com>, on 07/11/97
>    at 02:07 PM, Shawn Halpenny <malachai at iname.com> said:
> 
> >Roughly:
> >1.  A client requests object O from the database.
> >2.  Return OC (a client-only copy of O) to the client.
> >3.  The client returns OC' after some munging.
> >4.  If no changes have been made to O since the request was made
> >    (a different client request may have committed changes to O
> >    while OC' was being created), OC' is atomically committed to
> >    the database and notification of success is returned to the
> >    client.
> >5.  If O has changed, OC' is thrown away and the client receives
> >    notification that OC' could not commit.
> 
> This is pretty well identical to my model.  Concerns:
> 
>   Most events modify more than one object.  eg Bubba (object X) moves
> from room A to room B.  Minimally objects A, B, and X will be modified
> by this event (containment pointers/lists).
> 
>   How do you intend to handle the cases of an event requesting object
> Q just to check the value of a data member (ie no modification), where
> that data member has then been changed by the time the event commits
> (see the dragon's dinner example, and look at the door)?

Yep, a slight change is necessary.  Now (and again, roughly):
1.  A client C requests object O from the database. 
2.  Add C to list of clients using O. 
3.  Return OC (a client-only copy of O) to C. 
4.  A client D (which may or may not be the same as C, but is on the
    using-list for O) returns OC'. 
5.  If O has not changed since D's request for it (a different client may
    have committed changes to O while D was processing), OC' is atomically
    committed to the database, replacing O.   D is removed from O's using-
	list.
6.  If O has changed since D's request for it, OC' is discarded and D
    receives notification that OC' couldn't commit.
7.  Clients in the using-list for O are asynchronously notified that O has
    changed. 

This with the intent that all clients (usually events, in this case)
will reschedule upon notification that their changes couldn't commit.
Step 7 is not entirely necessary, since after any change to O, all
clients using O will (when they terminate their processing and return
their OC' 's for commit) receive notification that what they did is
no longer applicable.  Step 7 just lets them know about it sooner.

>   Do you have a concept of a "transaction" where a transaction is
> effectively synonymous with an event, and involves the possible
> requesting of read-only copies of N objects, and the possible
> modification of M objects where M is a subset of N?  What I'm looking
> for here is the idea that a transaction or event can only commit if
> all of its component objects resolve correctly to their commit state
> (ie everything compares right).

This is now the case:  if one of those M objects has changed since an
event's beginning, reschedule that event since the data it has
already made a decision on may have changed (i.e. the door is shut
now so the dragon, who was moving through it, now has to reevaluate
its movement).

I think that fits the above criteria.

>   What about the case of an object with two attributes, say object A,
> with attributes A::X, and A::Y.  Two events, Q and R, then occur.  Q
> modifies the value of A::X.  R modifies the value of A::Y.  Both
> events run simultaneously and commit in arbitrary order.  Should one
> event fail and be rescheduled?

Yes.  The attributes that are read/written in A from Q and R are not
monitored by the DB, since the DB has no way of knowing what attributes an
event is going to access next.

>   You can take this last case and instead of having both events modify
> the attributes, instead have one modify one value, and the other do a
> read-only check, or have one do a read-only check of A::X while the
> other modifies it.

As above.

[ how to prevent events from starving ]

> I don't have a pure solution.  I (rough memory) follow the following
> course:
> 
>   A rescheduled event is given a higher than default priority.  All
> this means is that it gets first crack at getting a thread to execute
> on as versus a "normal" event which will have to wait until all
> higher-priority events have threads.
> 
>   A 5*rescheduled event forces the Executor to cease assigning events
> to threads until the 5*rescheduled event terminates.
> 
>   A 10*rescheduled event (I think its 10) forces the Executor to cease
> assigning events to threads until the 10*rescheduled event
> successfully terminates (ie it heads toward and finally goes into
> single-tasking mode).
> 
>   A 20*rescheduled event (have no idea what the real number is)
> signals all other executing events to block until this event has
> terminated.  This just shuts down the multi-threading until the event
> has run.

Ahh.  I had settled on using execution priorities as well, but not
quite like this.  I don't think I'll keep track of the number of
times an event has been rescheduled.  Instead, I've a fixed number of
possible priorities, with the top one reserved for internal use.  An
event will have its priority increased each time it is rescheduled.
If it reaches the top priority, it is run to completion before any further
event processing.

> Note: Events have a very short maximum time they must execute within.
> Event's which take longer than that time are killed and not
> rescheduled.  This maximum time is reduced as events are rescheduled
> and ascend the above priority list (ie I give them more chance to get
> their job done, but less time to do it).

Not so for me.  Am I missing something while standing here at the drawing
board? :)

--
Shawn Halpenny

"Turn once for maximum vend."
                        - Me



More information about the MUD-Dev mailing list