Datei bei Zugriff sperren (File-Lock)

Alles rund um die Programmierung mit Qt
Antworten
michams
Beiträge: 56
Registriert: 14. November 2005 18:24

Datei bei Zugriff sperren (File-Lock)

Beitrag von michams »

Hi,

Ich schreibe gerade ein Programm, bei dem einige Dateien von verschiedenen Nutzern (auf Netzlaufwerken) bearbeitet werden können. Es muß also eine Möglichkeit her, allen anderen zu signalisieren, daß eine Datei gerade in Benutzung ist. Eigentlich super geeignet wäre das QtLockedFile Addon, nur leider wird die Datei nicht als QFile gelesen und geschrieben sondern über tinyxml.
Also bin ich erstmal den einfacheren Weg gegangen und erzeuge ein Lock-File, indem ich erstmal mit einem QFile.exists() nachschaue, ob es das schon gibt, falls ja, dann gesperrt, falls nein, wird es gesperrt. Das ist kein Problem. Die Lock-Datei wird gelöscht, wenn das Programm mit bearbeiten fertig ist, oder im Destruktor.
Nun das Problem: Wenn die Applikation unvorhergesehen beendet wird (die diplomatische Umschreibung für Absturz), dann passiert das Löschen nicht, weil ja auch der Destruktor nicht aufgerufen wird. Die Datei bleibt folglich für alle gesperrt und müßte händisch gelöscht werden. Gibt es eine Möglichkeit, das abzufangen?
Oder Alternativ, andere Lösungen (brauchen notfalls auf nur unter Windows funktionieren)?
arj
Beiträge: 45
Registriert: 1. Juni 2009 13:51
Wohnort: Ihringen

Beitrag von arj »

Eine Möglichkeit wäre, dass Du im Lock-File nen "Totmannschalter" anlegst.

Beispiel: deine Software schreibt nen Timestamp (vorsicht Zeitzonen, deshalb am besten gleich immer UTC nehmen) alle 10 Sekunden (oder auch mehr, je nach Anwendung) in die Datei. Wenn eine andere Instanz die Datei sperren will, dann liest sie das Lockfile ein falls vorhanden und schaut ob deutlich mehr als die 10 Sekunden vergangen sind. Wenn ja, dann wird das Lockfile neu angelegt.

Eine Instanznummer zusätzlich zur Zeitzone wäre wahrscheinlich notwendig, da Du ja unterscheiden musst, ob Du selbst das File angelegt hast, oder jemand anders. Alternativ, kann man das auch anhand des Status der Anwendung erkennen.
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

Du kannst dem Dateinamen des Lock-Files auch die Prozess-ID hinzufügen.
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag von AuE »

Oder die MAC Adresse mit reinschreiben/angeben das sollte es eindeutig machen!
michams
Beiträge: 56
Registriert: 14. November 2005 18:24

Beitrag von michams »

(auch wenn es etwas gedauert hat) danke für die Anregungen, ich denke da läßt sich was passendes draus machen
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Die Vorschlaege halt ich eher fuer suboptimal ...

Normal erledigt das Filesystem(ind deinem fall smb oder nfs über das normale FS) das locken fuer dich .... das heisst es führt selber schon mal buch drueber, welche dateien grad "beschrieben" werden und welche ned, (je nach filesystem führen die dinger nen komplexen header, wo auch mehr oder wenig komplexe locking infos drinne stehen) genau so wie die zum system gehoerende fileoperation dann entsprechende Fehlermeldungen generiert.

Du kannst TiXmlDocument selber ueberladen ... bzw dessen methode "Parse" benutzen, um statt nen file nen speicherblock zu parsen !

Warum benutzt du nich QXML ?

windows(winapi) kann das gut mit smb, sowie posix-systeme sicher auch gut mit nfs können.
bei mischverbau(z.b. linux importiert ein smb share oder Windows importiert ein samba share) weiss ich halt ned wie gut das funktioniert.

Fakt ist, das du beim anlegen der datei eigentlich schon viel granularer die sharing verhaeltnisse einstellen kannst.

Beispiel winapi / vollstaendiger Lock:
oeffnest du eine datei mit CreateFile und setzt bei dwShareMode keine berechtigung, wird nie jemals ein anderer prozess diese Datei auch nur zum lesen oeffnen koennen, auch nicht ueber eine windows freigabe. erst wenn du wieder nen CloseHandle auf das filehandle ausführst wird der lock zurueckgesetzt.
Falls sich noch wer an 16 bit windows und dos erinnern kann, damit man dateien parallel sharen konnte, musste man diesen share treiber laden, sonst hat jeder zugriff die datei immer komplett gesperrt.

Leider bietet einen QFile ned direkt zugriff auf detailierte funktionen ... wenn unbedingt bei QFile Bleiben willst, dann musst mit solchen "kniffen" wo oben beschrieben arbeiten. Laesst dich auf dein BS ein, brauchst das wahrscheinlich ned ....

Du kannst QIODevie auch selber ueberladen mit deiner eigenen fileversion ... bleibt zwar immernoch BS abhaengig dann, aber du koenntest dann immer noch das ding wie ein QFile behandeln, und eben trotzdem deine eigenen spezialitaeten einbauen ....
Wenn die Applikation unvorhergesehen beendet wird (die diplomatische Umschreibung für Absturz), dann passiert das Löschen nicht
Bei der FS version bleibt die Datei auch ne ganze weile gelockt bis windows mitkriegt das der prozess sich abgeschossen hat.
Du kannst aber mit dem prozess, der entsprechende Rechte auf das file hat ... das oeffnen und damit ignorieren des Locks erzwingen.
Damit kannst dir das file falls dein server agbeknallt ist, das ding wieder krallen und bereinigen. Nur erzeugen danach, falls es im shared und ned im vollgelockten modus lief, alle lese und schreibezugriffe der CLients aus anderen prozessen recht haessliche Fehlermeldungen :-)

Noch was, Prozesse über files miteinander kommunizieren zu lassen, iss fast immer nur ne Kruecke !
Fuer IPC und Netzwerkkommunikation gibt es spezialsiertere methoden.
Kannst du nicht einen server bauen der die Datei verwaltet, und allen deinen clients die infos über TCP/IP zur verfuegung stellt ?
Besonders wenn die info in der datei ein xml iss ... stell ich mir das extrem haesslich vor wenn jeder client da selber draufrumparst .....

Ciao ...
michams
Beiträge: 56
Registriert: 14. November 2005 18:24

Beitrag von michams »

Naja, prinzipiell schon, aber das geht alles in eine viel zu komplizierte Richtung. Das Problem ist lediglich, daß eine Applikation gleichzeitig von mehreren Nutzern verwendet wird, ohne daß dies jemals vorgesehen war (erbärmlicherweise aber recht gut funktioniert). Dabei werden xml Dateien eingelesen, dann brav geschlossen, der Inhalt in der Applikation bearbeitet und am Ende die Änderungen zurückgeschrieben. Daß auf die Datei während des Lesens/Schreibens kein Zugriff auf FS Ebene besteht, ist schon klar, aber das Übel in dieser Konstruktion liegt darin, daß beliebig viele Nutzer eine Datei öffnen und auch wieder schreiben könnte, der zeitlich gesehen letzte Schreiber aber der Gewinner ist und alle anderen zwischenzeitlichen Änderungen verlorengehen.
Ich will nun aber auch gar kein großartiges Multiuserhandling einbauen (weil SO viele parallele Änderungen sind nicht zu erwarten), sondern lediglich den Zugriff auf eine Datei während des Bearbeitens exklusiv reservieren und eben den Fall abfangen, daß diese Reservierung versehentlich bestehen bleibt, obwohl die Bearbeitung abgeschlossen oder abgebrochen wurde.
RavenIV
Beiträge: 267
Registriert: 21. Januar 2009 14:24
Wohnort: Waldshut

Beitrag von RavenIV »

Ohne dass es nach Klugscheissen klingt:

Es gibt einen einfacher Weg.
Ändere die Applikation so um, dass die xml-Datei geöffnet bleibt, solange die Applikation läuft.
Dann macht das Betriebssystem das Locking und Du musst Dich um nichts mehr kümmern.
Je nachdem, wie Du die Datei öffnest, können evtl. andere User noch lesend zugreifen, aber nix mehr schreiben.

Damit wäre dann auch die Absturz-Problematik behoben.
Linux, das längste Text-Adventure aller Zeiten
michams
Beiträge: 56
Registriert: 14. November 2005 18:24

Beitrag von michams »

Das ist der Notfallplan B
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

aber das Übel in dieser Konstruktion liegt darin, daß beliebig viele Nutzer eine Datei öffnen und auch wieder schreiben könnte, der zeitlich gesehen letzte Schreiber aber der Gewinner ist und alle anderen zwischenzeitlichen Änderungen verlorengehen.
Und damit finden die User sich ab ?
Solche user mag ich auch haben ^^ bei mir staenden täglich zig bugzilla punkte drin und mein Tel. gaebe nie Ruhe, solange bis ich das umgebaut haette.

Wie gesagt mein vorschlag waere auch, die datei solange geoffnet geoeffnet zu halten wie sie gelockt werden soll. weiterhin wuerd ich versuchen unter deinen xml parser zu kommen und das oeffnen der dateien selber zu uebernehmen (mit createfile), dann kannst aggressiver locken.

die idee mit dem lockfile bringt dir auf lange sicht nur mehr komplexitaet und mehr konstellation die du abhandeln musst -> fehleranfaelliger !

Ciao ...
michams
Beiträge: 56
Registriert: 14. November 2005 18:24

Beitrag von michams »

8) Hähä! Es geht um ein Programm, das nebenher als Hilfsmittel für einen existierenden Prozeß erstellt wurde. Es gibt bei uns einen Leitrechner, der mit einer Gruppe von Prüfständen über ein Netzwerk verbunden ist und mit den normalen Arbeitsplatzrechner über ein zweites Netzwerk. Das Programm dient dazu, bestimmte Statusinformationen auszulesen, was aufgrund der Netzwerktopologie nur vom Leitrechner funktioniert (zumindest ohne größere Frickelei). Gleichzeitig beherrbergt dieses Programm aber auch eine Liste der auf den Prüfständen laufenden Maschinen (was sich recht häufig ändert). Und dann haben einige halt bemerkt, daß sie diese Liste auch von ihrem Arbeitsplatz bearbeiten können. Deswegen scheint es mir jetzt die einfachste Idee, dem Nutzer zu sagen "Pfoten wech! Das bearbeitet gerade jemand anders.". Alles andere ist imho zu aufwendig und für dieses Szenario überdimensioniert, denn SO häufig ändern sich die Daten auch wieder nicht.
Nebenbei: Ich bin offiziell nicht dafür zuständig, irgendwelche Tools zu programmieren, ich mache das nur nebenbei, weil ich es kann und weil sonst immer jemand (u.a. ich!) zu bestimmten Zeiten losziehen müßte, um mit Zettel und Stift den Status der Prüfstände zu notieren und diese dann wieder in ein Excel Dokument einzuhacken.
Antworten