Hi!
Szenario: Zwei Besucher rufen eine Seite auf, zwei Instanzen des Counters werden gestartet; seien ihre Namen A und B. A oeffnet die Datei, liest sie ein, schliesst sie, zaehlt, was zu zaehlen ist, oeffnet die Datei zum Schreiben - diese wird damit auf Nullgroesse zurueckgesetzt. In diesem Moment schaltet das multitaskende Betriebssystem zu Prozess B. Der oeffnet die Datei zum Lesen, liest die gesamten Null Bytes ein, ... den Rest kannst Du Dir denken.
Und wenn Du nach dem open zum Lesen auch flock benutzen wuerdest? Das verringert die Wahrscheinlichkeit von Konflikten, ja, aber vollstaendig vermeiden wuerde es diese immer noch nicht. Das geht naemlich nicht. Nicht, solange Datei lesen und Datei schreiben in Deinem Script zwei voellig voneinander unabhaengige Dinge sind.
Du hast zwei Moeglichkeiten:
1. Oeffne die Datei mit
open(FILE, "+< clicks.txt");
zum gleichzeitigen Lesen und schreiben, sperre sie mit flock(), lies sie wie gewoehnlich ein, schliesse sie NICHT, sondern setze mit
seek(FILE, 0, 0);
den Dateizeiger an den Anfang zurueck, schreibe alles was Du loswerden willst. Jetzt muss Du die Datei abschneiden, denn wenn der neue Inhalt kuerzer ist als der alte, bleibt das, was hinter dem jetzigen Dateizeiger war, auch weiterhin stehen. Also
truncate(FILE, tell(FILE)); # immer schoen perlfunc lesen ;-)
und jetzt endlich die Datei schliessen.
Auf diese Weise hast Du Lesen und Schreiben zu einer einzigen Operation verknuepft, die gesamtheitlich durch flock() beschuetzt wird. Ich habe das auch mal in dieser Weise gemacht. Das Script laeuft noch heute, hatte auch noch nie Probleme gemacht, allerdings war es auch noch nie "unter Sperrfeuer", musste sich also noch nie unter erheblicher Last bewaehren.
2. Du packst saemtliche kritischen Operationen in einen schwarzen Kasten, der nur eine Tuer hat, und stellst einen Tuersteher davor. Der sorgt dafuer, dass immer nur einer in den Kasten darf und weitere Eintrittswillige gefaelligst zu warten haben. Im Programmierhandwerk wird so ein Tuersteher als binaere Semaphore bezeichnet, aber anderes als der Name suggeriert ist das eigentlich alles ganz einfach.
So eine Semaphore bietet Dir entweder das Betriebssystem an, wobei sich hier nicht viel gutes ueber die Portabilitaet sagen laesst. Oder Du nimmst ein Modul, dass sowas mit lustigen Tricks plattformuebergreifend bewerkstelligt. Da fallen mir auf Anhieb zwei solche Module ein. Eines, welches Teil des Sourcecodes dieses Forums ist (http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/selfforum/selfforum-cgi/shared/ (Lock.pm und Unterverzeichnis Lock)) und eines, das ich selber mal geschrieben habe (http://calocybe.dyndns.org/temp/FileSemaphore/). Ersteres ist ziemlich umfangreich und scheint ziemlich viel zu koennen. Zweiteres erfuellt seinen Zweck auch. ;-)
while (<FILE>) {
$file .= $_;
}
Einfacher:
{
local $/;
$file = <FILE>;
}
flock FILE, 2;
^ Wuerdest Du die LOCK_* Konstanten verwenden (mit use Fcntl ':flock'; importieren), wuesste man, was das bedeuted, ohne erst in der Referenz nachzuschauen.
HTH && So long
--
Falscher oder fehlender Kaffee. Benutzer angehalten.
[calokey: perl flock semaphore]