aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/py/imc/lockclient.py111
-rw-r--r--src/py/imc/lockserver.py67
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)