tcorecontext.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. '''
  2. Transformation context for TCore
  3. Author: Huseyin Ergin (hergin)
  4. Purpose: Tcore integration to AtomPM
  5. '''
  6. import random
  7. from tconstants import TConstants as TC
  8. from utils import Utilities as utils
  9. from tcontext import TransformationContext
  10. from pytcore.tcore.messages import Pivots
  11. from pytcore.tcore.matcher import Matcher
  12. from pytcore.tcore.iterator import Iterator
  13. from pytcore.tcore.rewriter import Rewriter
  14. '''
  15. holds the execution context of a 'Transformation' construct
  16. fname the filename of the transformation model '''
  17. class TCoreContext(TransformationContext) :
  18. def __init__(self,fname,ptcal) :
  19. super(TCoreContext,self).__init__(ptcal._transfData[fname])
  20. self.fname = fname
  21. self.metamodel = TC.TCOREMM
  22. self.totalExecutionTime=0
  23. self.pivots = Pivots()
  24. self.sendAndApplyDeltaFunc=ptcal.sendAndApplyDelta
  25. self.nextInput = "packetIn"
  26. self.compiler = ptcal._compiler
  27. self.rules = {}
  28. self.startPacketInID = None
  29. self.startNextInID = None
  30. self.startCancelInID = None
  31. for id in self.t['nodes']:
  32. if self.t['nodes'][id]['$type'] == self.metamodel+"/Matcher":
  33. max = self.t['nodes'][id]['max']['value']
  34. ruleName = self.t['nodes'][id]['pattern']['value']
  35. compiledRule = self.compiler.compileRule(None,ruleName)
  36. matcher = Matcher(condition=compiledRule['lhs'],max=max)
  37. self.rules[id] = {'id':id,
  38. 'name':self.t['nodes'][id]['name']['value'],
  39. 'alias':self.t['nodes'][id]['alias']['value'],
  40. 'rule':matcher}
  41. elif self.t['nodes'][id]['$type'] == self.metamodel+"/Rewriter":
  42. ruleName = self.t['nodes'][id]['pattern']['value']
  43. compiledRule = self.compiler.compileRule(None,ruleName)
  44. rewriter = Rewriter(condition=compiledRule['rhs'],sendAndApplyDeltaFunc=self.sendAndApplyDeltaFunc)
  45. self.rules[id] = {'id':id,
  46. 'name':self.t['nodes'][id]['name']['value'],
  47. 'alias':self.t['nodes'][id]['alias']['value'],
  48. 'rule':rewriter}
  49. elif self.t['nodes'][id]['$type'] == self.metamodel+"/Iterator":
  50. maxIterations = self.t['nodes'][id]['maxIterations']['value']
  51. ruleName = self.t['nodes'][id]['pattern']['value']
  52. compiledRule = self.compiler.compileRule(None,ruleName)
  53. iterator = Iterator(condition=compiledRule['lhs'])
  54. self.rules[id] = {'id':id,
  55. 'name':self.t['nodes'][id]['name']['value'],
  56. 'alias':self.t['nodes'][id]['alias']['value'],
  57. 'rule':iterator}
  58. elif self.t['nodes'][id]['$type'] == self.metamodel+"/StartPacketIn":
  59. self.startPacketInID = id
  60. elif self.t['nodes'][id]['$type'] == self.metamodel+"/StartNextIn":
  61. self.startNextInID = id
  62. elif self.t['nodes'][id]['$type'] == self.metamodel+"/StartCancelIn":
  63. self.startCancelInID = id
  64. ''' TODO add other rules '''
  65. def setLastStepExecTime(self,a):
  66. self._lastStep['time'] = a
  67. self.totalExecutionTime += a
  68. '''
  69. returns the id of the current step in the transformation model '''
  70. def getCurrentStepId(self) :
  71. if self._lastStep == {} :
  72. assert False, \
  73. "this function shouldn't be called when there is no current step"
  74. else :
  75. return self._lastStep['id']
  76. '''
  77. Returns the initial step of transformation which is the step after start state
  78. '''
  79. def _getInitialStep(self) :
  80. if self.startPacketInID == None and self.startNextInID == None and self.startCancelInID == None:
  81. raise RuntimeError('There is no start state in loaded TCore instance!')
  82. ''' a regular Tcore trafo starts with an startPacketIn node '''
  83. if self.startPacketInID != None:
  84. startStateEdges = filter(lambda e:e['src']==self.startPacketInID,self.t['edges'])
  85. if len(startStateEdges) == 0 :
  86. raise RuntimeError('StartPacketIn is not connected to any other rule!')
  87. else:
  88. initialStepID=filter(lambda e:e['src']==startStateEdges[0]['dest'],self.t['edges'])[0]['dest']
  89. return self.rules[initialStepID]
  90. '''
  91. return the next step to run in this transformation... this is either
  92. the initial step OR a neighbour of the last step... which one of these
  93. neighbours is the next step is determined by the application information
  94. of the said last step
  95. 0. if self._expired is true (i.e., a race condition occurred causing this
  96. context to be called after it terminated but before ptcal.stop()
  97. removed it from ptcal._mtContexts), raise error
  98. 1. if there is no last step, return initial step
  99. 2. filter through edges to find appropriate edge out of last step
  100. a) if none is found, reset lastStep, set self._expired flag, and
  101. return the application information of this entire transformation
  102. context
  103. b) otherwise, return step on the other end of the said edge
  104. Next step structure
  105. lastStepID --> successID --> nextID
  106. --> failID --> nextID
  107. Steps to find next
  108. 1- Filter edges and get (lastStepID, successID) and (lastStepID,failID) edges
  109. 2- Select success or fail according to _lastStep['applicationInfo']
  110. 3- Find this edge (nextPath, nextStepID) where nextPath is one of the success or fail ids.
  111. '''
  112. def nextStep(self) :
  113. if self._expired == True :
  114. raise RuntimeError('can not step in expired mtContext')
  115. elif self._lastStep == {} :
  116. ns = self._getInitialStep()
  117. if ns == None :
  118. return {'$err':'could not find initial transformation step'}
  119. self._lastStep = ns
  120. return ns
  121. else :
  122. def f(e) :
  123. return e['src'] == self._lastStep['id']
  124. edgesFromLastStep = filter(f,self.t['edges'])
  125. if len(edgesFromLastStep) == 0 :
  126. ai = self._applicationInfo()
  127. self._lastStep = {}
  128. self._expired = True
  129. return ai
  130. else :
  131. targetLinkID=None
  132. resString = None
  133. if self._lastStep['applicationInfo'] == TC.SUCCEEDED :
  134. resString = "success"
  135. elif self._lastStep['applicationInfo'] == TC.FAILED:
  136. resString = "fail"
  137. else: #exception
  138. resString = "exception"
  139. for edgeLS in edgesFromLastStep:
  140. if 'output' in self.t['nodes'][edgeLS['dest']] and self.t['nodes'][edgeLS['dest']]['output']['value'] == resString:
  141. targetLinkID=edgeLS['dest']
  142. break
  143. elif 'output' not in self.t['nodes'][edgeLS['dest']]:
  144. if self.t['nodes'][edgeLS['dest']]['$type']==self.metamodel+"/endExceptionPort" and resString=='exception':
  145. targetLinkID=edgeLS['dest']
  146. break
  147. elif self.t['nodes'][edgeLS['dest']]['$type']==self.metamodel+"/endSuccessPort" and resString=='success':
  148. targetLinkID=edgeLS['dest']
  149. break
  150. elif self.t['nodes'][edgeLS['dest']]['$type']==self.metamodel+"/endFailPort" and resString=='fail':
  151. targetLinkID=edgeLS['dest']
  152. break
  153. if 'input' in self.t['nodes'][targetLinkID]:
  154. self.nextInput = self.t['nodes'][targetLinkID]['input']['value']
  155. def f(e) :
  156. return e['src'] == targetLinkID
  157. nodesAfterLastStep = filter(f,self.t['edges'])
  158. nextStepID = nodesAfterLastStep[0]['dest']
  159. if nextStepID in self.rules:
  160. self._lastStep = self.rules[nextStepID]
  161. else:
  162. if self.t['nodes'][nextStepID]['$type']==self.metamodel+"/EndSuccess":
  163. self._lastStep = {'trafoResult':TC.SUCCEEDED,
  164. 'feedbackReceived':'True'}
  165. elif self.t['nodes'][nextStepID]['$type']==self.metamodel+"/EndFail":
  166. self._lastStep = {'trafoResult':TC.FAILED,
  167. 'feedbackReceived':'True'}
  168. elif self.t['nodes'][nextStepID]['$type']==self.metamodel+"/EndException":
  169. self._lastStep = {'trafoResult':TC.EXCEPTION,
  170. 'feedbackReceived':'True'}
  171. return self._lastStep
  172. '''
  173. set the application information of the last step '''
  174. def setLastStepApplicationInfo(self,applicationInfo) :
  175. if applicationInfo == TC.SUCCEEDED :
  176. self._notApplicable = False
  177. self._lastStep['applicationInfo'] = applicationInfo
  178. def isLastStepFeedbackReceived(self) :
  179. return (not self._expired and self._lastStep=={}) or \
  180. 'feedbackReceived' in self._lastStep