Alain: db_file is nicht mit -f flock()!

hallo, Ich beiss mir regelrecht die zähne aus an dem einen satz seit tagen :( Der apache meckert immer wieder wenn ich $loginlog   =    'log/login'; $doflock   = 1;

if (dbmopen(%logins,$loginlog,0666)) {     -f flock(logins,2) if ($doflock) or die "$!";

oder

if (dbmopen(%logins,$loginlog,0666)) {     flock(%logins,2) if ($doflock) or die "$!";

verwende.

ich war auch schon auf den einschlägigen perl-seiten und konnte leider keine lösung finden wie z.B. diese: http://www.google.ch/search?q=-f+flock+perl&btnG=Google-Suche&hl=de&ie=ISO-8859-1

das mit tie hab ich auch schon brobiert,aber is nicht.Der server meldet immer wieder fehler,fehler,fehler...wie diese: flock() on unopened filehandle 0 at test.cgi line 83. Unquoted string "logins" may clash with future reserved word at test.cgi line 35. Use of uninitialized value in numeric gt (>) at test.cgi line 31. flock() on unopened filehandle logins at test.cgi line 35. flock() on unopened filehandle 0 at test.cgi line 83.

ich habe auch in der doku mal nach gekuckt und gesehen was der server so unterstützt: AnyDBM_File - provide framework for multiple DBMs

NDBM_File, DB_File, GDBM_File, SDBM_File, ODBM_File - various DBM implementations

=head1 SYNOPSIS

use AnyDBM_File;

aber leider bin ich nicht so der hirsch damit. ist es denn nicht Möglich das flock einfach so zu benutzen für db-files?

Grüsse vom Alain-- ...nichts ist so schlecht, als daß es nicht für irgend etwas gut wäre

  1. hallo, ich nochma, was bedeutet eigentlich

    tie %HASH , 'DB_File', '$loginlog', O_RDWR|O_CREAT, 0666; ^^ist das dasselbe wie dbmopen?

    wie könnte man das mit meinen variablen verbinden? use DB_File;

    my %HASH;

    tie %HASH , 'DB_File', '$loginlog', O_RDWR|O_CREAT, 0666;

    hier wird gelesen und allenfalls geschrieben...

    untie %HASH;

    das logins unten sollte dabei sein, weil es abhängig ist mit den darin enthaltenen daten.

    $loginlog   =    'log/login'; $doflock   = 1;

    if (dbmopen(%logins,$loginlog,0666)) {     -f flock(logins,2) if ($doflock) or die "$!";

    oder

    if (dbmopen(%logins,$loginlog,0666)) {     flock(%logins,2) if ($doflock) or die "$!";

    Grüsse vom Alain

    --
    ...nichts ist so schlecht, als daß es nicht für irgend etwas gut wäre
    1. hallo, ok ich habs jetzt (ohne fehler -w) geschafft :) die frage besteht aber nun ,ob man zwingend nach dieser methode

      use DB_File; my %logins; tie %logins , 'DB_File', "$loginlog", O_RDWR|O_CREAT, 0666;

      flock,2 setzten muss? Oder ist das bereits darin enthalten? Weil bei fast allen seiten , wo dieses thema aufgegriffen wird, wird auf flock() db_file nicht hingewiesen. Grüsse vom Alain

      --
      ...nichts ist so schlecht, als daß es nicht für irgend etwas gut wäre
      1. hallo,
        ok ich habs jetzt (ohne fehler -w) geschafft :)
        die frage besteht aber nun ,ob man zwingend
        nach dieser methode

        use DB_File;
        my %logins;
        tie %logins , 'DB_File', "$loginlog", O_RDWR|O_CREAT, 0666;

        flock,2 setzten muss?
        Oder ist das bereits darin enthalten?

        Nein.

        Hier der auschnitt aus meiner doku zu DB_File:
        ------------------------------------------------
        Concurrent access of a read-write database by several parties requires them all to use some kind of locking. Here's an example of Tom's that uses the fd method to get the file descriptor, and then a careful open() to give something Perl will flock() for you. Run this repeatedly in the background to watch the locks granted in proper order.

        use DB_File;
            use strict;
            sub LOCK_SH { 1 }
            sub LOCK_EX { 2 }
            sub LOCK_NB { 4 }
            sub LOCK_UN { 8 }
            my($oldval, $fd, $db, %db, $value, $key);
            $key = shift || 'default';
            $value = shift || 'magic';
            $value .= " $$";
            $db = tie(%db, 'DB_File', '/tmp/foo.db', O_CREAT|O_RDWR, 0644)
                    || die "dbcreat /tmp/foo.db $!";
            $fd = $db->fd;
            print "$$: db fd is $fd\n";
            open(DB_FH, "+<&=$fd") || die "dup $!";
            unless (flock (DB_FH, LOCK_SH | LOCK_NB)) {
                print "$$: CONTENTION; can't read during write update!
                            Waiting for read lock ($!) ....";
                unless (flock (DB_FH, LOCK_SH)) { die "flock: $!" }
            }
            print "$$: Read lock granted\n";
            $oldval = $db{$key};
            print "$$: Old value was $oldval\n";
            flock(DB_FH, LOCK_UN);
            unless (flock (DB_FH, LOCK_EX | LOCK_NB)) {
                print "$$: CONTENTION; must have exclusive lock!
                            Waiting for write lock ($!) ....";
                unless (flock (DB_FH, LOCK_EX)) { die "flock: $!" }
            }
            print "$$: Write lock granted\n";
            $db{$key} = $value;
            $db->sync;  # to flush
            sleep 10;
            flock(DB_FH, LOCK_UN);
            undef $db;
            untie %db;
            close(DB_FH);
            print "$$: Updated db to $key=$value\n";
        ------------------------------------------------
        Struppi.

        1. hallo,

          Hier der auschnitt aus meiner doku zu DB_File:

          Concurrent access of a read-write database by several parties requires them all to use some kind of locking. Here's an example of Tom's that uses the fd method to get the file descriptor, and then a careful open() to give something Perl will flock() for you. Run this repeatedly in the background to watch the locks granted in proper order.

          use DB_File;     use strict;     sub LOCK_SH { 1 }     sub LOCK_EX { 2 }     sub LOCK_NB { 4 }     sub LOCK_UN { 8 }     my($oldval, $fd, $db, %db, $value, $key);     $key = shift || 'default';     $value = shift || 'magic';     $value .= " $$";     $db = tie(%db, 'DB_File', '/tmp/foo.db', O_CREAT|O_RDWR, 0644)             || die "dbcreat /tmp/foo.db $!";     $fd = $db->fd;     print "$$: db fd is $fd\n";     open(DB_FH, "+<&=$fd") || die "dup $!";     unless (flock (DB_FH, LOCK_SH | LOCK_NB)) {         print "$$: CONTENTION; can't read during write update!                     Waiting for read lock ($!) ....";         unless (flock (DB_FH, LOCK_SH)) { die "flock: $!" }

          .............

          ok thanks,aber ist lock wircklich notwendig weil "tie" schützt die datei doch auch oder nicht? zum obigen beispiel -> gehts vielleicht auch einfacher? ich weiss schonmal dass ich LOCK_EX benötige und zweitens mit open open(DB_FH, "+<&=$fd")... kann man da auch open(LOGINS, "+<&=$fd") schreiben?

          Grüsse vom Alain

          --
          ...nichts ist so schlecht, als daß es nicht für irgend etwas gut wäre
          1. hallo, naja ich habs jetzt doch wieder so geschrieben

            if (dbmopen(%logins,$loginlog,0666)) {     flock(logins,2) if ($doflocks);    ($agent_last,$count_last,$date_last) = split(/*/,$logins{$username});

            blabla  flock(logins,8) if ($doflocks) or &Dead('Cannot flock file');         dbmclose(%logins);


            und lass es auch so,obwohl der server fehler -w findet bei flock(). Funktionieren tuts ja...nach zwei tagen suchen,hab ichs nun aufgegeben. Trotzdem dank für die mühe. Grüsse vom Alain

            --
            ...nichts ist so schlecht, als daß es nicht für irgend etwas gut wäre
            1. hallo,
              naja
              ich habs jetzt doch wieder so geschrieben

              if (dbmopen(%logins,$loginlog,0666))
              {
                  flock(logins,2) if ($doflocks);
                 ($agent_last,$count_last,$date_last) = split(/\*/,$logins{$username});

              Ich bezweifle stark, dass du damit einen Lock ausführst.

              mach mal: flock(logins,2) || die "kann Datei nicht flocken! $!";

              und, nein, tie macht keinen flock.

              Struppi.

              1. hallo,

                if (dbmopen(%logins,$loginlog,0666)) {     flock(logins,2) if ($doflocks);    ($agent_last,$count_last,$date_last) = split(/*/,$logins{$username});

                Ich bezweifle stark, dass du damit einen Lock ausführst.

                mach mal: flock(logins,2) || die "kann Datei nicht flocken! $!";

                und, nein, tie macht keinen flock.

                ok, naja der server schrieb das,was ich erwartet habe:

                Unquoted string "logins" may clash with future reserved word at abuse.cgi line 29. Unquoted string "logins" may clash with future reserved word at abuse.cgi line 76. kann Datei nicht flocken! Bad file descriptor at test.cgi line 29.

                ich denke das flock kann nicht als solches erkannt werden,jedenfalls nicht für dbmfile desshalb der error.

                Grüsse vom Alain

                --
                ...nichts ist so schlecht, als daß es nicht für irgend etwas gut wäre
                1. kann Datei nicht flocken! Bad file descriptor at test.cgi line 29.

                  ich denke das flock kann nicht als solches erkannt werden,jedenfalls nicht für dbmfile
                  desshalb der error.

                  Ich sagte dir doch bereits dreimal, du kannst nur einen Filhandle flocken und du flockst ein HASH was quatsch ist.

                  Du musst die DATEI öffnen und mit diesen Handle dein Flock ausführen.

                  Struppi.

                  1. hallo,

                    Du musst die DATEI öffnen und mit diesen Handle dein Flock ausführen.

                    okok, ich habs jetzt geschafft :) nach langem durchprobieren und natürlich mit der hilfe der dokumentation. Hier ist die Lösung:

                    use DB_File;

                    my %logins;

                    $db = (tie %logins , 'DB_File', "$loginlog", O_RDWR|O_CREAT, 0644);

                    $fd = $db->fd;

                    open(DB_FH, "+<&=$fd") || die "kann datei nicht oeffnen $!";

                    flock (DB_FH,2) || die "kann Datei nicht flocken! $!";

                    lese und schreibe irgendwas...

                    flock(DB_FH,8);     undef $db;     untie %logins;     close(DB_FH);

                    -------------------------------end of

                    Grüsse vom Alain

                    --
                    ...nichts ist so schlecht, als daß es nicht für irgend etwas gut wäre
                    1. soweit so gut, aber

                      lese und schreibe irgendwas...

                      flock(DB_FH,8);

                      Ich vermute mal das soll das flock aufheben (du solltest die symbolischen Konstanten von Fnctl verwenden) und das darf man nie machen!
                      Es kann gut sein, dass die Datei noch nicht auf die Festplatte geschrieben wurde und somit jetzt ungeflockt im Speicher liegt, d.h. ein neuer Prozess kann ungehindert auf ungeänderte Daten zugreifen und die Änderungen dieses Prozeß sind futsch.

                      undef $db;
                          untie %logins;
                          close(DB_FH);

                      close macht automatisch ein UNLOCK.

                      Struppi.

                      1. hallo struppi, besten dank also für den tip !

                        close macht automatisch ein UNLOCK.

                        Grüsse vom Alain

                        --
                        ...man(n) lernt nie aus :)
          2. ok thanks,aber ist lock wircklich notwendig weil "tie" schützt die datei doch auch
            oder nicht?

            Nein.

            zum obigen beispiel -> gehts vielleicht auch einfacher?

            Was ist daran nicht einfach?

            ich weiss schonmal dass ich LOCK_EX benötige und zweitens mit open open(DB_FH, "+<&=$fd")...
            kann man da auch open(LOGINS, "+<&=$fd") schreiben?

            Wie du den Filehandle benennst spielt keine Rolle, nur musst du diesen dann auch beim flocken benutzen.

            Struppi.

  2. hallo,
    Ich beiss mir regelrecht die zähne aus an dem einen satz seit tagen :(
    Der apache meckert immer wieder wenn ich

    Der Server meckert über ein Perlskript? Wohl kaum, es ist immer noch Perl das Warnungen und Fehler erzeugt.

    $loginlog   =    'log/login';
    $doflock   = 1;

    if (dbmopen(%logins,$loginlog,0666))
    {
        -f flock(logins,2) if ($doflock) or die "$!";

    oder

    if (dbmopen(%logins,$loginlog,0666))
    {
        flock(%logins,2) if ($doflock) or die "$!";

    Du kannst kein Flock auf einen HASH machen, dazu brauchst du einen Dateihandle auf eine geöffnete Datei.

    Und zwar musst du dazu (zumindest mit DB_File), die verwendete Datei flocken.

    open F, "+<$loginlog" || die "$!";
    flock F, LOCK_EX;

    ....

    Struppi.