173 lines
5.3 KiB
Python
Executable file
173 lines
5.3 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# -*- coding: iso-8859-15 -*-
|
|
|
|
""" Gestion de lock
|
|
|
|
Copyright (C) Frédéric Pauget
|
|
Licence : GPLv2
|
|
"""
|
|
|
|
import os,string,time,sys, affich_tools
|
|
from commands import getoutput
|
|
from user_tests import getuser
|
|
from fcntl import lockf, LOCK_EX, LOCK_NB, LOCK_UN
|
|
import errno
|
|
|
|
def wait_lock(lock_name, lock_comment='', d=None):
|
|
"""Attend la disponibilité d'un lock en utilisant le framework Twisted.
|
|
|
|
Si d est de type Deferred, on est en mode asynchrone.
|
|
"""
|
|
from twisted.internet import reactor, defer
|
|
try:
|
|
try:
|
|
make_lock(lock_name, lock_comment, nowait=1, quiet=True)
|
|
except:
|
|
print "*** Probleme lors de l'obtention du lock..."
|
|
import traceback
|
|
traceback.print_exc()
|
|
# On a sans doute pas le lock et c'est pas moi qui me tape
|
|
# à debugguer les trucs à Fred.
|
|
raise AssertionError
|
|
|
|
# On a le lock
|
|
if not d:
|
|
# On est en mode synchrone
|
|
return defer.succeed(None)
|
|
# On appelle le callback car on est en mode asynchrone
|
|
print "We got the lock, in asynchronous mode"
|
|
d.callback(None)
|
|
except AssertionError:
|
|
# On a pas le lock
|
|
if not d:
|
|
# On est en mode synchrone, on va passer en asynchrone
|
|
d = defer.Deferred()
|
|
# On essaie de nouveau dans 200 ms.
|
|
reactor.callLater(0.2, wait_lock, lock_name, lock_comment, d)
|
|
return d
|
|
|
|
def make_lock(lock_name, lock_comment='',nowait=0, quiet=False) :
|
|
""" Création d'un lock
|
|
si nowait=1 fait un sys.exit(254) quand un ancien lock actif est rencontré
|
|
"""
|
|
lock_dir = '/var/lock/gestion'
|
|
try:
|
|
os.mkdir(lock_dir)
|
|
except OSError:
|
|
pass
|
|
lock_file = "%s/%s" % (lock_dir, lock_name)
|
|
|
|
# On créé une zone d'exclusion
|
|
lock_fd_dl=open("%s-dotlock" % lock_file, "w")
|
|
# On demande un verrou exclusif
|
|
try:
|
|
lockf(lock_fd_dl, LOCK_EX | LOCK_NB)
|
|
except IOError, e:
|
|
if e.errno not in [errno.EACCES, errno.EAGAIN]:
|
|
raise
|
|
if nowait:
|
|
if quiet:
|
|
# On va plutot lever une exception
|
|
raise AssertionError('In critical section')
|
|
else:
|
|
sys.stderr.write('\tpropriétaire : inconnu\n\tpid : inconnu\n\tdémarré depuis inconnu\n')
|
|
sys.exit(254)
|
|
else:
|
|
# La procédure de lock est deja en cours d'execution, on essaie un peu plus tard
|
|
time.sleep(0.5)
|
|
return make_lock(lock_name, lock_comment)
|
|
|
|
if os.path.isfile(lock_file) :
|
|
### Lock existant
|
|
|
|
# Lecture du lock
|
|
fd = open(lock_file, "r")
|
|
pid= fd.readline().strip()
|
|
user = fd.readline().strip()
|
|
fd.close()
|
|
|
|
# Informations sur le processus lockant
|
|
if os.system( "ps ax | grep -q '^%s '" % pid ) :
|
|
# Le script lockant ne tourne plus
|
|
os.remove(lock_file)
|
|
elif nowait :
|
|
if not quiet:
|
|
sys.stderr.write('Lock : %s\n' % lock_file)
|
|
l=getoutput("ps -ax -o pid,etime | awk '($1 == %s)'" % pid)
|
|
data = [ user , pid , l.strip() ]
|
|
|
|
# Formatate de etime
|
|
s = data[-1].split('-')
|
|
if len(s)==2 :
|
|
txt = '%s jour(s) ' % s[0]
|
|
s=s[1]
|
|
else :
|
|
txt = ''
|
|
s=s[0]
|
|
|
|
s = s.split(':')
|
|
if len(s) == 3 :
|
|
txt = '%sh%smin%ss' % tuple(s)
|
|
elif len(s) == 2 :
|
|
txt = '%smin%ss' % tuple(s)
|
|
else :
|
|
txt = '???'
|
|
|
|
data[-1]=txt
|
|
|
|
if not quiet:
|
|
sys.stderr.write('\tpropriétaire : %s\n\tpid : %s\n\tdémarré depuis %s\n' % tuple(data) )
|
|
sys.exit(254)
|
|
else:
|
|
# On va plutot lever une exception
|
|
raise AssertionError(tuple(data))
|
|
else :
|
|
# Il faut attendre
|
|
a = affich_tools.anim('\tattente du lock')
|
|
for i in range(8) :
|
|
time.sleep(1)
|
|
a.cycle()
|
|
sys.stdout.write('\r')
|
|
return make_lock(lock_name, lock_comment)
|
|
|
|
### Prise du lock
|
|
lock_fd = file(lock_file,"w")
|
|
try:
|
|
utilisateur = getuser()
|
|
except:
|
|
utilisateur = "inconnu"
|
|
lock_fd.write("%s\n%s\n%s" % (os.getpid(), utilisateur, lock_comment) )
|
|
lock_fd.close()
|
|
|
|
# On enleve le verrou système
|
|
lockf(lock_fd_dl, LOCK_UN)
|
|
lock_fd_dl.close()
|
|
|
|
|
|
def remove_lock( lock_name ) :
|
|
""" Destruction du lock """
|
|
# On créé une zone d'exclusion
|
|
lock_dir = '/var/lock/gestion'
|
|
lock_file = "%s/%s" % (lock_dir, lock_name)
|
|
|
|
lock_fd_dl=open("%s-dotlock" % lock_file, "w")
|
|
# On demande un verrou exclusif
|
|
try:
|
|
lockf(lock_fd_dl, LOCK_EX | LOCK_NB)
|
|
except IOError, e:
|
|
if e.errno not in [errno.EACCES, errno.EAGAIN]:
|
|
raise
|
|
# Déjà locké
|
|
time.sleep(0.5)
|
|
return remove_lock(lock_name)
|
|
try :
|
|
fd = open(lock_file, "r")
|
|
if fd.readline().strip()=="%s" % os.getpid():
|
|
os.remove(lock_file)
|
|
fd.close()
|
|
except :
|
|
pass
|
|
|
|
# On enleve le verrou système
|
|
lockf(lock_fd_dl, LOCK_UN)
|
|
lock_fd_dl.close()
|