*********************
Простое использование
*********************

Простые примеры использования модуля
====================================
В качестве примера работы с m3-mutex реализуем небольшой класс-семафор, который будет блокировать повторное редактирование уже заданного объекта::

	class ObjEditMutex(object):
        u"""Класс-семафор, блокирующий повторное редактирование объекта
        """
		
Добавим метод, который позволит нам получать id объекта::

        def get_obj_id(self, obj_id):
            u"""Подмена obj_id, для возможности переопределения класса.
            Позволяет использовать свой уникальный obj_id
            без изменения логики родительского класса.
            """
            return obj_id
			
Добавим метод, который позволит нам получать семафор по типу и id объекта::

        def get_mutex_id(self, mode, obj_id):
            u"""Возвращает id семафора для указанного типа и id объекта
    
            :param basestring mode: Тип объекта
            :param int obj_id: id объекта
    
            :rtype: int
            """
            return m3_mutex.MutexID(mode=mode, id=str(obj_id))

Добавим метод, который позволит нам проверять наличие семафора::
			
        def check(self, obj_id, mode, request_id):
            u"""Проверка на наличие семафора.
            Возвращает True, если объект не заблокирован или заблокирован нами.
            В противном случае возвращает False
            """
            obj_id = self.get_obj_id(obj_id)
            mutex_id = self.get_mutex_id(mode=mode, obj_id=obj_id)
    
            # По умолчанию семафор занят
            is_free = False
            state, mt = m3_mutex.request_mutex(mutex_id)
    
            # Проверяем свободен ли семафор
            if state == m3_mutex.MutexState.FREE:
                is_free = True
            # Если семафорт занят нами в текущем запросе, то тоже все ОК
            elif state == m3_mutex.MutexState.CAPTURED_BY_ME:
                is_free = True
    
            return is_free
			
Добавим метод, который позволит нам создавать семафор для последующей его блокировки::

        def block(self, obj_id, mode, request_id):
            u"""Создание семафора и его блокировка.
            Передаётся id объекта, тип объекта и id запроса.
    
            :param int obj_id: id объекта
            :param basestring mode: тип объекта
            :param int request_id: id запроса
    
            :rtype: basestring or None
            """
            blocker = None
            obj_id = self.get_obj_id(obj_id)
            mutex_id = self.get_mutex_id(mode=mode, obj_id=obj_id)
    
            try:
                # Получаем состояние
                state, mt = m3_mutex.request_mutex(mutex_id)
    
                # Если mutex никем не занят, в том числе нами из другого места
                if state == m3_mutex.MutexState.FREE:
                    # Захватываем mutex
                    m3_mutex.capture_mutex(mutex_id, status_data=request_id)
    
                # Иначе блокируем
                else:
                    # Получаем владельца mutex
                    blocker = mt.owner.name
    
            # Если занят
            except m3_mutex.MutexBusy:
                blocker = u'Блокировщик неизвестен'

            return blocker
			
Добавим метод, который позволит нам обновлять блокировку семафора::
			
    def refresh(self, obj_id, mode, request_id):
        u"""Обновление блокировки семафора, чтобы он не освободился по тайм-ауту.
        Передаётся id объекта, тип объекта и id запроса.

        :param int obj_id: id объекта
        :param basestring mode: тип объекта
        :param int request_id: id запроса

        :rtype: basestring or None
        """
        obj_id = self.get_obj_id(obj_id)
        mutex_id = self.get_mutex_id(mode=mode, obj_id=obj_id)

        # Получаем состояние
        state, mt = m3_mutex.request_mutex(mutex_id)

        # Если заблокирован нами и не из другого запроса
        if (state == m3_mutex.MutexState.CAPTURED_BY_ME
                and mt.status_data == request_id):
            # Обновляем блокировку для повторного захвата
            m3_mutex.capture_mutex(mutex_id, status_data=request_id)
        else:
            return u"Блокировка объекта снята!"

        return None

Добавим метод, который позволит нам освобождать семафор::

    def release(self, obj_id, mode, request_id):
        u"""Освобождение семафора.
        Передаётся id объекта, тип объекта и id запроса.
        """
        obj_id = self.get_obj_id(obj_id)
        mutex_id = m3_mutex.MutexID(mode=mode, id=obj_id)

        state, mt = m3_mutex.request_mutex(mutex_id)

        if state == m3_mutex.MutexState.CAPTURED_BY_ME:
            mt = m3_mutex.capture_mutex(mutex_id)
            try:
                if mt.status_data == request_id:
                    m3_mutex.release_mutex(mutex_id)
            except m3_mutex.MutexBusy:
                pass
        return None
			
После этого, данный семафор можно использовать следующим образом::
		
		# создаем семафор
		mutex = ObjEditMutex()
		# создаем или получаем каким - либо образом объект
		some_obj = SomeObjClass()
		
		# блокируем объект
		blocker = mutex.block(some_obj.id, some_obj.type, some_obj.uuid)
		# если нам удалось заблокировать объект
		if blocker is None:
			# делаем что - то с объектом
			do_something(some_obj)
			# освобождаем объект 
			mutex.release(some_obj.id, some_obj.type, some_obj.uuid)
			print 'Операция с объектом завершена'			
		else:
			# говорим, что объект занят
			print u'Объект занят'
		
    
