hotti: Frage zum Konzept 'mehrere tie() auf eine Datei'

hi,

für ein paar meiner Anwendungen habe ich ein kleines Modul geschrieben, was numerische Werte, einem Key zugeordnet, verwaltet:

  
tie my %h, 'Counter', {-file => $file, -keys => ['foo','bar']};  
# oder  
tie my %h, 'Counter', {-file => $file, -incr => ['foo','bar']};  

Mit -incr => [..] wird beim Initialisieren der Wert zum zugehörigen Key um eins erhöht, unabhängig davon können die Werte zur Laufzeit verändert oder weitergezählt werden. In der Datei, wo das gespeichert wird, können weitere Keys liegen, ein Zugriff ist jedoch nur über -keys|-incr => [..] möglich, also diejenigen Keys, die beim tie() angegeben sind. Einem versehentliches Ändern der Keys anderer Anwendungen wird so vorgebeugt.

Nun kann es ja sein, dass das Modul von allgemeinen Interesse ist, von daher ist es in der jetzigen Version möglich, in einer main() mehrere tie() auf einunddieselbe Datei folgen zu lassen ohne dass ein Deadlock entsteht; bisher hat das jedoch keinen Effekt und ich selbst sehe auch keinen Sinn darin, weil das dem Konzept zum exclusive Lock widerspricht, was dazu eingebaut wurde, dass die Daten konsistent bleiben:

main(A) liest Ziffer 3, erhöht auf 10 und schreibt zurück. Was nicht passieren darf: main(B) liest auch eine 3 in der Zeit, wo main(A) noch nicht zurückgeschrieben hat. Mit Lock_Ex wird das verhindert: main(B) darf erst lesen, wenn main(A) fertig ist und liest eine 10.

Eine Zulassung mehrfacher tie() mit einundderselben Datei stellt dieses Konzept in Frage und führt es ad absurdum.

Oder sieht das jemand anders?

Hotti

--
Mach die Fehler da, wo sie wiederzufinden sind, das erleichtert die Suche!
  1. Meinst du das binden derselben Variable mehrmals an die gleiche Klasse? Klar kriegt man da unterschiedliche Instanzen.

      
    $ perl -MDevel::Peek -e'  
        use Tie::Hash::NamedCapture;  
        Dump tie %h, "Tie::Hash::NamedCapture";  
        Dump tie %h, "Tie::Hash::NamedCapture";  
    '  
    SV = IV(0x744218) at 0x744220  
      REFCNT = 2  
      FLAGS = (TEMP,ROK)  
      RV = 0x79d8c8  
      SV = PVMG(0x794660) at 0x79d8c8  
        REFCNT = 1  
        FLAGS = (PADMY,OBJECT,IOK,pIOK)  
        IV = 256  
        NV = 0  
        PV = 0  
        STASH = 0x75b460    "Tie::Hash::NamedCapture"  
    SV = IV(0x75b938) at 0x75b940  
      REFCNT = 2  
      FLAGS = (TEMP,ROK)  
      RV = 0x744430  
      SV = PVMG(0x794690) at 0x744430  
        REFCNT = 1  
        FLAGS = (PADMY,OBJECT,IOK,pIOK)  
        IV = 256  
        NV = 0  
        PV = 0  
        STASH = 0x75b460    "Tie::Hash::NamedCapture"  
    
    

    Wenn das ein Konsument deiner Klasse macht, ist das ein Programmierfehler und nicht anders zu sehen als $i = C->new; $i = C->new;. Dokumentiere dies unter einer Überschrift "Pitfalls", wenn du magst. AFAICS helfen Singletonmechanismen hier nicht. Vom gewaltsamen Herummurksen in den Eingeweiden von Perl zur Unterbindung dieses Fehlerfalls rate ich ab, die Risiken sind immer nicht absehbar und stehen nicht im Verhältnis zum Nutzen.

    1. hi,

      danke ;

      Wenn das ein Konsument deiner Klasse macht, ist das ein Programmierfehler und nicht anders zu sehen als $i = C->new; $i = C->new;. Dokumentiere dies unter einer Überschrift "Pitfalls", wenn du magst. AFAICS helfen Singletonmechanismen hier nicht. Vom gewaltsamen Herummurksen in den Eingeweiden von Perl zur Unterbindung dieses Fehlerfalls rate ich ab, die Risiken sind immer nicht absehbar und stehen nicht im Verhältnis zum Nutzen.

      In meiner Frage gehts weniger um Perl (sorry), vielmehr um die Realisierung eines Transaktionskonzepts. Dieses Transaktionskonzept sieht vor, dass jeder Zugriff auf eine Repository (Datei) vom "Lesen bis zum Schreiben" ein in sich abgeschlossener Vorgang ist.

      Somit darf ein zweites (oder jedes weitere) tie() innerhalb _einer_ main() auf die gleiche Datei nur lesenden Zugriff haben: wenn überhaupt(?) und genau das ist die Frage.

      Konkret:
      Der Konstruktor lädt die gewünschten Werte (hier sind es assoziierte Nummern) in den main()-Space like this:

        
      tie my %h, 'Counter', {-file => $file, -incr => ['foo','bar'], -keys => ['baz']} or die $!;  
        
      $h{baz}++;        # ok  
      $h{foo} = 99;     # ok  
      $h{bar} = 'otto'; # carp, not a number  
      $h{hugo}++;       # carp, key not predefined...  
        
      my $o = tied %h;  
      $o->hashdump;  
      
      

      Wobei die Numerics in '-incr' beim tie() um Eins erhöht werden, die Nummern in '-keys' jedoch nicht. Die Repository kann weitere Nummern enthalten, ein

        
      $o->filedump;  
      
      

      gibt alles aus, was 'drin ist.

      Ein zweites tie(*) innerhalb einer main() ist überflüssig (**), das Modul ist jedoch so konzipiert, dass damit zumindest kein DeadLock entsteht.

      (*) auf die gleiche Datei
      (**) aber möglich und nur lesender Zugriff

      Die Frage noch einmal anders gestellt: Welcher Programmierer braucht innerhalb einer main() ein zweites tie() und wozu?

      Hotti

      Modul Source siehe Link, es tut so wie beschrieben.

      1. Moin Moin!

        In meiner Frage gehts weniger um Perl (sorry), vielmehr um die Realisierung eines Transaktionskonzepts. Dieses Transaktionskonzept sieht vor, dass jeder Zugriff auf eine Repository (Datei) vom "Lesen bis zum Schreiben" ein in sich abgeschlossener Vorgang ist.

        Och nö, laß mal stecken. Das Rad wurde bereits einige Male erfunden: DBI + DBD::SQLite und gut ist. Und wenn's mal größer wird, nimmst Du stattdessen PostgreSQL und DBD::Pg. Es sei denn, Du hast zu viel Geld, dann kaufst Du Dir eine Oracle-Lizenz und nimmst DBD::Oracle.

        Für meinen Geschmack verändert Dein tie-Mechanismus das Verhalten der Hashes dermaßen, dass die kaum noch etwas mit gewöhnlichen Hashes gemein haben. Das ist dann kein Fall mehr für tie, sondern für bless.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
        1. Moin Moin!

          In meiner Frage gehts weniger um Perl (sorry), vielmehr um die Realisierung eines Transaktionskonzepts. Dieses Transaktionskonzept sieht vor, dass jeder Zugriff auf eine Repository (Datei) vom "Lesen bis zum Schreiben" ein in sich abgeschlossener Vorgang ist.

          Och nö, laß mal stecken.

          Ohh Mann, ja. Darum gehts auch gar nicht. Versteht denn keiner meine Frage:

          Welcher Programmierer braucht mehr als ein tie() auf einundieselbe Repository?

            
          tie %h1, 'Class', $file;  
          tie %h2, 'Class', $file;  
          
          

          Und jetzt hast Du mich soweit provoziert, dass ich sage: Nö! Das braucht keiner, es ergibt keinen Sinn, %h1 und %h2 sind identisch.

          Aber vielleicht kommt ja doch noch einer, der sowas braucht ;)

          Hotti

        2. moin Alexander,

          Für meinen Geschmack verändert Dein tie-Mechanismus das Verhalten der Hashes dermaßen, dass die kaum noch etwas mit gewöhnlichen Hashes gemein haben. Das ist dann kein Fall mehr für tie, sondern für bless.

          Du möchtest nur den native hash bless'n. Bitteschön, dann hast Du Filehandle und Daten paketweit, erschwerst Dir die Fehlersuche und nimmst noch andere Konsequenzen in Kauf, die möglicherweise nicht nach Deinem Geschmack sind. Du darfst dann selbst dafür sorgen, dass FH geschlossen wird, weil das dann nicht mehr automatisch in DESTROY passiert. Mthoden, die Du schreiben möchtest, kranken daran, dass sie auf paketweite Variablen zugreifen müssen, weil Dein Objekt keine wirkliche Instanz der Klasse ist.

          Viele Grüße an alle,
          schönen Sonntag,
          Hotti