Queue Logikproblem

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
jasonts
User
Beiträge: 5
Registriert: Freitag 25. Februar 2011, 05:18

Hallo, ich schreibe gerade an einem Python Tool und kann ein bestimmtes Problem nicht lösen. Ich würde mich über Tipps freuen.

Das Tool soll einzelne Dateien an verschiedene FTP Server ausliefern. Dabei weiß das Tool aber nicht, wann es neue Dateien erhält oder wie viele noch kommen. Das Tool läuft einfach als Deamon und reagiert auf einen Eingangsordner. Um aber zu verhindern, dass beim gleichen Server die Verbindung für jede Datei aufgebaut und getrennt wird, sollte das Tool testen, ob noch weitere Dateien für den gleichen Server in der Warteschlange sind.

Bis Hier ist das auch noch einfach mit einer Liste als Queue machbar. Das Problem ist aber, dass mehrere Dateien parallel ausgeliefert werden. Außerdem möchte ich nicht, dass 2 Threads an den gleichen Server liefern. Es gibt aber auch mehr Server als mögliche Threads/Verbindungen, weswegen nicht jeder Server einen eigenen Thread haben kann. Ein Prioritätssystem für die Server muss auch einbaubar sein.

Beispiel:
Die Dateien 1 bis 40 liegen im Ordner und sollen an die Server a, c, d, e, f, g, h verteilt werden. Dabei sollen nur 5 Verbindungen aufgebaut werden. Datei 1 wird nun also an a,b,c,d,e gleichzeitig ausgeliefert. Ist der Thread für Server a fertig, soll er prüfen, ob noch weitere Dateien an den gleichen Server gesendet werden sollen. Falls ja, soll die Verbindung nicht abgebrochen werden, sondern die nächste Datei folgen. Erst wenn einer der ersten 5 Servern eine leere Warteschlange hat, sollen f,g,h nachrücken. Wird jedoch an b,c,d,e,f übertragen und für a landet eine neue Datei in der Warteschlange, soll der Thread für f nach der aktuellen Datei die Verbindung kappen und sich wieder um a kümmern (höhere Priorität).

Es ist leider schwer eine konkrete Frage zu formulieren. Ich suche keinen fertigen Code. Allerdings wäre ein Hinweis auf die Lösung des Problems (als Ablauf oder Pseudocode) sehr hilfreich. Hier meine Überlegungen:

Nach meiner Vermutung müsste die Lösung etwa so aussehen:
Der Hauptprozess erzeugt 5 Threads und eine Warteschlange je Server. Die Threads prüfen dann die Warteschlangen auf Inhalt. Findet ein Thread eine gefüllte Warteschlange, arbeitet er diese ab. Allerdings muss er sie komplett "blockieren", damit die anderen Threads nicht an den selben Server liefern. Nach jeder Datei läuft der Thread die Warteschlangen neu ab (prüft ob blockiert bzw. leer) und wechselt ggf. zu einer mit größerer Priorität. Findet der Thread keine wichtigere, freie Queue, macht er einfach weiter.

Leider weiß ich nicht, wie ich das Blockieren realisieren kann. Ich will schließlich nicht nur einen Eintrag blocken, sondern eine ganze Queue.

Ich bedanke mich schon einmal bei allen, die sich daran versuchen.



Und als das nicht schon schlimm genug wäre, eine Frage am Rand:
In den Docs heißt es, eine Queue kann mit einem "item" gefüllt werden. Was genau ist als item gültig ? Testen zeigt, dass fast alles geht, aber eine genaue Definition wäre schon schön. Dictionaries scheinen z.B. nicht zu gehen.

Lg Micha
Rekrul
User
Beiträge: 78
Registriert: Dienstag 7. Dezember 2010, 16:23

Ich würde nur einen Thread machen, der nur damit beschäftigt ist die Warteschlangen zu überprüfen. Dieser Thread soll dann Threads erzeugen, die sich jeweils nur um eine Warteschlange kümmern, sofern sie nicht leer ist. Ein so erzeugter Thread terminiert wenn die ihm zugewiesene Warteschlange leer ist oder der Hauptthread ihn aufgrund der Prioritäten beendet.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Immerhin hast Du den Weg von uu.de ins richtige Forum gefunden ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@jasonts: Warum soll ein Thread eine Queue komplett abarbeiten wenn er doch sowieso nach jeder Datei unterbrochen werden kann wenn es Dateien mit höherer Priorität gibt?

Von welcher Queue redest Du, in die man keine Dictionaries stecken kann? In `Queue.Queue` und `Queue.PriorityQueue` kann man das zumindest. In erstere sollte man alles stecken können, bei der zweiten muss eine totale Ordnung auf den Elementen definiert sein, d.h. die müssen sinnvoll auf kleiner/grösser vergleichbar sein.

Bei `uu.de` wurde ja schon das `multiprocessing`-Modul empfohlen.
jasonts
User
Beiträge: 5
Registriert: Freitag 25. Februar 2011, 05:18

Danke für die ersten Vorschläge!

@Rekrul: So hatte ich mir das auch überlegt, aber das würde bedeuten, dass wenn server b,c,d,e,f beliefert werden, sich keiner mehr um a kümmert, bis die warteschlangen leer sind. im schlechtesten fall würden also nur die unwichtigsten server beliefert werden.

@Blackjack: damit die server so gut wie möglich zusammen gefasst werden. im worst case werden zb nur die gleichen server beliefert (zb bei unendlich vielen dateien). wenn ich die warteschlange so schreibe, dass nach jeder übertragung schluss ist, hätte ich jedes mal "verbinden"->"chdir"->"upload"->"verbindung trennen". ich möchte einfach von vorn herein ausschließen, dass da der eine oder andere server probleme mit hat. auch könnte das bei einer schlechten verbindung zu stärkerenen wartezeiten führen. daher soll der thread zwar gucken, ob es etwas wichtigeres gibt, aber nur in diesem fall die verbindung trennen oder ggf. einfach weiter machen.

@blackjack: ja dann war mein dict nicht sortierbar, danke für den hinweis.
Rekrul
User
Beiträge: 78
Registriert: Dienstag 7. Dezember 2010, 16:23

aber das würde bedeuten, dass wenn server b,c,d,e,f beliefert werden, sich keiner mehr um a kümmert, bis die warteschlangen leer sind. im schlechtesten fall würden also nur die unwichtigsten server beliefert werden.
Der Hauptthread soll ja auch Threads beenden können. Beispiel: 5 Threads (also die maximal mögliche Anzahl von Threads) arbeiten jeweils eine Warteschlange (b,c,d,e,f) ab. Warteschlange a wird befüllt. Der Hauptthread stellt dies fest und möchte einen neuen Thread starten, der diese Warteschlange abarbeitet. Hierfür muss zuerst aber zuerst der Thread mit der niedrigsten Priorität terminiert werden. Der Thread, der sich gerade um Warteschlange f kümmert muss also terminiert werden, dass ein neuer sich um Warteschlange a kümmern kann.
Antworten