rollbacker.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. '''*****************************************************************************
  2. AToMPM - A Tool for Multi-Paradigm Modelling
  3. Copyright (c) 2011 Eugene Syriani
  4. This file is part of AToMPM.
  5. AToMPM is free software: you can redistribute it and/or modify it under the
  6. terms of the GNU Lesser General Public License as published by the Free Software
  7. Foundation, either version 3 of the License, or (at your option) any later
  8. version.
  9. AToMPM is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  11. PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with AToMPM. If not, see <http://www.gnu.org/licenses/>.
  14. *****************************************************************************'''
  15. #import pickle, os
  16. from ..util.infinity import INFINITY
  17. from iterator import Iterator
  18. from ..tcore.messages import TransformationException
  19. class Rollbacker(Iterator):
  20. '''
  21. Provides back-tracking capacity.
  22. '''
  23. def __init__(self, condition, max_iterations=INFINITY):
  24. '''
  25. Selects one match from the packet.
  26. @param condition: The pre-condition pattern.
  27. @param max_iterations: The maximum number of times to select.
  28. By default, this is +INFINITY.
  29. '''
  30. super(Rollbacker, self).__init__(condition, max_iterations)
  31. self.checkpoints = [] # Stack of file names
  32. def packet_in(self, packet):
  33. self.exception = None
  34. self.is_success = False
  35. try:
  36. self.establish(packet)
  37. self.is_success = True
  38. except Exception, e:
  39. self.is_success = False
  40. self.exception = TransformationException(e)
  41. self.exception.packet = packet
  42. self.exception.transformation_unit = self
  43. finally:
  44. self.iterations = 1
  45. return packet
  46. def next_in(self, packet):
  47. self.exception = None
  48. self.is_success = False
  49. if self.iterations < self.max_iterations:
  50. # If came from the same scope as the rollbacker, then just pass it over
  51. if packet.current in packet.match_sets:
  52. self.iterations += 1
  53. self.is_success = True
  54. return packet
  55. else:
  56. try:
  57. packet.set_state(self.restore())
  58. self.is_success = True
  59. except Exception, e:
  60. self.is_success = False
  61. self.excepion = TransformationException(e)
  62. self.exception.packet = packet
  63. self.exception.transformation_unit = self
  64. finally:
  65. return packet
  66. else: # self.iterations == self.max_iterations
  67. try:
  68. packet = self.restore()
  69. self.is_success = True
  70. except:
  71. self.is_success = False
  72. finally:
  73. return packet
  74. def establish(self, packet):
  75. # fileName = '%d.tc_state.%d' % (self._id, len(self.checkpoints))
  76. # with open(fileName, 'w') as storage:
  77. # pickle.dump(packet, storage)
  78. # self.checkpoints.append(fileName)
  79. self.checkpoints.append(packet.copy_state(self.condition))
  80. def restore(self):
  81. # with open(self.checkpoints[-1], 'r') as storage:
  82. # packet = pickle.load(storage)
  83. # return packet
  84. # os.remove(self.checkpoints[-1])
  85. if len(self.checkpoints) > 0:
  86. return self.checkpoints.pop()
  87. raise Exception('There are no checkpoints to restore')
  88. def discard(self):
  89. # os.remove(self.checkpoints[-1])
  90. if len(self.checkpoints) > 0:
  91. del self.checkpoints[-1]
  92. raise Exception('There are no checkpoints to discard')
  93. def discard_all(self):
  94. # for fn in self.checkpoints:
  95. # os.remove(fn)
  96. self.checkpoints = []