function increase_save_count() {
if (!file_exists(PFAD."counter_files/count.txt")) {
error("no_counter_file");
} elseif (!is_writable(PFAD."counter_files/count.txt")) {
error("count_unwriteable");
} else {
$counts = file(PFAD."counter_files/count.txt");
$count = trim($counts[0]);
$count++;
$fh = fopen(PFAD."counter_files/count.txt","wb");
flock($fh, LOCK_EX);
fwrite($fh, $count);
fclose($fh);
$string = $count . " " . date("H:i:s",time(TRUE)) . " " .
$_SERVER[ "REMOTE_ADDR" ] . "\n" ;
$logfile = PFAD."counter_files/countlog.txt";
$fh = fopen($logfile,"a");
flock($fh, LOCK_EX);
fwrite($fh, $string);
fclose($fh);
}
return;
}
Dieser Counter springt so alle paar tausend Counts, aber unregelmäßig,
auf "0".
Wie kann das passieren? Wie kann ich das verhindern?
Der Code stammt aus einer fertigen Codeschnipselsammlung. Ich habe nur
den Zusatz bezüglich der Mitspeicherung im "countlog" drangehängt
damit ch den Counter anhand des Logfiles wieder neu setzen kann.
Ein ähnliches Script in einer anderen Webseite per Perl/CGI hat das
selbe Problem. Alle paat zehntausend counts springt es willkürlich auf
"0"
> Hallo, ich nutze folgenden Code für einen Counter:
>
> function increase_save_count() {
> if (!file_exists(PFAD."counter_files/count.txt")) {
> error("no_counter_file");
> } elseif (!is_writable(PFAD."counter_files/count.txt")) {
> error("count_unwriteable");
> } else {
> $counts = file(PFAD."counter_files/count.txt");
> $count = trim($counts[0]);
> $count++;
> $fh = fopen(PFAD."counter_files/count.txt","wb");
> flock($fh, LOCK_EX);
> fwrite($fh, $count);
> fclose($fh);
Hi Jens
Schau dir mal den Counter (siehe Link unten) an (Code und Beispiel).
Mit dem gab es nach meinem Kenntnisstand bisher noch keine Probleme
und vielleicht bekommst du dort eine Idee, wie du deinen Counter
optimieren kannst oder ersetzen.
Der aelteste Counter, den ich verwende - freilich in TCL, steht jetzt
bei 187095 (siehe Link unten) und ist durchaus vergleichbar, weil er
einen vergleichbaren Code verwendet..
Franz-Josef
http://www.huecker.com/msw/php/php_man_f.shtml
--
Dr. Franz-Josef Huecker
W3: http://www.huecker.com
Email: in...@huecker.com
> > $counts = file(PFAD."counter_files/count.txt");
> > $count = trim($counts[0]);
> > $count++;
> > $fh = fopen(PFAD."counter_files/count.txt","wb");
> > flock($fh, LOCK_EX);
> > fwrite($fh, $count);
> > fclose($fh);
> Hi Jens
Hi Franz-Josef
> Schau dir mal den Counter (siehe Link unten) an (Code und Beispiel).
> aus http://www.huecker.com/msw/php/php_man_f.shtml
| $count = @file ( $file ); // Inhalt von file lesen, - in Array speichern.
| $state = $count[0]; // Status einlesen.
| ++$state; // Zähler um eins erhöhen.
| $fp = fopen ( $file, "w" );
| @fwrite ( $fp, $state ); // counter.dat aktualisieren.
| fclose ( $fp );
Das Beispiel entspricht fast meiner Routine. Nur hat sie kein "flock".
Damit wäre nach meinem bisherigen Verständnis meine Routine sicherer.
Wobei es nicht "meine" Erfindung ist. Ich habe sie aus einer
Codesammlung und nur eingebaut.
> Mit dem gab es nach meinem Kenntnisstand bisher noch keine Probleme
> und vielleicht bekommst du dort eine Idee, wie du deinen Counter
> optimieren kannst oder ersetzen.
> Der aelteste Counter, den ich verwende - freilich in TCL, steht jetzt
> bei 187095 (siehe Link unten) und ist durchaus vergleichbar, weil er
> einen vergleichbaren Code verwendet..
Ich habe die MIO schon lange überschritten. <g> Pro Tag im Schnitt ca.
300 zählende Zugriffe.
Danke für den Tip
> Ich habe die MIO schon lange überschritten. <g> Pro Tag im Schnitt ca.
> 300 zählende Zugriffe.
Hi Jens
Bei dem Traffic ist flock natuerlich zwingend. Mein Hinweis zeigte
auf ein Einfuehrungsbeispiel, das zeigen sollte, wie so ein Zaehler
grundsaetzalich gestaltet werden kann.
flock wird spaeter eingefuehrt. In Lektion 10 . HTML Forumulare und
PHP sieht das dann so aus:
$fp = fopen($file, 'r+');
flock ($fp, LOCK_SH);
$count = fread($fp, 4096);
rewind ( $fp );
fwrite($fp, ++$count);
fflush ($fp);
flock ($fp, LOCK_UN);
fclose($fp);
Ich vermute, das wird dir auch nicht weiterhelfen.Um das Problem
einzugrenzen, wuerde ich das Konzept mit while ueber den kritischen
Wert hinauslaufen lassen. Dann sollte sich doch zeigen, ob der Counter
grundsaetzlich funktioniert, was ich vermute.
Franz-Josef
ich vermute dein Problem liegt hier:
> $counts = file(PFAD."counter_files/count.txt");
file() liefert False zurück, wenn die Operation fehlgeschlagen ist. Das
kann durchaus mal vorkommen. Du testest zwar einen Schritt vorher ob die
Datei schreibbar ist, das kann sich beim file()-Aufruf aber schon wieder
geändert haben, wenn du parallele Zugriffe hast. Ein paralleler Prozess,
hat vielleicht gerade einen Schreib-lock für die Datei bekommen. Eine
klassische Race Condition. Du solltest dann zwar in der Zeile:
> $count = trim($counts[0]);
eine NOTICE bekommen, das der Index 0 in $counts nicht existiert, aber
ansonsten läuft dein Programm weiter und betrachtet $count dann als 0.
Am Ende sollte er einen Counter von 1 in die Datei schreiben.
Die Lösung dürfte sein, den lock auf das File schon vor dem lesen zu
holen, bzw. fürs lesen einen shared lock anzufordern.
Du solltest auch beachten das seit php 5.3.2 der lock nicht mehr
automatisch aufgehoben wird, wenn du fclose() aufrufst, dass musst du
dann via flock() explizit tun.
Bye,
Dennis