Example #1
0
 def lock_and_update_flag(cls, __ctx, dictData):
     '''
        update data to an existing context
     :param contextKey: first hash level
     :param value: second hash level
     :param dictData: a dictionary of data ( resulting  from a memorize() evaluation ) 
     '''
     try:
         with cls.mutex:        
             __ctx=cls.hash[__ctx.contextKey][__ctx.contextValue]
             if not __ctx.isLocked():
                 return False
             
             asynclog.log(pos='%s.__manage' %(cls.__name__), key=__ctx.contextKey,value=__ctx.contextValue, 
                          ctx=__ctx, msg='LOCK IS UP' )    
             __ctx.setFlag()
             # update dictRuntime data
             __ctx.getCacheKeys().update_keys(dictData)
             asynclog.log(pos='%s.update_and_flag' %(cls.__name__), key=__ctx.contextKey,value=__ctx.contextValue, 
                          msg='updated with notification data',ctx=__ctx )
             return True
             
     except Exception, e:
         asynclog.logError(pos='%s.update_and_flag' %(cls.__name__), key=__ctx.contextKey,value=__ctx.contextValue, msg='update notification data permanently',err=str(e) )
         raise e
Example #2
0
 def update(cls, key, value, dictData):
     '''
        update data to an existing context
     :param contextKey: first hash level
     :param value: second hash level
     :param dictData: a dictionary of data ( resulting  from a memorize() evaluation ) 
     '''
     try:
         with cls.mutex:        
             cls.hash[key][value].getCacheKeys().update_keys_permanently(dictData)
             asynclog.log(pos='%s.update' %(cls.__name__), key=key,value=value, msg='update notification data permanently' )
     except Exception, e:
         asynclog.logError(pos='%s.update' %(cls.__name__), key=key,value=value, msg='update notification data permanently',err=str(e) )
         raise e
Example #3
0
 def updateCache(cls,__ctx):
     key,value=__ctx.contextKey,__ctx.contextValue
     try:
         with cls.mutex:
             # get DictRuntime keys
             __data=cls.hash[key][value].getCacheKeys().get()
             
             if logger.isTraceEnabled():
                 asynclog.logTrace(pos='%s.updateCache' %(cls.__name__), key=key,value=value, msg='update with callback cache. data: %s' % (__data) )
             # Merge with current context REF cache 
             __ctx.getCacheKeys().update_asyncData_permanently(__data)
             return cls.hash[key][value].getCacheKeys()
     except Exception, e:
         asynclog.logError(pos='%s.updateCache' %(cls.__name__), key=key,value=value, msg='update callback cache',err=str(e) )
Example #4
0
 def pop_ctx_value(cls, key,value):
     '''
        find a Context() identified by its 2 levels
        if found, remove from the Context from the hash
     :param contextKey: first level
     :param value: second level
     '''
     try:
         with cls.mutex:       
             asynclog.log(pos='%s.pop_ctx_value' %(cls.__name__), key=key,value=value, msg='')
             return cls.hash[key].pop(value)
     except KeyError:
         if not key in cls.hash:
             logger.error('Key "%s" not defined, check what happens for the value "%s" in the asynchronous.call_after()' % (key,value))
         else:
             logger.error('Key "%s" exists but value "%s" not found - check asynchronous.call_after() at the add() context call' % (key,value))
         return None
     except Exception,e:
         asynclog.logError(pos='%s.pop_ctx_value' %(cls.__name__), key=key,value=value, msg='',err=str(e) )
         return None
Example #5
0
 def add_ctx(cls, key, value, clonedContext):
     '''
        Add a Context() instance to the hash of hash
     :param contextKey: first hash level
     :param value: second hash level
     :param contextInstance: the value for the second level of type Context()
     '''
     try:
         with cls.mutex:
             if not key in cls.hash:
                 cls.hash[key] = {}
             
             # Set a functional lock from callback_before()
             clonedContext.setLock()
             cls.hash[key][value] = clonedContext
             
             asynclog.log(pos='%s.add_ctx' %(cls.__name__), key=key,value=value, msg='storing context',ctx=clonedContext )
             
     # No ERROR logger trace here, as it is reported one level up
     except Exception, e:
         asynclog.logError(pos='%s.add' %(cls.__name__), key=key,value=value, msg='storing context failed',err=str(e),ctx=clonedContext )
         raise e
Example #6
0
class ContextIdentifier:
    
    hash={}
    mutex=Condition()
    reaperThread = None
    stopReaperThread=False
    threadStarted=False
    
        
    @classmethod
    def start(cls):
        cls.reaperThread = Thread( target=cls.reaperLoop, name="ContextIdentifierReaperThread")
        cls.stopReaperThread=False
        cls.reaperThread.start()
        cls.threadStarted=True
        
    @classmethod
    def stop(cls):
        if cls.reaperThread is not None:
            cls.stopReaperThread=True
    
         
    @classmethod
    def isLocked(cls, key, value):
        '''
        check if cache resource is locked
        '''
        try:
            with cls.mutex:
                asynclog.log(pos='%s.isLocked' %(cls.__name__), key=key,value=value, msg='lock flag set' )
                return cls.hash[key][value].isLocked()
        except KeyError,e:
            # This could happen if entry was removed from cache
            asynclog.logWarning(pos='%s.isLocked' %(cls.__name__), key=key,value=value, msg='unlock flag', err=str(e))
            pass
        except Exception, e:
            asynclog.logError(pos='%s.isLocked' %(cls.__name__), key=key,value=value, msg='unlock flag', err=str(e))
Example #7
0
        return False

    @classmethod
    def unlock(cls, key, value):
        '''
        check if cache resource is locked
        '''
        try:
            with cls.mutex:
                asynclog.log(pos='%s.unlock' %(cls.__name__), key=key,value=value, msg='unlock flag' )
                return cls.hash[key][value].unlock()
        except KeyError, e:
            # This could happen if entry was removed from cache
            asynclog.logWarning(pos='%s.unlock' %(cls.__name__), key=key,value=value, msg='unlock flag', err=str(e))
        except Exception, e:
            asynclog.logError(pos='%s.unlock' %(cls.__name__), key=key,value=value, msg='unlock flag', err=str(e))
        # if the key/value doesn't exists - it has been swept
        return False


        
    @classmethod
    def add_ctx(cls, key, value, clonedContext):
        '''
           Add a Context() instance to the hash of hash
        :param contextKey: first hash level
        :param value: second hash level
        :param contextInstance: the value for the second level of type Context()
        '''
        try:
            with cls.mutex:
Example #8
0
                return
            except Exception, e:
                logger.error(
                    '<<ASYNC>>[%s=%s][%s.__manage] context management ,reason: %s'
                    % (contextKey, contextValue, self.__class__.__name__, e))
                raise (e)
        #
        # Anomaly : If we are here, it means, the context is no more in the cache
        #           Either it's real problem either the context has expired
        #
        try:
            asynclog.logError(
                pos='%s.__manage' % (self.__class__.__name__),
                key=contextKey,
                value=contextValue,
                msg=
                'IGNORED Unknown EVENT (Expiration occurred or real processing error)',
                err='Unknown EVENT received')
            if logger.isTraceEnabled():
                logger.trace(ContextIdentifier.printall())
        except Exception, e:
            logger.error(
                '<<ASYNC>>[%s=%s][%s.__manage] No ctx found () !, reason: %s' %
                (contextKey, contextValue, self.__class__.__name__, e))
            raise (e)

    def handle(self, httpExchange):
        try:
            method = httpExchange.getRequestMethod()
            requestHeaders = httpExchange.getRequestHeaders()
Example #9
0
    def call_before(cls, __ctx):

        # ZERO, increase the number of context waiting (should be clean up in case of expiration)
        # *** This Object is useful for Validation mode ***
        # TODO: check this is not useless - as the number of waiting context is in the ContextIdentifier class
        if __ctx.line.asyncBlocking():
            ContextLock.contextIncrease()

            if logger.isTraceEnabled():
                logger.trace(
                    '<<ASYNC>> asynchronous.call_before() - contextIncrease() & lock() - [ContextLock=%d]'
                    % (ContextLock.count()))

        if not __ctx.line.multipleCaller:

            # This is the expiration criteria in ContextIdentifier reaper thread
            #
            __ctx.line.timeout = int(__ctx.line.timeout)
            # expiration date in milli seconds (-1 means NO expiration)
            expirationTime = ((__ctx.line.timeout + time.time()) *
                              1000 if __ctx.line.timeout != -1 else -1)
            __ctx.setExpirationTime(expirationTime)

            #
            # FIRST, get the context identifier value
            #  3 cases:
            #    value: ${VAR}
            #    value: xxxx                     => a fixed literal value
            #    "value" keyword is not defined  => get the current value from the contextKey in the running context
            #

            # Remember: line is only a definition (Immutable)
            contextKeyValue = __ctx.line.contextValue if __ctx.line.contextValue else __ctx.line.contextKey
            __ctx.contextKey = __ctx.line.contextKey
            __ctx.contextValue = __ctx.getCacheKeys().getValue(contextKeyValue)

            asynclog.logTrace(pos='%s.call_before' % (cls.__name__),
                              msg='Initializing key/value',
                              key=__ctx.contextKey,
                              value=__ctx.contextValue)

            if not __ctx.contextValue:
                asynclog.logError(pos='%s.call_before' % (cls.__name__),
                                  key=__ctx.contextKey,
                                  value=__ctx.contextValue,
                                  msg='\ncache=%s' %
                                  (__ctx.getCacheKeys().dictRuntime),
                                  err='No value found in cache')
                raise SyntaxError(
                    '[Asynchronous step] contextKey "%s" must have a value in the context or have a "value","contextValue" defined in the scenation'
                    % (__ctx.contextKey))

            asynclog.log(pos='%s.callBefore' % (cls.__name__),
                         key=__ctx.contextKey,
                         value=contextKeyValue,
                         msg='initial async identifiers')

            # SECOND, send the JSON message to the ContextManager process
            #---------------------------------------------------------------
            # TODO: manage the case there is no context router !
            # TODO: manage the case we have only SMPP callback
            jsonMessage = None
            if __ctx.line.use_contextManager:
                try:
                    # client call to the router
                    # Time expressed in milliseconds
                    jsonMessage = '{"contextKey" : "%s", "value" : "%s", "host" : "%s", "port" : "%s", "expirationtime": "%s", "count": "%d"}' % (
                        __ctx.contextKey, __ctx.contextValue,
                        HTTPServerCallback.getHost(),
                        HTTPServerCallback.getPort(), expirationTime,
                        __ctx.line.callbackCount)
                    Configuration.getrouterContextClient().postJsonMessage(
                        jsonMessage,
                        Configuration.getrouterContextClient().getCreateUri())
                    logger.debug(
                        'CREATE - Posting the callback router [message: %s]' %
                        (jsonMessage))
                except Exception, e:
                    logger.error(
                        'CREATE - Error posting message to the contextRouter, stacktrace=%s'
                        % (str(e)))
                    raise Exception(
                        'CREATE - Error posting message to the contextRouter, stacktrace=%s'
                        % (str(e)))

            # bet that the call will succeed - so we store the contextKey, value doubleton in ContextIdentifier cache
            # We bet the oneWay will succeed, so we store the context for the callback
            asynclog.logInfo(pos='%s.callBefore' % (cls.__name__),
                             key=__ctx.contextKey,
                             value=__ctx.contextValue,
                             msg='Storing a cloned context')

            with cls.mutex:
                cloneContext = Context(__ctx.macrosAllScenario)
                cloneContext.copy(__ctx)
                asynclog.logTrace(
                    pos='%s.callBefore' % cls.__name__,
                    key=__ctx.contextKey,
                    value=__ctx.contextValue,
                    msg=
                    'Cloned object address: %s, original address=%s, context=%s'
                    % (hex(id(cloneContext)), hex(id(__ctx)), cloneContext))

                try:
                    ContextIdentifier.add_ctx(__ctx.contextKey,
                                              __ctx.contextValue, cloneContext)
                except Exception, e:
                    raise (e)
Example #10
0
    def process_callback(cls, __ctx, __data):

        __key, __value = __ctx.contextKey, __ctx.contextValue

        # Decrease all asynchronous counters & print value if trace level
        ContextLock.decreaseAllCounters('<<ASYNC>> %s.process_callback()' %
                                        (cls.__name__))

        # For debugging purpose, uid maintains an unique identifier in the log files
        MDC.put('uid', '[uid=%s]' % (__ctx.uid))

        # Ask to the implementation to process asynchronous data returned
        asynclog.log(pos='%s.process_callback' % cls.__name__,
                     key=__key,
                     value=__value,
                     msg='resuming with notification data : %s' % (__data))

        #
        # if the step as a tag async with a property timeout_success: True
        # coming back to the callback method means there was no timeout
        # so this is an assertion failure
        #
        if __ctx.line.isTimeoutSuccess():
            reporting.report_step_status(
                success=False,
                context=__ctx,
                cause='Assertion Failure: a timeout was expected',
                state='AsyncStepAssertTimeoutSuccessKO',
                synchronous=False)
            __ctx.endAsyncScenario()
            return True

        try:
            # Load an alternative implementation defined in the callback_implementation tag
            if __ctx.line.callback_implementation:
                asynclog.log(
                    pos='%s.process_callback' % cls.__name__,
                    key=__key,
                    value=__value,
                    msg=
                    'post-processing notification data with implementation "%s"'
                    % (str(__ctx.line.callback_implementation)))
                class_implementation = __ctx.scenario.loaded_implementations[
                    str(__ctx.line.callback_implementation)]
                processedData = class_implementation.process_data(__data)
            else:
                # Calling back the implementation to interpret the Mock data
                processedData = __ctx.getCurrentLine().getImplementation(
                ).process_data(__data)

        except (SyntaxError, KeyError), x:
            asynclog.logError(
                pos='%s.process_callback' % cls.__name__,
                key=__key,
                value=__value,
                msg=
                'SyntaxError/KeyError raised when processing process_data()',
                err=str(x))
            logger.error(
                '[state=StopAsyncStepFatalError][cause=%s][test=%s][scenario=%s]'
                % (repr(x), __ctx.line.getTestName(), __ctx.scenario))
            reporting.report_step_status(
                success=False,
                synchronous=False,
                context=__ctx,
                cause="%s\n while processing test '%s' in scenario '%s'" %
                (x, __ctx.line.getTestName(), __ctx.scenario),
                state='StopSAsynctepFatalError')
            raise SyntaxError(
                "%s\n while processing test '%s' in scenario '%s'" %
                (x, __ctx.line.getTestName(), __ctx.scenario))
Example #11
0
                success=False,
                synchronous=False,
                context=__ctx,
                cause="%s\n while processing test '%s' in scenario '%s'" %
                (x, __ctx.line.getTestName(), __ctx.scenario),
                state='StopSAsynctepFatalError')
            raise SyntaxError(
                "%s\n while processing test '%s' in scenario '%s'" %
                (x, __ctx.line.getTestName(), __ctx.scenario))

        # could be raised by process_data()
        except Exception, cause:
            asynclog.logError(
                pos='%s.process_callback' % cls.__name__,
                key=__key,
                value=__value,
                msg=
                'SyntaxError/KeyError raised when processing process_data()',
                err=str(x))
            # last boolean parameter means : caused by an async callback
            reporting.report_step_status(success=False,
                                         synchronous=False,
                                         context=__ctx,
                                         cause=cause,
                                         state='stopAsyncStepKO')
            __ctx.endAsyncScenario()
            return True

        # interpreted mock data must be a dictionary
        if not isinstance(processedData, dict):
            asynclog.logError(