737 # - processed by the precommit/commit event or not |
737 # - processed by the precommit/commit event or not |
738 # - if processed, is it the failed operation |
738 # - if processed, is it the failed operation |
739 try: |
739 try: |
740 # by default, operations are executed with security turned off |
740 # by default, operations are executed with security turned off |
741 with security_enabled(self, False, False): |
741 with security_enabled(self, False, False): |
742 for trstate in ('precommit', 'commit'): |
742 processed = [] |
743 processed = [] |
743 self.commit_state = 'precommit' |
744 self.commit_state = trstate |
744 try: |
745 try: |
745 while self.pending_operations: |
746 while self.pending_operations: |
746 operation = self.pending_operations.pop(0) |
747 operation = self.pending_operations.pop(0) |
747 operation.processed = 'precommit' |
748 operation.processed = trstate |
748 processed.append(operation) |
749 processed.append(operation) |
749 operation.handle_event('precommit_event') |
750 operation.handle_event('%s_event' % trstate) |
750 self.pending_operations[:] = processed |
751 self.pending_operations[:] = processed |
751 self.debug('precommit session %s done', self.id) |
752 self.debug('%s session %s done', trstate, self.id) |
752 except: |
753 except: |
753 # if error on [pre]commit: |
754 # if error on [pre]commit: |
754 # |
755 # |
755 # * set .failed = True on the operation causing the failure |
756 # * set .failed = True on the operation causing the failure |
756 # * call revert<event>_event on processed operations |
757 # * call revert<event>_event on processed operations |
757 # * call rollback_event on *all* operations |
758 # * call rollback_event on *all* operations |
758 # |
759 # |
759 # that seems more natural than not calling rollback_event |
760 # that seems more natural than not calling rollback_event |
760 # for processed operations, and allow generic rollback |
761 # for processed operations, and allow generic rollback |
761 # instead of having to implements rollback, revertprecommit |
762 # instead of having to implements rollback, revertprecommit |
762 # and revertcommit, that will be enough in mont case. |
763 # and revertcommit, that will be enough in mont case. |
763 operation.failed = True |
764 operation.failed = True |
764 for operation in reversed(processed): |
765 for operation in reversed(processed): |
765 try: |
766 try: |
766 operation.handle_event('revertprecommit_event') |
767 operation.handle_event('revert%s_event' % trstate) |
767 except: |
768 except: |
768 self.critical('error while reverting precommit', |
769 self.critical('error while reverting %sing', trstate, |
769 exc_info=True) |
770 exc_info=True) |
770 # XXX use slice notation since self.pending_operations is a |
771 # XXX use slice notation since self.pending_operations is a |
771 # read-only property. |
772 # read-only property. |
772 self.pending_operations[:] = processed + self.pending_operations |
773 self.pending_operations[:] = processed + self.pending_operations |
773 self.rollback(reset_pool) |
774 self.rollback(reset_pool) |
774 raise |
775 raise |
|
776 self.pool.commit() |
775 self.pool.commit() |
777 self.commit_state = trstate = 'postcommit' |
776 self.commit_state = 'postcommit' |
778 while self.pending_operations: |
777 while self.pending_operations: |
779 operation = self.pending_operations.pop(0) |
778 operation = self.pending_operations.pop(0) |
780 operation.processed = trstate |
779 operation.processed = 'postcommit' |
781 try: |
780 try: |
782 operation.handle_event('%s_event' % trstate) |
781 operation.handle_event('postcommit_event') |
783 except: |
782 except: |
784 self.critical('error while %sing', trstate, |
783 self.critical('error while postcommit', |
785 exc_info=sys.exc_info()) |
784 exc_info=sys.exc_info()) |
786 self.debug('%s session %s done', trstate, self.id) |
785 self.debug('postcommit session %s done', self.id) |
787 return self.transaction_uuid(set=False) |
786 return self.transaction_uuid(set=False) |
788 finally: |
787 finally: |
789 self._touch() |
788 self._touch() |
790 if reset_pool: |
789 if reset_pool: |
791 self.reset_pool(ignoremode=True) |
790 self.reset_pool(ignoremode=True) |