# Path: zoonado/exc.py
# class ZKError(Exception):
# class ConnectError(ZKError):
# class NoServersError(ZKError):
# class SessionLost(ZKError):
# class InvalidClientState(ZKError):
# class TimeoutError(ZKError):
# class FailedRetry(ZKError):
# class ResponseErrorMeta(type):
# class ResponseError(ZKError):
# class UnknownError(ResponseError):
# class RolledBack(ResponseError):
# class ZKSystemError(ResponseError):
# class RuntimeInconsistency(ResponseError):
# class DataInconsistency(ResponseError):
# class ConnectionLoss(ResponseError):
# class MarshallingError(ResponseError):
# class Unimplemented(ResponseError):
# class OperationTimeout(ResponseError):
# class BadArguments(ResponseError):
# class UnknownSession(ResponseError):
# class NewConfigNoQuorum(ResponseError):
# class ReconfigInProcess(ResponseError):
# class APIError(ResponseError):
# class NoNode(ResponseError):
# class NoAuth(ResponseError):
# class BadVersion(ResponseError):
# class NoChildrenForEphemerals(ResponseError):
# class NodeExists(ResponseError):
# class NotEmpty(ResponseError):
# class SessionExpired(ResponseError):
# class InvalidCallback(ResponseError):
# class InvalidACL(ResponseError):
# class AuthFailed(ResponseError):
# class SessionMoved(ResponseError):
# class NotReadOnly(ResponseError):
# class EphemeralOnLocalSession(ResponseError):
# class NoWatcher(ResponseError):
#     def __init__(self, host, port, server_id=None):
#     def __str__(self):
#     def __new__(cls, name, bases, attrs):
#     def __str__(self):
#     def __init__(self, error_code):
#     def __str__(self):
# def get_response_error(error_code):
# 
# Path: zoonado/recipes/base_lock.py
# class BaseLock(SequentialRecipe):
# 
#     @gen.coroutine
#     def wait_in_line(self, znode_label, timeout=None, blocked_by=None):
#         time_limit = None
#         if timeout is not None:
#             time_limit = time.time() + timeout
# 
#         yield self.create_unique_znode(znode_label)
# 
#         while True:
#             if time_limit and time.time() >= time_limit:
#                 raise exc.TimeoutError
# 
#             owned_positions, contenders = yield self.analyze_siblings()
#             if znode_label not in owned_positions:
#                 raise exc.SessionLost
# 
#             blockers = contenders[:owned_positions[znode_label]]
#             if blocked_by:
#                 blockers = [
#                     contender for contender in blockers
#                     if self.determine_znode_label(contender) in blocked_by
#                 ]
# 
#             if not blockers:
#                 break
# 
#             yield self.wait_on_sibling(blockers[-1], time_limit)
# 
#         raise gen.Return(self.make_contextmanager(znode_label))
# 
#     def make_contextmanager(self, znode_label):
#         state = {"acquired": True}
# 
#         def still_acquired():
#             return state["acquired"]
# 
#         @gen.coroutine
#         def handle_session_loss():
#             yield self.client.session.state.wait_for(states.States.LOST)
#             if not state["acquired"]:
#                 return
# 
#             log.warn(
#                 "Session expired at some point, lock %s no longer acquired.",
#                 self
#             )
#             state["acquired"] = False
# 
#         ioloop.IOLoop.current().add_callback(handle_session_loss)
# 
#         @gen.coroutine
#         def on_exit():
#             state["acquired"] = False
#             yield self.delete_unique_znode(znode_label)
# 
#         @contextlib.contextmanager
#         def context_manager():
#             try:
#                 yield still_acquired
#             finally:
#                 ioloop.IOLoop.current().add_callback(on_exit)
# 
#         return context_manager()


from tornado import gen
from zoonado import exc
from .base_lock import BaseLock
from __future__ import unicode_literals





class SharedLock(BaseLock):

    @gen.coroutine
    def acquire_read(self, timeout=None):
        result = None
        while not result:
            try:
                result = yield self.wait_in_line(
                    "read", timeout, blocked_by=("write")
                )
            except exc.SessionLost:
                continue

        raise gen.Return(result)

    @gen.coroutine
    def acquire_write(self, timeout=None):
        result = None
        while not result:
            try:
                result = yield self.wait_in_line("write", timeout)

# Path: zoonado/exc.py
# class ZKError(Exception):
# class ConnectError(ZKError):
# class NoServersError(ZKError):
# class SessionLost(ZKError):
# class InvalidClientState(ZKError):
# class TimeoutError(ZKError):
# class FailedRetry(ZKError):
# class ResponseErrorMeta(type):
# class ResponseError(ZKError):
# class UnknownError(ResponseError):
# class RolledBack(ResponseError):
# class ZKSystemError(ResponseError):
# class RuntimeInconsistency(ResponseError):
# class DataInconsistency(ResponseError):
# class ConnectionLoss(ResponseError):
# class MarshallingError(ResponseError):
# class Unimplemented(ResponseError):
# class OperationTimeout(ResponseError):
# class BadArguments(ResponseError):
# class UnknownSession(ResponseError):
# class NewConfigNoQuorum(ResponseError):
# class ReconfigInProcess(ResponseError):
# class APIError(ResponseError):
# class NoNode(ResponseError):
# class NoAuth(ResponseError):
# class BadVersion(ResponseError):
# class NoChildrenForEphemerals(ResponseError):
# class NodeExists(ResponseError):
# class NotEmpty(ResponseError):
# class SessionExpired(ResponseError):
# class InvalidCallback(ResponseError):
# class InvalidACL(ResponseError):
# class AuthFailed(ResponseError):
# class SessionMoved(ResponseError):
# class NotReadOnly(ResponseError):
# class EphemeralOnLocalSession(ResponseError):
# class NoWatcher(ResponseError):
#     def __init__(self, host, port, server_id=None):
#     def __str__(self):
#     def __new__(cls, name, bases, attrs):
#     def __str__(self):
#     def __init__(self, error_code):
#     def __str__(self):
# def get_response_error(error_code):
# 
# Path: zoonado/recipes/base_lock.py
# class BaseLock(SequentialRecipe):
# 
#     @gen.coroutine
#     def wait_in_line(self, znode_label, timeout=None, blocked_by=None):
#         time_limit = None
#         if timeout is not None:
#             time_limit = time.time() + timeout
# 
#         yield self.create_unique_znode(znode_label)
# 
#         while True:
#             if time_limit and time.time() >= time_limit:
#                 raise exc.TimeoutError
# 
#             owned_positions, contenders = yield self.analyze_siblings()
#             if znode_label not in owned_positions:
#                 raise exc.SessionLost
# 
#             blockers = contenders[:owned_positions[znode_label]]
#             if blocked_by:
#                 blockers = [
#                     contender for contender in blockers
#                     if self.determine_znode_label(contender) in blocked_by
#                 ]
# 
#             if not blockers:
#                 break
# 
#             yield self.wait_on_sibling(blockers[-1], time_limit)
# 
#         raise gen.Return(self.make_contextmanager(znode_label))
# 
#     def make_contextmanager(self, znode_label):
#         state = {"acquired": True}
# 
#         def still_acquired():
#             return state["acquired"]
# 
#         @gen.coroutine
#         def handle_session_loss():
#             yield self.client.session.state.wait_for(states.States.LOST)
#             if not state["acquired"]:
#                 return
# 
#             log.warn(
#                 "Session expired at some point, lock %s no longer acquired.",
#                 self
#             )
#             state["acquired"] = False
# 
#         ioloop.IOLoop.current().add_callback(handle_session_loss)
# 
#         @gen.coroutine
#         def on_exit():
#             state["acquired"] = False
#             yield self.delete_unique_znode(znode_label)
# 
#         @contextlib.contextmanager
#         def context_manager():
#             try:
#                 yield still_acquired
#             finally:
#                 ioloop.IOLoop.current().add_callback(on_exit)
# 
#         return context_manager()


# Path: zoonado/recipes/shared_lock.py
from tornado import gen
from zoonado import exc
from .base_lock import BaseLock

from __future__ import unicode_literals





class SharedLock(BaseLock):

    @gen.coroutine
    def acquire_read(self, timeout=None):
        result = None
        while not result:
            try:
                result = yield self.wait_in_line(
                    "read", timeout, blocked_by=("write")
                )
            except exc.SessionLost:
                continue

        raise gen.Return(result)

    @gen.coroutine
    def acquire_write(self, timeout=None):
        result = None
        while not result:
            try:
                result = yield self.wait_in_line("write", timeout)

            except exc.SessionLost: