Ejemplo n.º 1
0
    async def write_unlock(self, obj_ids: Union[Iterable[str], str], owner: str, notify: bool = False) -> None:
        """Check object lock real owner and remove it from lock database.

        :param obj_ids: object identifiers to be locked
        :param owner: lock owner name
        :param notify: if set, send-out notification about unlocked objects
        """

        if isinstance(obj_ids, str):
            obj_ids = [obj_ids]
        else:
            obj_ids = list(obj_ids)

        roots = [await self.get_root_id(obj_id) for obj_id in obj_ids]

        async with self._lock:
            locked_trees = self._write_unlock(roots, obj_ids, owner)

        ui_locked = set(obj_ids)
        for obj_id, locked_tree in zip(roots, locked_trees):  # TODO lock only tree from affected object
            if locked_tree:
                ui_locked.update(self.get_all_children(obj_id))
                ui_locked.update(roots)

        # Always try to remove locked objects from database, so it won't get messy when deleting too many objects
        self._remove_user_locked_objects(owner, list(ui_locked))

        if notify:
            self.notifications_q.put_nowait(LockEventData(ui_locked, owner))
Ejemplo n.º 2
0
    async def write_lock(
        self, obj_ids: Union[Iterable[str], str], owner: str, lock_tree: bool = False, notify: bool = False
    ) -> bool:
        """Lock object or list of objects for writing, possible to lock whole
        tree where object(s) is located.

        :param obj_ids: object or objects to be locked
        :param owner: name of lock owner
        :param lock_tree: boolean whether lock whole tree
        :param notify: if set, broadcast information about locked objects and store those objects in user lock database
        :return: boolean whether lock was successful
        """

        assert isinstance(obj_ids, str) and lock_tree or not lock_tree

        if isinstance(obj_ids, str):
            obj_ids = [obj_ids]

        roots = [await self.get_root_id(obj_id) for obj_id in obj_ids]

        async with self._lock:
            ret = self._write_lock(roots, obj_ids, owner, lock_tree)

        if ret and notify:
            ui_locked = set(obj_ids)
            if lock_tree:
                for obj_id in roots:  # TODO lock only tree from affected object
                    ui_locked.update(self.get_all_children(obj_id))
                ui_locked.update(roots)
            self._upsert_user_locked_objects(owner, list(ui_locked))
            self.notifications_q.put_nowait(LockEventData(ui_locked, owner, True))
        return ret
Ejemplo n.º 3
0
    async def update_lock(self, obj_id: str, owner: str,
                          upgrade_type: UpdateType) -> None:
        """Upgrades lock to locked whole tree or downgrades lock to simple
        object lock.

        :param obj_id: objects which is locked and updated
        :param owner: owner of current lock
        :param upgrade_type: one of available type
        """

        root_id = await self.get_root_id(obj_id)

        async with self._lock:
            if root_id not in self._locked_objects:
                raise LockingException(self.ErrMessages.NOT_LOCKED.value)

            lock_record = self._get_lock_record(root_id)
            if upgrade_type == UpdateType.TREE:
                lock_record.check_upgrade(obj_id, owner)
                lock_record.tree = True

                to_notify = self.get_all_children(root_id)
                to_notify.add(root_id)
                to_notify.remove(obj_id)
                evt = LockEventData(to_notify, owner, True)

                self._upsert_user_locked_objects(owner, to_notify)
            elif upgrade_type == UpdateType.OBJECT:
                lock_record.check_downgrade(obj_id, owner)
                lock_record.tree = False

                to_notify = self.get_all_children(root_id)
                to_notify.add(root_id)
                to_notify -= {obj_id}
                evt = LockEventData(to_notify, owner)

                self._remove_user_locked_objects(owner, to_notify)
            else:
                raise Arcor2Exception("Unknown type of lock upgrade")

            self.notifications_q.put_nowait(evt)
Ejemplo n.º 4
0
async def register_user_cb(req: srpc.u.RegisterUser.Request,
                           ui: WsClient) -> None:

    await glob.USERS.login(req.args.user_name, ui)
    logger.debug(
        f"User {req.args.user_name} just logged in. Known user names are: {glob.USERS.user_names}"
    )

    await glob.LOCK.cancel_auto_release(req.args.user_name)

    # those are locks that are known for all users
    for user, user_objects in glob.LOCK.all_ui_locks.items():
        if user != req.args.user_name:
            glob.LOCK.notifications_q.put_nowait(
                LockEventData(user_objects, user, True, ui))

    # these locks are known only to the current user
    if user_write_locks := (await
                            glob.LOCK.get_owner_locks(req.args.user_name))[1]:
        glob.LOCK.notifications_q.put_nowait(
            LockEventData(user_write_locks, req.args.user_name, True, ui))
Ejemplo n.º 5
0
async def register_user_cb(req: srpc.u.RegisterUser.Request,
                           ui: WsClient) -> None:

    await glob.USERS.login(req.args.user_name, ui)
    glob.logger.debug(
        f"User {req.args.user_name} just logged in. Known user names are: {glob.USERS.user_names}"
    )

    await glob.LOCK.cancel_auto_release(req.args.user_name)

    for user, user_objects in glob.LOCK.all_ui_locks.items():
        if user != req.args.user_name:
            glob.LOCK.notifications_q.put_nowait(
                LockEventData(user_objects, user, True, ui))

    _, user_write_locks = await glob.LOCK.get_owner_locks(req.args.user_name)
    if user_write_locks:
        glob.LOCK.notifications_q.put_nowait(
            LockEventData(user_write_locks, req.args.user_name, True, ui))

    return None
Ejemplo n.º 6
0
    async def _release_all_owner_locks(self, owner: str) -> None:
        """Task planned after user logout. Release all its lock after timeout
        and notify UIs.

        :param owner: unregistered user
        """

        await asyncio.sleep(self.LOCK_TIMEOUT)

        async with self._lock:
            read, write = self._get_owner_locks(owner)
            self._read_unlock(list(read), list(read.values()), owner)
            self._write_unlock(list(write), list(write.values()), owner)

        to_notify = self._ui_user_locks[owner].copy()
        del self._ui_user_locks[owner]

        if to_notify:
            self.notifications_q.put_nowait(LockEventData(to_notify, owner))