[PEAK] Re: Trellis-fork

Sergey Schetinin maluke at gmail.com
Fri Jul 17 17:34:00 EDT 2009


2009/7/18 Sergey Schetinin <maluke at gmail.com>:
> I was thinking about how read invalidation would be processed. To
> remind you what I mean by that, it's when there are concurrent
> transactions and one has committed a write that makes some reads of
> the still running one invalid. That means that transaction has to be
> rolled back so that it has no invalid reads and restart from there. If
> the read happened in a rule it can be safely rolled back and retried,
> there are two cases when retry is problematic -- top-level @modifier
> and @task.
>
> If the invalidated read happened in @modifier, it can be retried as
> well if we remember its arguments. It however requires that modifier
> not to have any effects. It's a reasonable demand.
>
> @task is a different matter -- it kinda runs as a modifier, but the
> body of it is <generator>.next() which cannot be retried -- the
> generator changes internal state irreversibly. To make things worse
> @tasks would normally have effects, such as sending data over network.
> This is unfortunate, but I think there's a way around -- @tasks would
> need to have two modes which they could switch between by yield
> TxnMode / yield EffectMode. In effect mode they would not be able to
> read transactional data, just like things called from effect() queue
> -- that ensures that @task effects will not be invalidated and will
> not need to roll back. The transactional mode however would need to be
> able to handle retries due to invalidated reads, something like this:
>
> yield TxnMode
> while True:
>    self.a += 1
>    # if self.a was changed after we read it but before we committed
>    # we'll need to retry
>    if (yield Commit):
>        break
>
> That's ugly and I really don't want to do that, so I'm looking into
> possibility of some limitations to what and how could be used from
> @tasks that would guarantee their reads won't ever get invalidated.
>

I think there's a way -- if task reads a cell it is (synchronously
with commits) registered in controller. If some commit tries to write
a cell that was read by a @task that didn't commit yet (which means it
will invalidate that read) the priority is given to the task and the
commit is delayed until that task commits, at that point the delayed
commit tries again and either just writes the new value still
preserving the state consistency or retries (if any of *its* reads got
invalidated since).

There's only one case that algorithm wouldn't handle -- mutual
invalidation from the bodies of concurrent @tasks. This can only
happen if a task running in one thread changes a value from its body
(not via some triggered rule!) that was read by a body (not some
dependent rule either!) of a task running in another thread and the
same happened the other way around. This would create a cycle in the
algorithm above. However, this is a very unlikely case, it can be
detected and it would clearly signal bad application design. So it
seems @task can stay as concise as they are.



-- 
Best Regards,
Sergey Schetinin

http://s3bk.com/ -- S3 Backup
http://word-to-html.com/ -- Word to HTML Converter


More information about the PEAK mailing list