Example #1
0
    def update(self, obj, edit_session):
        '''Updates model object lock as being active. Raises exception on
        error. obj should be either model object or its global identifier.'''
        cfg = self.env.cfg
        redis = self.env.redis
        key = self._item_lock_key(obj)

        with redis.pipeline() as pipe:
            for i in range(2):
                try:
                    # put a WATCH on the key that holds our sequence value
                    pipe.watch(key)
                    old_value = loads(pipe.get(key))

                    if old_value is None:
                        raise ModelLockIsLost()
                    elif old_value['edit_session']==edit_session:
                        # now we can put the pipeline back into buffered mode with MULTI
                        pipe.multi()
                        pipe.expire(key, cfg.MODEL_LOCK_TIMEOUT)
                        pipe.execute()
                        return edit_session
                    else:
                        lock_user = self.env.db.query(self.env.auth_model)\
                                                    .get(old_value['user_id'])
                        raise ModelLockedByOther(lock_user, old_value['edit_session'])
                except WatchError:
                    continue
        logger.error('Failed to update model object lock. '\
                     'Problem with redis?')
        raise ModelLockError()
Example #2
0
    def update(self, obj, edit_session):
        '''Updates model object lock as being active. Raises exception on
        error. obj should be either model object or its global identifier.'''
        cfg = self.env.cfg
        redis = self.env.redis
        key = self._item_lock_key(obj)

        with redis.pipeline() as pipe:
            for i in range(2):
                try:
                    # put a WATCH on the key that holds our sequence value
                    pipe.watch(key)
                    old_value = loads(pipe.get(key))

                    if old_value is None:
                        raise ModelLockIsLost()
                    elif old_value['edit_session'] == edit_session:
                        # now we can put the pipeline back into buffered mode with MULTI
                        pipe.multi()
                        pipe.expire(key, cfg.MODEL_LOCK_TIMEOUT)
                        pipe.execute()
                        return edit_session
                    else:
                        lock_user = self.env.db.query(self.env.auth_model)\
                                                    .get(old_value['user_id'])
                        raise ModelLockedByOther(lock_user,
                                                 old_value['edit_session'])
                except WatchError:
                    continue
        logger.error('Failed to update model object lock. '\
                     'Problem with redis?')
        raise ModelLockError()
Example #3
0
    def create(self, obj, force=False):
        '''Marks model object as editted. Returns edit session on success or
        raises exception. obj should be either model object or its global
        identifier. When force is True the current lock is ignored.'''
        cfg = self.env.cfg
        redis = self.env.redis

        edit_session = self._create_edit_session()
        key = self._item_lock_key(obj)
        value = self._item_lock_value(edit_session)
        if force:
            redis.set(key, json.dumps(value))
            redis.expire(key, cfg.MODEL_LOCK_TIMEOUT)
            return edit_session

        with redis.pipeline() as pipe:
            for i in range(2):
                try:
                    # put a WATCH on the key that holds our sequence value
                    pipe.watch(key)
                    # after WATCHing, the pipeline is put into immediate execution
                    # mode until we tell it to start buffering commands again.
                    # this allows us to get the current value of our sequence
                    old_value = loads(pipe.get(key))

                    if old_value is None:
                        # now we can put the pipeline back into buffered mode with MULTI
                        pipe.multi()
                        pipe.set(key, json.dumps(value))
                        pipe.expire(key, cfg.MODEL_LOCK_TIMEOUT)
                        # and finally, execute the pipeline (the set command)
                        pipe.execute()
                        # if a WatchError wasn't raised during execution, everything
                        # we just did happened atomically.
                        return edit_session
                    else:
                        lock_user = self.env.db.query(self.env.auth_model)\
                                                    .get(old_value['user_id'])
                        raise ModelLockedByOther(lock_user,
                                                 old_value['edit_session'])
                except WatchError:
                    continue
        logger.error('Failed to lock model object. '\
                     'Problem with redis?')
        raise ModelLockError()
Example #4
0
    def create(self, obj, force=False):
        '''Marks model object as editted. Returns edit session on success or
        raises exception. obj should be either model object or its global
        identifier. When force is True the current lock is ignored.'''
        cfg = self.env.cfg
        redis = self.env.redis

        edit_session = self._create_edit_session()
        key = self._item_lock_key(obj)
        value = self._item_lock_value(edit_session)
        if force:
            redis.set(key, json.dumps(value))
            redis.expire(key, cfg.MODEL_LOCK_TIMEOUT)
            return edit_session

        with redis.pipeline() as pipe:
            for i in range(2):
                try:
                    # put a WATCH on the key that holds our sequence value
                    pipe.watch(key)
                    # after WATCHing, the pipeline is put into immediate execution
                    # mode until we tell it to start buffering commands again.
                    # this allows us to get the current value of our sequence
                    old_value = loads(pipe.get(key))

                    if old_value is None:
                        # now we can put the pipeline back into buffered mode with MULTI
                        pipe.multi()
                        pipe.set(key, json.dumps(value))
                        pipe.expire(key, cfg.MODEL_LOCK_TIMEOUT)
                        # and finally, execute the pipeline (the set command)
                        pipe.execute()
                        # if a WatchError wasn't raised during execution, everything
                        # we just did happened atomically.
                        return edit_session
                    else:
                        lock_user = self.env.db.query(self.env.auth_model)\
                                                    .get(old_value['user_id'])
                        raise ModelLockedByOther(lock_user, old_value['edit_session'])
                except WatchError:
                    continue
        logger.error('Failed to lock model object. '\
                     'Problem with redis?')
        raise ModelLockError()
Example #5
0
    def create(self, obj, force=False):
        '''Marks model object as editted. Returns edit session on success or
        raises exception. obj should be either model object or its global
        identifier. When force is True the current lock is ignored.'''
        cfg = self.env.cfg
        cache = self.env.cache

        cache.cas_ids.clear()
        edit_session = self._create_edit_session()
        key = self._item_lock_key(obj)
        value = self._item_lock_value(edit_session)
        if force:
            if cache.set(key, value, time=cfg.MODEL_LOCK_TIMEOUT):
                return edit_session
            else:
                raise ModelLockError()
        for i in range(3):
            if cache.add(key, value, time=cfg.MODEL_LOCK_TIMEOUT):
                return edit_session
            old_value = cache.gets(key)
            if old_value is None:
                # Should try add() again
                continue
            if not old_value or \
                    time()-old_value['time']>cfg.MODEL_LOCK_TIMEOUT:
                # Somebody's lock is already expired
                if cache.cas(key, value,
                             time=cfg.MODEL_LOCK_TIMEOUT):
                    return edit_session
                else:
                    continue
            # Somebody holds active lock, no farther attempts
            break
        else:
            logger.error('Failed to lock model object. '\
                         'Problem with memcached?')
            raise ModelLockError()
        lock_user = self.env.db.query(self.env.auth_model)\
                                    .get(old_value['user_id'])
        raise ModelLockedByOther(lock_user, old_value['edit_session'])
Example #6
0
    def create(self, obj, force=False):
        '''Marks model object as editted. Returns edit session on success or
        raises exception. obj should be either model object or its global
        identifier. When force is True the current lock is ignored.'''
        cfg = self.env.cfg
        cache = self.env.cache

        cache.cas_ids.clear()
        edit_session = self._create_edit_session()
        key = self._item_lock_key(obj)
        value = self._item_lock_value(edit_session)
        if force:
            if cache.set(key, value, time=cfg.MODEL_LOCK_TIMEOUT):
                return edit_session
            else:
                raise ModelLockError()
        for i in range(3):
            if cache.add(key, value, time=cfg.MODEL_LOCK_TIMEOUT):
                return edit_session
            old_value = cache.gets(key)
            if old_value is None:
                # Should try add() again
                continue
            if not old_value or \
                    time()-old_value['time']>cfg.MODEL_LOCK_TIMEOUT:
                # Somebody's lock is already expired
                if cache.cas(key, value, time=cfg.MODEL_LOCK_TIMEOUT):
                    return edit_session
                else:
                    continue
            # Somebody holds active lock, no farther attempts
            break
        else:
            logger.error('Failed to lock model object. '\
                         'Problem with memcached?')
            raise ModelLockError()
        lock_user = self.env.db.query(self.env.auth_model)\
                                    .get(old_value['user_id'])
        raise ModelLockedByOther(lock_user, old_value['edit_session'])