flock() Lösung
Cruz
- perl
0 Peter Squentz0 Cruz0 Peter Squentz0 Cruz0 Peter Squentz0 Cruz
0 Michael Schröpl0 Cruz
0 Peter Squentz
0 Calocybe
Hi!
Tut mir Leid, daß ich schon wieder mit diesem Thema anfange, aber im Archiv stehen nur jede Menge Diskussionen und keine richtige Lösung. Darum Poste ich hier mal eine erste Version für eine flock Lösung und ich hoffe, daß am Ende dieses Threads eine Lösung im Quellcodeformat steht, die noch unsere Enkel aus dem Archiv suchen werden.
Also hier we go:
----------------------------------------------------------------------------------------------------------------------------------
#!/usr/bin/perl
$timeout=10000; #how long the script waits between attempts to get a lock
$exit=100; #how many attempts to get a lock before exiting the script
if (!flock(FILE,2))
{
until ($released eq TRUE or $x>$exit) {
# little timeout
$i=0;
for ($i=0;$i<$timeout;$i++) {}
#count attempts
$x++;
if (flock(FILE,2)) {$released=TRUE;}
} # end until
} # end if
if ($exit>100) {
print "Server too busy, please try again.";
die;
}
else {
flock(FILE,2); # (I don't know if file still needs to be locked after "if (flock(FILE,2))")
flock(FILE,8);
} # end else
---------------------------------------------------------------------------------------------------------------------------------
Ich weiß z.B. schon mal nicht genau, ob der flock noch gesetzt werden muss, nachdem man in einer if clause schon versucht hat den lock zu kriegen.
Gruß
Cruz
$timeout=10000; #how long the script waits between attempts to get a lock
$exit=100; #how many attempts to get a lock before exiting the scriptif file is locked keep trying until $exit
if (!flock(FILE,2))
{
Was soll das denn? "flock FILE,2" wartet solange, bis der andere Prozess / die anderen Prozesse das File wieder freigeben haben. Wenn Du nur pruefen willst, ob eine Datei gelockt ist, musst Du LOCK_SH/LOCK_EX _und_ LOCK_NB benutzen.
release file
flock(FILE,8);
Das lass lieber bleiben. Schliesse die Datei einfach mit close, das impliziert einen LOCK_UN und ist wesentlich sicherer.
Peter
"flock FILE,2" wartet solange, bis der andere Prozess / die anderen Prozesse das File wieder freigeben haben.
Auch auf UNIX?
Auch auf UNIX?
Da auf jeden Fall.
Peter
Ergo, die optimal flock() Lösung ist so?
open (FILE, "file.ext");
flock(FILE,2);
#do your stuff
close(FILE);
Ergo, die optimal flock() Lösung ist so?
open (FILE, "file.ext");
flock(FILE,2);
#do your stuff
close(FILE);
Nein, für den reinen Lesezugriff ist LOCK_SH sinnvoller. Also:
flock FILE, 1;
Peter
Nein, für den reinen Lesezugriff ist LOCK_SH sinnvoller. Also:
flock FILE, 1;
Ja ne soll schon Schreibzugriff sein. Was bewirkt denn überhaupt der shared lock genau? Wenn andere Prozesse auch die Datei lesen können, warum soll sie dann überhaupt "gelockt" sein?
Übrigens, Danke für die Geduld und die ganzen Tipps.
Cruz
Ja ne soll schon Schreibzugriff sein. Was bewirkt denn überhaupt der shared lock genau? Wenn andere Prozesse auch die Datei lesen können, warum soll sie dann überhaupt "gelockt" sein?
Vielleicht gegen weitere Schreibzugriffe?
Wenn Du in einer record-strukturierten Datei nur den Inhalt einer Zeile ändern willst, dann darf niemand sonst diese Zeile gleichzeitig schreiben können - aber andere Prozesse sollten (auf eigenes Risiko, daß sich die von ihnen gelesene Zeile gerade ändert) durchaus lesen dürfen, ohne Dich zu stören.
Ergo, die optimal flock() Lösung ist so?
open (FILE, "file.ext");
flock(FILE,2);
#do your stuff
close(FILE);
Das kommt darauf an, was Du unter "optimal" verstehst.
Dein eigener Ansatz hatte ja immerhin ein Timeout-Konzept, was für eine CGI-Anwendung keine schlechte Idee ist (sonst gibt es einen Timeout durch den Webserver, und alles zerfällt zu feinstem Staub). flock() in der obigen Form ist abhängig von seiner Umwelt - und wenn diese das Semaphor ewig blockiert, dann hängst Du eben fest.
Deshalb fände ich ja eine "Test and Set"-Operation besser - die würde genau das tun, was Du willst, und das Wartezeitverhalten könntest Du selbst regeln.
Also dann vielleicht am besten so:
----------------------------------------------------------------------------------------------------------------------------------------
#!/usr/bin/perl
$timeout=10000; #how long the script waits between attempts to get a lock
$exit=100; #how many attempts to get a lock before exiting the script
open (FILE, "file");
if (!flock(FILE,2))
{
until ($released eq TRUE or $x>$exit) {
$i=0;
for ($i=0;$i<$timeout;$i++) {}
#count attempts
$x++;
if (flock(FILE,2)) {$released=TRUE;}
} # end until
} # end if
if ($exit>100) {
print "Server too busy, please try again.";
close(FILE);
die;
}
else {
flock(FILE,2);
close(FILE);
} # end else
----------------------------------------------------------------------------------------------------------------------------------------
Gruß
Cruz
Auch auf UNIX?
Da auf jeden Fall.
Peter
Hi Cruz!
Ich habe mal vor langer Zeit (naja, relativ) folgenden Code verwendet:
$cFLOCK_SHARED = 1;
$cFLOCK_EXCLUSIVE = 2;
$cFLOCK_NOBLOCK = 4;
$cFLOCK_UNLOCK = 8;
$cTIMEOUT = 10;
$cCOUNTERBASE = "local_counter.dat";
if (! -e $cCOUNTERBASE) {
open(CBASE, ">$cCOUNTERBASE");
close(CBASE);
}
for ($i=0; (!open(CBASE, "+<$cCOUNTERBASE") && ($i < $cTIMEOUT)); $i++) { sleep(1) }
abort() unless ($i < $cTIMEOUT);
for ($i=0; (!flock(CBASE, $cFLOCK_EXCLUSIVE$cFLOCK_NOBLOCK) && ($i < $cTIMEOUT)); $i++) { sleep(1) }
abort() unless ($i < $cTIMEOUT);
flock(CBASE, $cFLOCK_UNLOCK);
close(CBASE);
abort() ist eine eigene Funktion, die letztlich nur ein exit() oder die() macht. Hat bisher eigentlich noch nie Probleme gemacht, war aber auch noch nicht so sehr stark frequentiert, der Server auf dem das laeuft. Comments sind natuerlich erwuenscht.
Calocybe