motifcontext.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. '''
  2. Transformation context for MoTif
  3. Author: Huseyin Ergin (hergin)
  4. Purpose: MoTif integration to AtomPM
  5. '''
  6. import random
  7. import collections
  8. import datetime
  9. from time import *
  10. import timeit
  11. from tconstants import TConstants as TC
  12. from utils import Utilities as utils
  13. from tcontext import TransformationContext
  14. from pytcore.tcore.messages import Pivots
  15. from pytcore.rules.arule import ARule
  16. from pytcore.rules.query import Query
  17. from pytcore.rules.query import CQuery2
  18. from pytcore.rules.query import CQuery3
  19. from pytcore.rules.srule import SRule
  20. from pytcore.rules.crule import CRule
  21. from pytcore.rules.frule import FRule
  22. from pytcore.rules.brule import BRule
  23. from pytcore.rules.bsrule import BSRule
  24. from pytcore.rules.lrule import LRule
  25. from pytcore.rules.lfrule import LFRule
  26. from pytcore.rules.lsrule import LSRule
  27. from pytcore.rules.lqsrule import LQSRule
  28. from pytcore.rules.sequence import Sequence
  29. '''
  30. holds the execution context of a 'Transformation' construct
  31. t
  32. fname the filename of the transformation model '''
  33. class MotifContext(TransformationContext) :
  34. def __init__(self,fname,ptcal):
  35. super(MotifContext,self).__init__(ptcal._transfData[fname])
  36. self.fname = fname
  37. self.metamodel = TC.MOTIFMM
  38. self.pivots=Pivots()
  39. self.totalExecutionTime=0
  40. self.sendAndApplyDeltaFunc = ptcal.sendAndApplyDelta
  41. self.nextInput = "packetIn"
  42. self.compiler = ptcal._compiler
  43. self.ptcal = ptcal
  44. self.rules = {}
  45. self.startStateID = None
  46. for id in self.t['nodes']:
  47. rule = self.ruleIdentifier(self.t['nodes'], id)
  48. if rule == None:
  49. if self.t['nodes'][id]['$type'] == self.metamodel+"/LRule" or\
  50. self.t['nodes'][id]['$type'] == self.metamodel+"/LSRule" or\
  51. self.t['nodes'][id]['$type'] == self.metamodel+"/LFRule" or\
  52. self.t['nodes'][id]['$type'] == self.metamodel+"/LQSRule":
  53. maxIterations = int(self.t['nodes'][id]['maxIterations']['value'])
  54. nested = int(self.t['nodes'][id]['nested']['value'])
  55. outerFirst = True if nested==0 else False
  56. def f(e) :
  57. return e['src'] == id
  58. lruleEdges = filter(f,self.t['edges'])
  59. baseEdgeId=None
  60. loopEdgeId=None
  61. for edge in lruleEdges:
  62. if self.t['nodes'][edge['dest']]['$type']==self.metamodel+"/base":
  63. baseEdgeId=edge['dest']
  64. elif self.t['nodes'][edge['dest']]['$type']==self.metamodel+"/loop":
  65. loopEdgeId=edge['dest']
  66. def f(e) :
  67. return e['src'] == baseEdgeId
  68. baseRuleIds = filter(f,self.t['edges'])
  69. baseRuleID=baseRuleIds[0]['dest']
  70. compiledBaseRule = None
  71. if self.t['nodes'][id]['$type'] == self.metamodel+"/LRule" or\
  72. self.t['nodes'][id]['$type'] == self.metamodel+"/LQSRule":
  73. baseRuleName = self.t['nodes'][baseRuleID]['query']['value']
  74. compiledBaseRule = self.compiler.compileRule(None,baseRuleName)
  75. else:
  76. baseRuleName = self.t['nodes'][baseRuleID]['rule']['value']
  77. compiledBaseRule = self.compiler.compileRule(None,baseRuleName)
  78. #baseRule = ARule(compiledBaseRule['lhs'],compiledBaseRule['rhs'],self.sendAndApplyDeltaFunc)
  79. def f(e) :
  80. return e['src'] == loopEdgeId
  81. loopRuleIds = filter(f,self.t['edges'])
  82. loopRuleID=loopRuleIds[0]['dest']
  83. loopRuleType = self.t['nodes'][loopRuleID]['$type']
  84. if loopRuleType != self.metamodel+"/CRule":
  85. loopRuleName = self.t['nodes'][loopRuleID]['rule']['value']
  86. compiledLoopRule = self.compiler.compileRule(None,loopRuleName)
  87. loopRule = None
  88. if loopRuleType == self.metamodel+"/ARule":
  89. loopRule = ARule(compiledLoopRule['lhs'],compiledLoopRule['rhs'],self.sendAndApplyDeltaFunc)
  90. elif loopRuleType == self.metamodel+"/FRule":
  91. loopRule = FRule(compiledLoopRule['lhs'],compiledLoopRule['rhs'],maxIterations,self.sendAndApplyDeltaFunc)
  92. elif loopRuleType == self.metamodel+"/SRule":
  93. loopRule = SRule(compiledLoopRule['lhs'],compiledLoopRule['rhs'],maxIterations,self.sendAndApplyDeltaFunc)
  94. elif loopRuleType == self.metamodel+"/CRule":
  95. ruleName = self.t['nodes'][loopRuleID]['ref']['value']
  96. self.ptcal._transfData[ruleName] = utils.fread('/users/%s/%s'%(self.ptcal.username,ruleName))
  97. motifContext = MotifContext(ruleName,self.ptcal)
  98. loopRule = CRule(motifContext)
  99. if self.t['nodes'][id]['$type'] == self.metamodel+"/LRule":
  100. rule = LRule(compiledBaseRule['lhs'],loopRule,max_iterations=maxIterations)
  101. elif self.t['nodes'][id]['$type'] == self.metamodel+"/LQSRule":
  102. rule = LQSRule(compiledBaseRule['lhs'],loopRule,max_iterations=maxIterations)
  103. elif self.t['nodes'][id]['$type'] == self.metamodel+"/LSRule":
  104. rule = LSRule(compiledBaseRule['lhs'],compiledBaseRule['rhs'],loopRule,outer_first=outerFirst,sendAndApplyDeltaFunc=self.sendAndApplyDeltaFunc,max_iterations=maxIterations)
  105. elif self.t['nodes'][id]['$type'] == self.metamodel+"/LFRule":
  106. rule = LFRule(compiledBaseRule['lhs'],compiledBaseRule['rhs'],loopRule,outer_first=outerFirst,sendAndApplyDeltaFunc=self.sendAndApplyDeltaFunc,max_iterations=maxIterations)
  107. elif self.t['nodes'][id]['$type'] == self.metamodel+"/BRule" or\
  108. self.t['nodes'][id]['$type'] == self.metamodel+"/BSRule":
  109. def f(e) :
  110. return e['src'] == id
  111. bruleEdges = filter(f,self.t['edges'])
  112. branchRuleList=[]
  113. for edge in bruleEdges:
  114. if self.t['nodes'][edge['dest']]['$type']==self.metamodel+"/branch":
  115. branchID=edge['dest']
  116. def f(e) :
  117. return e['src'] == branchID
  118. branchRuleID=filter(f,self.t['edges'])[0]['dest']
  119. rule = self.ruleIdentifier(self.t['nodes'],branchRuleID)
  120. if rule == None and self.t['nodes'][branchRuleID]['$type']==self.metamodel+"/CRule":
  121. ruleName = self.t['nodes'][branchRuleID]['ref']['value']
  122. self.ptcal._transfData[ruleName] = utils.fread('/users/%s/%s'%(self.ptcal.username,ruleName))
  123. motifContext = MotifContext(ruleName,self.ptcal)
  124. rule = CRule(motifContext)
  125. branchRuleList.append(rule)
  126. if self.t['nodes'][id]['$type'] == self.metamodel+"/BRule":
  127. rule = BRule(branchRuleList)
  128. elif self.t['nodes'][id]['$type'] == self.metamodel+"/BSRule":
  129. maxIterations = int(self.t['nodes'][id]['maxIterations']['value'])
  130. rule = BSRule(branchRuleList,maxIterations)
  131. elif self.t['nodes'][id]['$type'] == self.metamodel+"/CRule":
  132. rule = self.t['nodes'][id]['ref']['value']
  133. elif self.t['nodes'][id]['$type'] == self.metamodel+"/Sequence":
  134. sequenceRuleList=[]
  135. rulesFile = self.t['nodes'][id]['ref']['value']
  136. self.ptcal._transfData[rulesFile] = utils.fread('/users/%s/%s'%(self.ptcal.username,rulesFile))
  137. rulesOrdered = collections.OrderedDict(sorted(self.ptcal._transfData[rulesFile]['nodes'].items()))
  138. for ruleId in rulesOrdered:
  139. rule = self.ruleIdentifier(rulesOrdered,ruleId)
  140. if rule != None:
  141. sequenceRuleList.append(rule)
  142. else: # TODO decide for CRule
  143. pass
  144. rule = Sequence(sequenceRuleList)
  145. elif self.t['nodes'][id]['$type'] == self.metamodel+"/Start":
  146. self.startStateID = id
  147. rule = None
  148. if rule != None:
  149. self.rules[id] = {'id':id,
  150. 'name':self.t['nodes'][id]['name']['value'],
  151. 'alias':self.t['nodes'][id]['alias']['value'],
  152. 'rule':rule}
  153. def ruleIdentifier(self,ruleList,ruleId):
  154. rule = None
  155. if ruleList[ruleId]['$type']==self.metamodel+"/ARule":
  156. ruleName = ruleList[ruleId]['rule']['value']
  157. compiledRule = self.compiler.compileRule(None,ruleName)
  158. rule = ARule(compiledRule['lhs'],compiledRule['rhs'],self.sendAndApplyDeltaFunc)
  159. elif ruleList[ruleId]['$type']==self.metamodel+"/QRule":
  160. ruleName = ruleList[ruleId]['query']['value']
  161. compiledRule = self.compiler.compileRule(None,ruleName)
  162. rule = Query(compiledRule['lhs'])
  163. elif ruleList[ruleId]['$type']==self.metamodel+"/FRule":
  164. maxIterations = ruleList[ruleId]['maxIterations']['value']
  165. ruleName = ruleList[ruleId]['rule']['value']
  166. compiledRule = self.compiler.compileRule(None,ruleName)
  167. rule = FRule(compiledRule['lhs'],compiledRule['rhs'],int(maxIterations),self.sendAndApplyDeltaFunc)
  168. elif ruleList[ruleId]['$type']==self.metamodel+"/SRule":
  169. maxIterations = ruleList[ruleId]['maxIterations']['value']
  170. ruleName = ruleList[ruleId]['rule']['value']
  171. compiledRule = self.compiler.compileRule(None,ruleName)
  172. rule = SRule(compiledRule['lhs'],compiledRule['rhs'],int(maxIterations),self.sendAndApplyDeltaFunc)
  173. elif ruleList[ruleId]['$type'] == self.metamodel+"/CQRule2":
  174. ruleName = ruleList[ruleId]['query']['value']
  175. innerRuleName = ruleList[ruleId]['innerQuery']['value']
  176. compiledRule = self.compiler.compileRule(None,ruleName)
  177. compiledInnerRule = self.compiler.compileRule(None,innerRuleName)
  178. innerQuery = Query(compiledInnerRule['lhs'])
  179. rule = CQuery2(compiledRule['lhs'],innerQuery)
  180. elif ruleList[ruleId]['$type'] == self.metamodel+"/CQRule3":
  181. ruleName = ruleList[ruleId]['query']['value']
  182. innerRuleName = ruleList[ruleId]['innerQuery']['value']
  183. secondInnerRuleName = ruleList[ruleId]['secondInnerQuery']['value']
  184. compiledRule = self.compiler.compileRule(None,ruleName)
  185. compiledInnerRule = self.compiler.compileRule(None,innerRuleName)
  186. compiledSecondInnerRule = self.compiler.compileRule(None,secondInnerRuleName)
  187. innerQuery = Query(compiledInnerRule['lhs'])
  188. secondInnerQuery = Query(compiledSecondInnerRule['lhs'])
  189. rule = CQuery3(compiledRule['lhs'],innerQuery,secondInnerQuery)
  190. return rule
  191. def setLastStepExecTime(self,a):
  192. self._lastStep['time'] = a
  193. self.totalExecutionTime += a
  194. '''
  195. returns the id of the current step in the transformation model '''
  196. def getCurrentStepId(self) :
  197. if self._lastStep == {} :
  198. assert False, \
  199. "this function shouldn't be called when there is no current step"
  200. else :
  201. return self._lastStep['id']
  202. '''
  203. Returns the initial step of transformation which is the step after start state
  204. Steps to find initial step:
  205. 1- Find start state id in self.t['nodes']
  206. 2- Find the edge where start is the 'src'
  207. 3- The edge has the initial step as 'dest' after the link between
  208. Structure:
  209. (startID) ----- (linkID) -----> (initialID)
  210. (startID, linkID) is an edge
  211. (linkID, initialID) is another edge
  212. '''
  213. def _getInitialStep(self) :
  214. if self.startStateID==None:
  215. raise RuntimeError('There is no start state in loaded MoTif instance!')
  216. def f(e) :
  217. return e['src'] == self.startStateID
  218. startStateEdges = filter(f,self.t['edges'])
  219. initialStepID=None
  220. if len(startStateEdges) == 0 :
  221. raise RuntimeError('Start state is not connected to any other state!')
  222. else:
  223. firstLinkID=startStateEdges[0]['dest']
  224. def f(e) :
  225. return e['src'] == firstLinkID
  226. startStateEdges = filter(f,self.t['edges'])
  227. initialStepID=startStateEdges[0]['dest']
  228. if initialStepID in self.rules:
  229. return self.rules[initialStepID]
  230. else:
  231. if self.t['nodes'][initialStepID]['$type']==self.metamodel+"/EndSuccess":
  232. return {'trafoResult':TC.SUCCEEDED,
  233. 'feedbackReceived':'True'}
  234. elif self.t['nodes'][initialStepID]['$type']==self.metamodel+"/EndFail":
  235. return {'trafoResult':TC.FAILED,
  236. 'feedbackReceived':'True'}
  237. '''
  238. return the next step to run in this transformation... this is either
  239. the initial step OR a neighbour of the last step... which one of these
  240. neighbours is the next step is determined by the application information
  241. of the said last step
  242. 0. if self._expired is true (i.e., a race condition occurred causing this
  243. context to be called after it terminated but before ptcal.stop()
  244. removed it from ptcal._mtContexts), raise error
  245. 1. if there is no last step, return initial step
  246. 2. filter through edges to find appropriate edge out of last step
  247. a) if none is found, reset lastStep, set self._expired flag, and
  248. return the application information of this entire transformation
  249. context
  250. b) otherwise, return step on the other end of the said edge
  251. Next step structure
  252. lastStepID --> successID --> nextID
  253. --> failID --> nextID
  254. Steps to find next
  255. 1- Filter edges and get (lastStepID, successID) and (lastStepID,failID) edges
  256. 2- Select success or fail according to _lastStep['applicationInfo']
  257. 3- Find this edge (nextPath, nextStepID) where nextPath is one of the success or fail ids.
  258. '''
  259. def nextStep(self) :
  260. timeNextStep = clock()
  261. if self._expired == True :
  262. raise RuntimeError('can not step in expired mtContext')
  263. elif self._lastStep == {} :
  264. ns = self._getInitialStep()
  265. if ns == None :
  266. return {'$err':'could not find initial transformation step'}
  267. self._lastStep = ns
  268. return ns
  269. else :
  270. def f(e) :
  271. return e['src'] == self._lastStep['id']
  272. edgesFromLastStep = filter(f,self.t['edges'])
  273. if len(edgesFromLastStep) == 0 :
  274. ai = self._applicationInfo()
  275. self._lastStep = {}
  276. self._expired = True
  277. return ai
  278. else :
  279. targetLinkID=None
  280. resString = None
  281. if self._lastStep['applicationInfo'] == TC.SUCCEEDED :
  282. resString = self.metamodel+"/success"
  283. else :
  284. resString = self.metamodel+"/fail"
  285. for edgeLS in edgesFromLastStep:
  286. if self.t['nodes'][edgeLS['dest']]['$type'] == resString:
  287. targetLinkID=edgeLS['dest']
  288. break
  289. def f(e) :
  290. return e['src'] == targetLinkID
  291. nodesAfterLastStep = filter(f,self.t['edges'])
  292. nextStepID = nodesAfterLastStep[0]['dest']
  293. if nextStepID in self.rules:
  294. self._lastStep = self.rules[nextStepID]
  295. else:
  296. if self.t['nodes'][nextStepID]['$type']==self.metamodel+"/EndSuccess":
  297. self._lastStep = {'trafoResult':TC.SUCCEEDED,
  298. 'feedbackReceived':'True'}
  299. elif self.t['nodes'][nextStepID]['$type']==self.metamodel+"/EndFail":
  300. self._lastStep = {'trafoResult':TC.FAILED,
  301. 'feedbackReceived':'True'}
  302. #print clock()-timeNextStep
  303. return self._lastStep
  304. '''
  305. set the application information of the last step '''
  306. def setLastStepApplicationInfo(self,applicationInfo) :
  307. if applicationInfo == TC.SUCCEEDED :
  308. self._notApplicable = False
  309. self._lastStep['applicationInfo'] = applicationInfo
  310. def isLastStepFeedbackReceived(self) :
  311. return (not self._expired and self._lastStep=={}) or \
  312. 'feedbackReceived' in self._lastStep