[h5py] 24/455: transactions stub
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:13 UTC 2015
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to annotated tag 1.3.0
in repository h5py.
commit d0ec5773b695156e3cd18b08838cdc2d6617f133
Author: andrewcollette <andrew.collette at gmail.com>
Date: Thu May 22 21:42:25 2008 +0000
transactions stub
---
h5py/transactions.py | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 239 insertions(+)
diff --git a/h5py/transactions.py b/h5py/transactions.py
new file mode 100644
index 0000000..9eadbea
--- /dev/null
+++ b/h5py/transactions.py
@@ -0,0 +1,239 @@
+import time
+
+class TransactionError(StandardError):
+ """ Base class for errors in the transactions module.
+ """
+ pass
+
+class TransactionStateError(TransactionError):
+ """ Illegal state change inside an Action object.
+ """
+ pass
+
+class NotTransactableError(TransactionError):
+ """ A non-transactable operation was attempted while in transaction mode.
+ """
+ pass
+
+class DeadTransactionError(TransactionError):
+ """ A transactable operation was attempted while not in transaction mode.
+ """
+ pass
+
+class Action(object):
+
+ """ Represents the smallest component of a transaction.
+
+ Each Action object is a simple state machine which can do three things:
+ do, undo and commit. Each of these actions is specified by a 3-tuple
+ containing (callable, args, kwds). Whatever the "do" callable does is
+ assumed to be an atomic operation, which is fully reversed by the
+ "undo" operation. The "commit" operation is optional, and can be
+ used to e.g. clean up state information used for undo.
+
+ States are
+ READY: The action has not been performed.
+ Legal calls:
+ do() => DONE
+ DONE: The action has been performed.
+ Legal calls:
+ undo() => READY
+ commit() => COMMITTED
+ COMMITTED: The action has been performed and cannot be undone.
+ No legal calls.
+
+ Peforming an illegal call (in the wrong state) will raise a
+ TransactionStateError.
+ """
+
+ READY = 0
+ DONE = 1
+ COMMITTED = 2
+
+ def __init__(self, name, do, undo, commit=None):
+ """ Create a new action object, from a name and a do/undo pair.
+
+ "Do" and "undo" are required and must be 3-tuples containing
+ (callable, args_tuple, keywords_dictionary). "commit" is optional.
+
+ do: Perform some kind of atomic operation
+ undo: Completely reverse the effects of the "do" operation.
+ commit: Clean up any temporary data created by the "do" operation.
+
+ """
+ self.name = name
+ self._validate(do, 'do')
+ self._validate(undo, 'undo')
+ if commit is not None:
+ self._validate(commit, 'commit')
+ self._do = do
+ self._undo = undo
+ self._commit = commit
+ self.state = Action.READY
+
+ def _validate(self, item, name):
+ if isinstance(item, tuple) and \
+ len(item) == 3 and \
+ hasattr(item[0],'__call__') and \
+ isinstance(item[1], tuple) and \
+ isinstance(item[2], dict):
+ return
+ raise ValueError('"%s" must be a 3-tuple (callable, args, kwds); got %s' % (name, str(item)) )
+
+ def _call(self, tpl):
+ if tpl is not None:
+ f, a, k = tpl
+ f(*a, **k)
+
+ def do(self):
+ if self.state != Action.READY:
+ raise TransactionStateError('Action "%s" is not in the ready state (got %d)' % (self.name, self.state))
+ self._call(self._do)
+ self.state = Action.DONE
+
+ def undo(self):
+ if self.state != Action.DONE:
+ raise TransactionStateError('Action "%s" is not in the "done" state for undo (got %d)' % (self.name, self.state))
+ self._call(self._undo)
+ self.state = Action.READY
+
+ def commit(self):
+ if self.state != Action.DONE:
+ raise TransactionStateError('Action "%s" is not in the "done" state for commit (got %d)' % (self.name, self.state))
+ self._call(self._commit)
+ self.state = Action.COMMITTED
+
+
+class TransactionManager(object):
+
+ active = property(lambda self: self.stack is not None)
+
+ def __init__(self, max_size=None):
+ """ Create a new transaction manager, inactive by default.
+ """
+ self.stack = None
+ self.ptr = None
+ self.max_size = max_size
+
+ def _check(self):
+ if not self.active:
+ raise DeadTransactionError("No current transaction.")
+
+ def begin(self):
+ """ Begin a new transaction. Implicitly commits any pending actions.
+ """
+ if self.active:
+ self.commit()
+ self.stack = {}
+ self.ptr = None
+
+ def commit(self):
+ """ Commit every action which is in the "done" state, and destroy
+ the stack.
+ """
+ self._check()
+ for t in sorted(self.stack):
+ action = self.stack[t]
+ if action.state == Action.DONE:
+ action.commit()
+ self.stack = None
+ self.ptr = None
+
+ def rollback(self):
+ """ Undo every action which is in the "done" state, and destroy
+ the stack.
+ """
+ self._check()
+ for t in sorted(self.stack, reverse=True):
+ action = self.stack[t]
+ if action.state == Action.DONE:
+ action.undo()
+ self.stack = None
+ self.ptr = None
+
+ def at_top(self):
+ """ Check if the pointer is at the top of the stack.
+ """
+ self._check()
+ if len(self.stack) == 0 or self.ptr == max(self.stack):
+ return True
+ return False
+
+ def at_bottom(self):
+ """ Check if the pointer is at the bottom of the stack.
+ """
+ self._check()
+ if len(self.stack) == 0 or self.ptr == min(self.stack):
+ return True
+ return False
+
+ def do(self, action):
+ """ Perform the given action and add it to the stack. Implicitly
+ discards any newer actions on the stack, and sets the pointer
+ to the new item. If the resulting stack size is greater than
+ max_size, commit and discard the oldest action.
+
+ The action's do() method is called before any modification is
+ made to the stack.
+ """
+ self._check()
+ action.do()
+
+ if self.ptr is not None:
+ for t in sorted(self.stack):
+ if t > self.ptr:
+ assert self.stack[t].state == Action.READY
+ del self.stack[t]
+
+ key = time.time()
+ self.stack[key] = action
+ self.ptr = key
+
+ if self.max_size is not None and len(stack) > self.max_size:
+ key = min(self.stack)
+ self.stack[key].commit()
+ del self.stack[key]
+
+ def undo(self):
+ """ Undo the action targeted by the current pointer, and move the
+ pointer down one level on the stack. Does nothing if the pointer
+ is None or off the bottom of the stack.
+ """
+ self._check()
+ if self.ptr is not None and self.ptr >= 0:
+ self.stack[self.ptr].undo()
+ keys = sorted(self.stack)
+ idx = keys.index(self.ptr)
+ if self.at_bottom():
+ self.ptr = -1
+ else:
+ self.ptr = keys[idx-1]
+
+ def redo(self):
+ """ Increment the pointer and redo the resulting action. Does nothing
+ if the pointer is already at the top of the stack, or is None.
+ """
+ self._check()
+ if not self.at_top() and self.ptr is not None:
+ keys = sorted(self.stack)
+ if self.ptr < 0:
+ self.ptr = min(keys)
+ else:
+ idx = keys.index(self.ptr)
+ self.ptr = keys[idx+1]
+ self.stack[self.ptr].do()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/h5py.git
More information about the debian-science-commits
mailing list