[ldap_locks] Mise en place des locks. Cf commentaires pour les détails.
* Malheureusement lc_ldap._create_entity et objet.create sont un peu sales, mais j'ai pas trouvé mieux. * L'historique contient désormais les secondes.
This commit is contained in:
parent
17efae121c
commit
d6efff30de
7 changed files with 123 additions and 58 deletions
|
@ -38,6 +38,8 @@ import os
|
|||
import exceptions
|
||||
import socket
|
||||
import crans_utils
|
||||
import collections
|
||||
import subprocess
|
||||
|
||||
class LdapLockedByYou(exceptions.StandardError):
|
||||
"""
|
||||
|
@ -67,24 +69,37 @@ class LdapLockHolder:
|
|||
"""
|
||||
On crée la connexion, et on crée un dico vide.
|
||||
"""
|
||||
self.locks = {}
|
||||
self.host = socket.gethostbyname()
|
||||
self.locks = collections.defaultdict(dict, {})
|
||||
self.host = socket.gethostname()
|
||||
self.pid = os.getpid()
|
||||
self.conn = conn
|
||||
|
||||
def __del__(self):
|
||||
def purge(self, Id=None):
|
||||
"""
|
||||
On essaye de détruire tous les verrous hébergés par
|
||||
l'objet mourant.
|
||||
l'objet.
|
||||
"""
|
||||
for item, value in self.locks:
|
||||
try:
|
||||
self.removelock(item, value)
|
||||
except:
|
||||
pass
|
||||
del self.conn
|
||||
if Id == None:
|
||||
for key, subdict in self.locks['default'].keys():
|
||||
for item, value in subdict:
|
||||
try:
|
||||
self.removelock(item, value, key)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
for item, value in self.locks[Id].items():
|
||||
try:
|
||||
self.removelock(item, value, Id)
|
||||
except:
|
||||
pass
|
||||
|
||||
def addlock(self, item, value):
|
||||
def __del__(self):
|
||||
"""
|
||||
En cas de destruction du lockholder
|
||||
"""
|
||||
self.purge()
|
||||
|
||||
def addlock(self, item, value, Id='default'):
|
||||
"""
|
||||
Applique un verrou sur "$item=$value,$LOCKS_DN",
|
||||
si le précédent verrou était géré par la session
|
||||
|
@ -97,21 +112,21 @@ class LdapLockHolder:
|
|||
"""
|
||||
|
||||
try:
|
||||
host, pid = self.getlock(item, value)
|
||||
if host == self.host and pid == self.pid():
|
||||
host, pid = self.getlock(item, value, Id)
|
||||
if host == self.host and pid == self.pid:
|
||||
raise LdapLockedByYou("La donnée %r=%r est lockée par vous-même." % (item, value))
|
||||
elif host == self.host:
|
||||
status = crans_utils.process_status(pid)
|
||||
if status:
|
||||
raise LdapLockedByOther("La donnée %r=%r est lockée par quelqu'un d'autre ou un processus." % (item, value))
|
||||
else:
|
||||
self.removelock(item, value)
|
||||
self.removelock(item, value, Id, True)
|
||||
else:
|
||||
raise LdapLockedByOther("La donnée %r=%r est lockée par quelqu'un d'autre ou un processus." % (item, value))
|
||||
except ldap.NO_SUCH_OBJECT:
|
||||
pass
|
||||
except LockFormatError:
|
||||
self.removelock(item, value)
|
||||
self.removelock(item, value, Id)
|
||||
|
||||
dn = "%s=%s,%s" % (item, value, LOCKS_DN)
|
||||
lockid = "%s-%s" % (self.host, self.pid)
|
||||
|
@ -121,38 +136,49 @@ class LdapLockHolder:
|
|||
|
||||
try:
|
||||
self.conn.add_s(dn, modlist)
|
||||
self.locks[item] = value
|
||||
self.locks[Id][item] = value
|
||||
except ldap.ALREADY_EXISTS:
|
||||
status = crans_utils.process_status(pid)
|
||||
if status:
|
||||
raise LdapLockedByOther("La donnée %r=%r est lockée par quelqu'un d'autre ou un processus." % (item, value))
|
||||
else:
|
||||
self.removelock(item, value)
|
||||
self.removelock(item, value, Id)
|
||||
try:
|
||||
self.conn.add_s(dn, modlist)
|
||||
self.locks[item] = value
|
||||
|
||||
# Si on a un pointeur vers l'id de l'objet, on en tient compte
|
||||
self.locks[Id][item] = value
|
||||
except:
|
||||
raise StandardError("Quelque chose a planté durant la pose du lock %s=%s" % (item, value))
|
||||
|
||||
def removelock(self, item, value):
|
||||
def removelock(self, item, value, Id='default', force=False):
|
||||
"""
|
||||
Libère le lock "$item=$value,$LOCKS_DN".
|
||||
"""
|
||||
print "Deleting %s=%s,%s\n" % (item, value, LOCKS_DN)
|
||||
if self.locks.get(item, "") == value:
|
||||
self.locks.pop(item)
|
||||
self.conn.delete_s("%s=%s,%s" % (item, value, LOCKS_DN))
|
||||
if not force:
|
||||
if self.locks[Id].get(item, "") == str(value):
|
||||
_ = self.locks[Id].pop(item)
|
||||
self.conn.delete_s("%s=%s,%s" % (item, value, LOCKS_DN))
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
print "Lock %s=%s,%s does not exist on this session" % (item, value, LOCKS_DN)
|
||||
try:
|
||||
self.conn.delete_s("%s=%s,%s" % (item, value, LOCKS_DN))
|
||||
except:
|
||||
pass
|
||||
|
||||
def getlock(self, item, value):
|
||||
def getlock(self, item, value, Id):
|
||||
"""
|
||||
Trouve le lock item=value, et renvoie le contenu de lockinfo
|
||||
via un couple host, pid
|
||||
"""
|
||||
|
||||
result = self.conn.search_s('%s=%s,%s' % (item, value, LOCKS_DN), 0)
|
||||
if not result:
|
||||
_ = self.locks[Id].pop(item)
|
||||
return None, 0
|
||||
try:
|
||||
return result[0][1]['lockid'][0].split('-')
|
||||
host, pid = result[0][1]['lockid'][0].split('-')
|
||||
return host, int(pid)
|
||||
except:
|
||||
raise LockFormatError
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue