diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/py/imc/lockclient.py | 111 | ||||
-rw-r--r-- | src/py/imc/lockserver.py | 67 |
2 files changed, 178 insertions, 0 deletions
diff --git a/src/py/imc/lockclient.py b/src/py/imc/lockclient.py new file mode 100644 index 0000000..7a35538 --- /dev/null +++ b/src/py/imc/lockclient.py @@ -0,0 +1,111 @@ +from imc import async +from imc.auth import Auth + +class LockClient: + def __init__(self,proxy,idendesc,serverlink): + self.RWLOCK_READ = 1 + self.RWLOCK_WRITE = 2 + + self._proxy = proxy + self._idendesc = idendesc + self._callpath = serverlink + 'lockserver/' + + self.rwlock_namemap = {} + + self._proxy.register_call('lockclient/','sync_write_lock', + self.sync_write_lock) + self._proxy.register_call('lockclient/','sync_write_unlock', + self.sync_write_unlock) + + with Auth.change_current_iden(self._idendesc): + self._proxy.instance.call(self._callpath,'connect_client',10000) + + LockClient.instance = self + + def read_lock(self,lockname): + while True: + if lockname not in self.rwlock_namemap: + self.rwlock_namemap[lockname] = { + 'state':self.RWLOCK_READ, + 'count':1, + 'waitlist':[] + } + + break + + else: + lock = rwlock_namemap[lockname] + if lock['state'] == self.RWLOCK_READ: + lock['count'] += 1 + break + + else: + retid = async.get_retid() + lock['waitlist'].append(retid) + async.switch_top() + + def read_unlock(self,lockname): + try: + lock = self.rwlock_namemap[lockname] + + except KeyError: + return + + if lock['state'] != self.RWLOCK_READ: + return + + lock['count'] -= 1 + if lock['count'] <= 0: + waitlist = lock['waitlist'] + for retid in waitlist: + asycn.ret(retid) + + del self.rwlock_namemap[lockname] + + def write_lock(self,lockname): + with Auth.change_current_iden(self._idendesc): + self._proxy.instance.call(self._callpath,'write_lock',3600000, + lockname) + + def write_unlock(self,lockname): + with Auth.change_current_iden(self._idendesc): + self._proxy.instance.call(self._callpath,'write_unlock',10000, + lockname) + + @async.caller + def sync_write_lock(self,lockname): + while True: + if lockname not in self.rwlock_namemap: + self.rwlock_namemap[lockname] = { + 'state':self.RWLOCK_WRITE, + 'count':1, + 'waitlist':[] + } + + break + + else: + lock = self.rwlock_namemap[lockname] + retid = async.get_retid() + lock['waitlist'].append(retid) + + return 'Success' + + @async.caller + def sync_write_unlock(self,lockname): + try: + lock = self.rwlock_namemap[lockname] + + except KeyError: + return 'Enoexist' + + if lock['state'] != self.RWLOCK_WRITE: + return 'Enoexist' + + waitlist = lock['waitlist'] + for retid in waitlist: + asycn.ret(retid) + + del self.rwlock_namemap[lockname] + + return 'Success' diff --git a/src/py/imc/lockserver.py b/src/py/imc/lockserver.py new file mode 100644 index 0000000..f4f0498 --- /dev/null +++ b/src/py/imc/lockserver.py @@ -0,0 +1,67 @@ +from imc import async +from imc.auth import Auth + +class LockServer: + def __init__(self,proxy,idendesc): + self._proxy = proxy + self._idendesc = idendesc + self.client_linkmap = set() + + self._proxy.register_call('lockserver/','connect_client', + self.connect_client) + self._proxy.register_call('lockserver/','write_lock', + self.write_lock) + self._proxy.register_call('lockserver/','write_unlock', + self.write_unlock) + + LockServer.instance = self + + @async.caller + def connect_client(self): + link = Auth.get_current_iden()['link'] + self.client_linkmap.add(link) + + @async.caller + def write_lock(self,lockname): + def _send(link): + def __cb(result): + nonlocal count + + stat,ret = result + if stat == False and ret == 'Enoexist': + self.client_linkmap.pop(link,None) + + count -= 1 + if count == 0: + async.ret(retid) + + self._proxy.call_async(link + 'lockclient/', + 'sync_write_lock', + 3600000, + __cb, + lockname) + + with Auth.change_current_iden(self._idendesc): + links = list(self.client_linkmap) + count = len(links) + retid = async.get_retid() + for link in links: + _send(link) + + async.switch_top() + + @async.caller + def write_unlock(self,lockname): + def _cb(result): + stat,ret = result + if stat == False and ret == 'Enoexist': + self.client_linkmap.pop(link,None) + + with Auth.change_current_iden(self._idendesc): + links = list(self.client_linkmap) + for link in links: + self._proxy.call_async(link + 'lockclient/', + 'sync_write_unlock', + 10000, + _cb, + lockname) |