flock - gleichteitiger Dateizugriff
Joachim
- php
Hi,
ich beschaeftige mich grade damit, daten in Textsourcen zu schreiben. Um den gleichzeitigen Zugriff zu verhindern habe ich zunaechst an flock gedacht. Aber auch da kann es Probleme geben, weil bei gleichzeitigem Zugriff wohl das prebuffering nicht die aktuelle Aenderung einer Datei enthaelt, nachdem flock die Datei freigibt.
Ich konnte auch nicht klar entnehmen, ob es mit einer Sperrdatei klappt. Jetzt habe ich gedacht, man koennte doch einfach die Aenderung zunaechst in eine temporaere Datei schreiben, und immer deren Vorhandensein überpruefen, bevor geschrieben werden darf:
while (zaehler < maximum) {
if (temoräres file nicht vorhanden) {
if ($temp = fopen(...)) {
fwrite ($temp, $text);
fclose ($temp);
rename (temp file, file);
return true;
}
}
Zähler hochzaehlen;
}
Hat jemand mit sowas - oder anderen Mechanismen - schon mal gearbeitet, und Erfahrungen gemacht?
Gruesse, Joachim
Hello,
Aber auch da kann es Probleme geben, weil bei gleichzeitigem Zugriff wohl das prebuffering nicht die aktuelle Aenderung einer Datei enthaelt, nachdem flock die Datei freigibt.
Hast Du eine Quelle für das "Prebuffering"?
Meine Meinung nach wird nichts gepuffert, solange Du keine Leseanforderung ausgeführt hast.
Der Weg muss also sein:
Filehandle besorgen
Dateisperre beantragen (Exclusiv)
lesen
verarbeiten
Zeiger zurücksetzen
weg schreiben
ggf. Dateilänge anpassen
Handle zurückgeben und damit Sperre wieder aufheben.
Wesentlich dabei ist, dass JEDER Lesevorgang, der eine Veränderung zur Folge haben soll, innerhalb desselben EXCLUSIVEN Locks wie der anschließenede Schreibvorgang stattfinden muss.
Daher baut man in Dialogsystemen häufig noch eine Abstraktionsschicht ein, die dann mittels "academic locking" für konfliktfreie Datenhalteung sorgt.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi,
Hast Du eine Quelle für das "Prebuffering"?
in diesem Posting auf http://www.php.net/manual/de/function.flock.php wird darauf hingewiesen:
pentek_imre at mailbox dot hu
31-Oct-2004 06:51
Gruesse, Joachim
Hello,
Hast Du eine Quelle für das "Prebuffering"?
in diesem Posting auf http://www.php.net/manual/de/function.flock.php wird darauf hingewiesen:
pentek_imre at mailbox dot hu
31-Oct-2004 06:51
Ach so. Da lass Dir mal keine grauen Haare wachsen.
Der Fehler steckt im Detail. Der Kollege hat sich selbst ein Bein gestellt.
Außerdem enthält die deutsche Bewschreinung von flock() immer noch gravierende Fehler.
LOCK_NB lässt keine anderen Zugriffe während des Lockings zu, sondern steuert den Wartemodus bis zum Lock. Ist es nicht gesetzt, wird die (interne) Schleife aus Lockversuchen sooft wiederholt, bis ein Lock erfolgreich war oder aber Script-Timeout zuschlägt. Is es gesetzt, wird nur eine kleine Zahl von Lockversuchen vorgenommen (Standard sind oft fünf). Wenn diese keinen Erfolg hatten, wird flock() mit 'Return false' abgebrochen.
Wie ich vorhin schon ausgeführt habe, dürfen Veränderungen an der Datei (dazu gehört hier auch die Bewegung des Dateizeigers) nur im EXCLUSIVE LOCK vorgenommen werden, wenn man vor hat, in der Datei Änderungen vorzunehmen.
Außerdem empfiehlt es sich, auch manchmal clearstatcache() zu bemühen, wenn verschiedene Open- und Close-Vorgänge innerhalb eines Scriptes auf dieselbe Datei gehen.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi,
Ach so. Da lass Dir mal keine grauen Haare wachsen.
zu spaet, ich hab kaum noch welche ;-)
Außerdem enthält die deutsche Bewschreinung von flock() immer noch gravierende Fehler.
ja, denn dort steht zu LOCK_NB:" Wenn Sie Zugriffe während der Verriegelung durch flock() erlauben wollen..."
Vielen Dank mal an dieser Stelle, ich hatte das hier nach dem anderen Posting gelesen...
Gruesse, Joachim
Lieber Joachim,
ich hatte genau die gleiche Frage, wie Du. Hier der Link zu meinem Thread. Die Profis hier haben mir da wertvolle Hilfestellung gegeben.
Liebe Grüße aus Ellwangen,
Felix Riesterer.
Hi Felix,
ich hatte genau die gleiche Frage, wie Du. Hier der Link zu meinem Thread. Die Profis hier haben mir da wertvolle Hilfestellung gegeben.
ganz klar ist mir das immer noch nicht. Soviel habe ich aber verstanden:
1. der Rückgabewert von flock in einer Schleife zu pruefen macht keinen Sinn, da false erst eintritt, wenn der Versuch komplett abgebrochen wird.
2. file_exists etc in einer Schleife zu pruefen ist nicht nett zum Provider (heb ich auf, falls ich nochmal Strato nehmen sollte)
3. Es macht Sinn, eine extra Lockdatei anzulegen, diese zu locken und dann die eigentliche Datei zu modifizieren.
Lieg ich da in etwa richtig?
Gruesse Joachim
Hello,
ganz klar ist mir das immer noch nicht. Soviel habe ich aber verstanden:
- der Rückgabewert von flock in einer Schleife zu pruefen macht keinen Sinn, da false erst eintritt, wenn der Versuch komplett abgebrochen wird.
- file_exists etc in einer Schleife zu pruefen ist nicht nett zum Provider (heb ich auf, falls ich nochmal Strato nehmen sollte)
- Es macht Sinn, eine extra Lockdatei anzulegen, diese zu locken und dann die eigentliche Datei zu modifizieren.
Nein.
Mit file_exists kannst Du schon mal gar nichts anfangen, da es mit NAMEN und nicht mit einem HANDLE (als Rückgabewert) arbeitet. Alle Funktionen über Namen sind nur "Pi mal Daumen". Die Aussagewerte haben nur Gültigkeit zum Zeitpunkt des Aufrufes der Funktion.
Selbstverständlich kann man flock() selber in einer Schleife aufrufen.
Nur was muss man denn tun, wenn es failed?
Muss man es dann einfach nochmal versuchen, oder muss man das Script oder den Teil des Scriptes dann einfach ignorieren und abbrechen? Das entscheidet doch der Programmierer.
Der denkbar schlechteste Weg wird aber das automatische Warten auf ein erteiltes Lock sein (also ohne LOCK_NB). Das blockiert eine Apache-Instanz[*] und lässt den User sinnlos auf eine Fehlanzeige warten.
[*] gilt auch für andere Webserver
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi,
Mit file_exists kannst Du schon mal gar nichts anfangen, da es mit NAMEN und nicht mit einem HANDLE (als Rückgabewert) arbeitet.
das scheidet ja auch nach der Lektuere des andere Threads eh aus...
Selbstverständlich kann man flock() selber in einer Schleife aufrufen.
Du hattest doch geschrieben:
flock() liefert in der Default-Einstellung erst false, wenn das Script-Timeour erreicht ist.
Daraus hatte ich entnommen, das ein
while (counter < max) {
if (flock($fp,2)) {
...
flock($fp,3)
return true;
}
counter ++
usleep (300);
}
eigentlich nix bringt.
Der denkbar schlechteste Weg wird aber das automatische Warten auf ein erteiltes Lock sein (also ohne LOCK_NB). Das blockiert eine Apache-Instanz[*] und lässt den User sinnlos auf eine Fehlanzeige warten.
Das ist mein aktuelles Schema:
$lock = fopen($lockfile, "w")
if (flock ($lock, 2)) {
fp = fopen($file, "w")
fwrite ($fp, $text);
fclose ($fp);
flock ($lock, 3);
fclose ($lock);
return true;
}
else return error;
Wuerdest Du also fuers Locken des Lockfiles doch mit einer Schleife und dann mit LOCK_NB arbeiten?
Gruesse, Gruesse, Joachim
Hello,
Du hattest doch geschrieben:
flock() liefert in der Default-Einstellung erst false, wenn das Script-Timeour erreicht ist.
Ja hatte ich. Aber unvollständige Zitate sind auch Demagogie:
Ich hatte weiterhin ausgeführt, dass man den Befehl durch den Parameter LOCK_NB ergänzen muss:
$lock_ok = flock($lockh,LOCK_EX + LOCK_NB) or die("Error in locking!");
So würde flock() nur noch eine "kurze Schleife" drehen und es nur ein paar Millisekunden lang versuchen, eine Sperranforderung durchzubringen
Das $lock_ok muss man dann natürlich auswerten. Ist es true, hat der Lockversuch gefruchtet.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi,
So würde flock() nur noch eine "kurze Schleife" drehen und es nur ein paar Millisekunden lang versuchen, eine Sperranforderung durchzubringen
So habe ich es jetzt auch verstanden (und gemacht), allerdings erst nachdem ich unten Deine Ergaenzung zu LOCK_NB gelesen habe. Da ist das Manual leider wirklich irrefuehrend. Sorry also fuer meine Demagogie.
Danke und Gruesse, Joachim
Hello,
So habe ich es jetzt auch verstanden (und gemacht), allerdings erst nachdem ich unten Deine Ergaenzung zu LOCK_NB gelesen habe. Da ist das Manual leider wirklich irrefuehrend. Sorry also fuer meine Demagogie.
Kann ja jedem passieren;-))
Hauptsache es klappt jetzt.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom