2016-09-28 5 views
0

Während Fragment X Code ausgeführt wird, sollte Fragment Y nicht ausgeführt werden und wenn Y ausgeführt wird X sollte nicht ausgeführt werden. Stattdessen sollten X und Y angehalten werden, wenn ein anderer gerade ausgeführt wird.Beschränken gleichzeitiger Prozesse mit beratenden Dateisperren

jedoch eine beliebige Anzahl von Prozessen oder Threads erlaubt gleichzeitig Code X.

Was mehr als eine Y Ausführung parallel ausführen? Es sollte auch angehalten werden, bis eine andere Instanz von Y ausgeführt wird oder mit dem Fehler "Mehr als ein Y kann nicht parallel ausgeführt werden" endet.

Kann dies mit Unix Advisory File Locks implementiert werden? Ich denke, ich sollte die Nummer des aktuell ausgeführten X in die Datei schreiben (ähnlich der Referenzzählung). Oder vielleicht brauche ich zwei Dateien: eine für die Speicherung der Anzahl gleichzeitiger Prozesse, die X ausführen, und die andere für die Sperrung der ersten? Versuchen wir nun, den Algorithmus zu konstruieren.

Beachten Sie, dass ich in Python schreibe.

+0

Beachten Sie, dass X in meinem echtes Problem ist ein Code, der eine DB modifiziert, und Y ist die DB-Wiederherstellungsprozedur, die benötigt wird, wenn die Daten irgendwie inkonsistent sind – porton

+0

Wenn es eine Y-Anfrage gibt Sind X-Anfragen erlaubt fortzufahren, oder werden sie gehalten, bis das Y verarbeitet wird? Gibt es noch andere Probleme beim Teilen/Verhungern (zu viele Y-Anfragen, die X-Anfragen verhindern)? Dies ist alles ziemlich Standard "Leser und Schriftsteller" gegenseitigen Ausschluss oder Sperrzeug - grundlegende Concurrency-Theorie. Es kann mit Advisory-Locking erfolgen, solange die Prozesse kooperieren. –

+0

@ JonathanLeffler Was meinst du mit "ausstehend"? Wenn Y ausgeführt wird, müssen alle X warten. Brauche ich ein oder zwei Beratungsschlösser? – porton

Antwort

0

Dies kann mit einer Sperre gelöst werden, da es zwei Arten von Dateisperren gibt: exklusiv und gemeinsam. Y erhält eine exklusive Sperre und X eine gemeinsame Sperre. Hier

ist der eigentliche Code:

class SequentialTask: 
    def __init__(self, lock_file): 
     self.lock_file = lock_file 

    def sequential(self, lock_mode): 
     def sequential_decorator(func): 
      #@wraps(func) # TODO: doesn't work 
      def func_wrapper(*args, **kwargs): 
       with open(self.lock_file, 'w') as file: 
        logger = logging.getLogger(__name__) 
        logger.debug("Locking a sequential request...") 
        flock(file, lock_mode) 
        try: 
         return func(*args, **kwargs) 
        finally: 
         logger.debug("Unlocking a sequential request...") 
         # unlink(self.lock_file) # Don't do: http://stackoverflow.com/q/17708885/856090 
         flock(file, LOCK_UN) 
         # unlink(self.lock_file) # Don't do: open but unlocked file may be deleted. 
      return func_wrapper 
     return sequential_decorator 

Dann

task = SequentialTask(VAR_DIR+"/groups-modify.lock") 

und fügen Sie einfach @task.sequential(LOCK_SH) auf die Funktion X und @task.sequential(LOCK_EX) auf die Funktion der Umsetzung Y. Umsetzung

Verwandte Themen