Frage zum Konzept 'mehrere tie() auf eine Datei'
hotti
- perl
1 CPAN0 hotti
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
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.
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.
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
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
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