Umstellung: Generisches Schreiben und Lesen von (Konfigurations-) Dateien

Begonnen von betateilchen, 26 April 2014, 12:52:46

Vorheriges Thema - Nächstes Thema

betateilchen

Zitat von: rudolfkoenig am 26 April 2014, 10:03:47
Wir sollten alles auf einem zu bauenden readFile/writeFile umstellen (Argument und Rueckgabe ein array von Zeilen), damit die eigentlichen Funktionen an eine Stelle sind.




Folgendes ist nun in die configDB implementiert:


sub cfgDB_FileRead($) {
my ($filename) = @_;

...

return (int(@outfile)) ? @outfile : undef;



sub cfgDB_FileWrite($@) {
my ($filename,@content) = @_;

...

return;
}



sub cfgDB_FileUpdate($) {
my ($filename) = @_;

...

return "";
}


Die bisherigen Funktionen sind aus Kompatibilitätsgründen ebenfalls noch nutzbar, ich plane die Entfernung aber für Mitte Juni.

cfgDB_FileUpdate ist eine reine Umbenennung, um eine Namenslogik bei den Funktionsnamen einzuhalten.
Die Funktion wird nur in der 98_update benutzt.



-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Die notwendigen Änderungen in den Modulen, die bisher schon mit configDB zusammenarbeten,
werde ich nach entsprechenden Tests hier im Thread kundtun.


  • 01_FHEMWEB.pm
  • 02_RSS.pm -  diff done - erledigt
  • 93_DbLog.pm - diff done
  • 95_holiday.pm - diff done
  • 98_SVG.pm - diff done
  • 98_update.pm - diff done
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen


Index: 98_update.pm
===================================================================
--- 98_update.pm (revision 5666)
+++ 98_update.pm (working copy)
@@ -788,7 +788,7 @@
         print FH $fileContent;
         close (FH);
         Log 5, "update write $localFile";
-        $writeError .= _cfgDB_Updatefile($localFile) if(configDBUsed());
+        $writeError .= cfgDB_FileUpdate($localFile) if(configDBUsed());
       } else {
         delete $updateFiles_ref->{$f};
         Log 1, "update Can't write $localFile: $!";
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

wg. 01_FHEMWEB.pm

Da dort noch nicht wirklich mit arrays beim Lesen/Schreiben von Dateien gearbeitet wird, warte ich da ausnahmsweise auf Rudis Vorarbeit.
Die notwendigen Funktionen in configDB stehen jedenfalls bereit.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

wo wir gerade beim Standardisieren sind...

Rudi, könntest Du bitte irgendwann Funktion(en) für das escapen und regexen von DEFs bereitstellen? Das ist ein wunder Punkt bei der Migration von fhem.cfg nach configDB und dann auch bei der Übergabe an den Editor von FHEMWEB (unabhängig von standard oder codemirror)

Es wäre schön, wenn man einfach per - beispielsweise - "getDef('deviceName')" einen standardisierten String zurückbekommen würde, der innerhalb von fhem überall verarbeitet werden und bei Bedarf auch wieder abgespeichert werden kann.

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

Habe angefangen mit der Umstellung auf die zentrale FileRead/FileWrite Funktionen, ich habe SVG und holiday komplett umgestellt. Falls ich mich nicht irre, muss ich noch FHEMWEB, backup und update umbauen, ich warte aber noch, bis du die aktuellen Aenderungen geprueft hast.

Die hier angehaengten Patches werde ich erstmal ignorieren :), ich haette gerne configDB nur zentral geprueft, wenn moeglich.

Bemerkungen:
- das gewaehlte Rueckgabeverfahren
(int(@outfile)) ? @outfile : undef;
macht die Ueberpruefung nicht gerade einfach, aber wir koennen erstmal dabei bleiben.
- ich meine du bist zu optimistisch beim Schreiben der Daten nicht explizit ein Zeilennummer
zu schreiben, SQL sichert nirgendwo zu, dass die Daten beim lesen in der gleichen Reihenfolge
geliefert werden. Habe ich etwas uebersehen?



justme1968

das heisst ich muss nur auf FileRead und FileWrite umstellen und das LightScene modul würde transparent die configDB verwenden?

das initiale importieren der config beim umstellen geschieht ein mal mit fileimport?

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968


betateilchen

Zitat von: rudolfkoenig am 01 Mai 2014, 17:10:45
Habe ich etwas uebersehen?

Ja....

Zitat von: rudolfkoenig am 01 Mai 2014, 17:10:45
Die hier angehaengten Patches werde ich erstmal ignorieren :), ich haette gerne configDB nur zentral geprueft, wenn moeglich.

z.B. im Vorfeld etwas genauer zu beschreiben, wie Du Dir das vorgestellt hast (z.B. bis auf welche Ebene Du es zentralisieren willst. Ich konnte nur von den Informationen ausgehen, die ich bis zum Zeitpunkt der Patchvorschläge hatte)

Zitat von: rudolfkoenig am 01 Mai 2014, 17:10:45
- das gewaehlte Rueckgabeverfahren
macht die Ueberpruefung nicht gerade einfach, aber wir koennen erstmal dabei bleiben.

z.B. einen Vorschlag zu machen, was Du besser fändest.

Zitat von: rudolfkoenig am 01 Mai 2014, 17:10:45
- ich meine du bist zu optimistisch beim Schreiben der Daten nicht explizit ein Zeilennummer
zu schreiben, SQL sichert nirgendwo zu, dass die Daten beim lesen in der gleichen Reihenfolge
geliefert werden.

Das mit den nicht garantierten Reihenfolgen ist korrekt, deshalb verwende ich je nach Verwendungszweck der Daten beim Lesen auch zwei unterschiedliche Verfahren. Eines, bei dem mir die Reihenfolge völlig wurscht ist, und eines, wo ich mich darauf verlassen kann, dass die zurückgelieferte Reihenfolge stimmt. Beim Lesen der Daten aus den Konfigurationsdateien erwarte ich keine Reihenfolgenprobleme.

Zitat von: rudolfkoenig am 01 Mai 2014, 17:10:45
ich habe SVG und holiday komplett umgestellt. Falls ich mich nicht irre, muss ich noch FHEMWEB, backup und update umbauen, ich warte aber noch, bis du die aktuellen Aenderungen geprueft hast.

Für Sonntag ist hier ganztägig Regen angesagt, da hab ich Zeit :)

Was willst Du denn in backup umbauen? Backup unterstützt doch configDB ohnehin nicht mehr ... :(

Zitat von: rudolfkoenig am 01 Mai 2014, 17:10:45
Habe angefangen mit der Umstellung auf die zentrale FileRead/FileWrite Funktionen,

Sollte man das eventuell ankündigen, damit (hoffentlich) alle Entwickler das mitkriegen?
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Die Umstellung in 98_update hält sich ja sehr in Grenzen, Du übergibst dort nur den Dateinamen an die Datenbank und die schaut nach, ob sie das File in sich trägt, wenn ja, wird es automatisch importiert und aus dem Filesystem gelöscht.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

Ich habe nur gesehen, dass configDB in den erwaehnten und von mir betreuten Modulen aufgerufen wird, und habe die noch nicht naeher angeschaut. Bei update und backup sehe ich aber ein, dass das nicht einfach/sinnvoll zu machen ist, und FHEMWEB wird auch nicht komplett davon befreit werden koennen.

Idealerweise ist eine Pruefung auf configDB in den Modulen gar nicht notwendig, weil alles zentral in Funktionen wie FileRead gekapselt ist. Wenn dann einer auf die Idee kommt, bei jeder Aenderung automatisch ein Backup anzulegen, oder Dateien im Cloud zu speichern, dann kann man das an eine Stelle aendern. Ich sehe aber ein, dass grundlegende Unterschiede (bei FileLog kann man fhem.cfg bearbeiten, bei configDB nicht) damit nur unschoen zu loesen sind.

Vorschlag fuer Rueckgabe waere ($err, @rows), da ich mich mit der aktuellen Pruefung auf Fehler (@ret==1 && !defined($ret[0]) etwas unwohl fuehle. Ist aber nicht tragisch, ich habe mich schon daran gewoehnt :)

betateilchen

Zitat von: rudolfkoenig am 01 Mai 2014, 17:10:45
Habe angefangen mit der Umstellung auf die zentrale FileRead/FileWrite Funktionen, ich habe SVG und holiday komplett umgestellt.
...
ich warte aber noch, bis du die aktuellen Aenderungen geprueft hast.

SVG und holiday funktionieren fehlerfrei.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

#12
Aktueller Sachstand:


  • 01_FHEMWEB.pm erledigt
  • 02_RSS.pm erledigt
  • 93_DbLog.pm erledigt
  • 95_holiday.pm erledigt
  • 98_SVG.pm erledigt
  • 98_update.pm erledigt
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Zitat von: betateilchen am 26 April 2014, 22:13:38
wo wir gerade beim Standardisieren sind...
Rudi, könntest Du bitte irgendwann Funktion(en) für das escapen und regexen von DEFs bereitstellen? Das ist ein wunder Punkt bei der Migration von fhem.cfg nach configDB und dann auch bei der Übergabe an den Editor von FHEMWEB (unabhängig von standard oder codemirror)

hat sich erledigt.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Soweit ich das erkennen kann, sind nun alle Module, die bereits im Vorfeld auf die Benutzung der configDB umgestellt wurden, auf das generische Lesen/Schreiben umgestellt.

Danke an alle Beteiligten für die Unterstützung!
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Hallo Rudi,

diese Lösung ist wirklich prima, allerdings scheitert sie aktuell in der 01_FHEMWEB.pm

Dort müssen wir in "Edit files" unterscheiden, ob die Datei im Dateisystem oder in der Datenbank liegt, und dann die Datei von der entsprechenden Stelle lesen.


  } elsif($a[1] eq "edit") {
...
    if ($cfgDB eq 'configDB') {
      my $filePath = FW_fileNameToPath($fileName);
      my ($err,@content) = cfgDB_FileRead($filePath);
      $data = join("\n",@content);
    } else {
      $fileName =~ s,.*/,,g;        # Little bit of security
      my $filePath = FW_fileNameToPath($fileName);
      my($err, @data) = FileRead($filePath);
      if($err) {
        FW_pO "<div id=\"content\">$err</div>";
        return;
      }
      $data = join("\n", @data);
      close(FH);
    }


Es wird an dieser Stelle unterschieden, ob der Eintrag "configDB" am Ende des Links steht oder nicht.
Falls ja, wird die Datei aus der Datenbank gelesen => Völlig korrekt.

Falls nein, wird die Datei zum Lesen an FileRead() übergeben. FileRead stellt stellt dann anhand configDBUsed() fest, dass es auf die Datenbank zugreifen soll, obwohl das genau in dem Moment eine falsche Entscheidung ist. In dem Moment, wo in den obigen else() Zweig übergeben wird, muss die Datei immer aus dem Dateisystem gelesen werden.

Entweder sollte FileRead() einen (optionalen) Parameter bekommen, um das Lesen von einer bestimmten Stelle zu erzwingen oder wir brauchen eine systemisch andere Lösung.

Gleiches trifft vermutlich auch auf FileWrite() zu, das habe ich aber aktuell noch nicht geprüft.

Problemthread auch hier: http://forum.fhem.de/index.php/topic,24132.0.html
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

Danke fuer den Hinweis.

FileRead/FileWrite kann statt filename einen Hash als ersten Parameter bekommen, das schaut dann so aus:

FileRead({FileName=>$filePath, ForceType=>"file"} );

betateilchen

Tolle Lösung, danke :)

Ich denke, das ist ein Spezialfall, der ohnehin nur in der FHEMWEB auftreten wird. Aber mit der Lösung kann ich mir jetzt nochmal Gedanken machen, ob wir auf die Sonderbehandlung in der FHEMWEB vielleicht komplett verzichten können.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Hallo Rudi,

Zitat von: betateilchen am 01 Juni 2014, 16:48:18
mit der Lösung kann ich mir jetzt nochmal Gedanken machen, ob wir auf die Sonderbehandlung in der FHEMWEB vielleicht komplett verzichten können.

das scheint recht einfach zu klappen. Mit dem untenstehenden Patch kann ich auf die Sonderbehandlung in "style edit" und "style save" verzichten. Kannst Du da mal bitte drüberschauen? Ich habe das sowohl mit Dateien in der configDB als auch im Filesystem erfolgreich getestet.

Damit bleiben in der FHEMWEB nur noch zwei logikbedingt unvermeidbare Abfragen auf configDBUsed() übrig:


  • für das Ausblenden der fhem.cfg in "Edit files"
  • für das Lesen der FileList aus der Datenbank

Ich hoffe, das sollte nun alles in allem Deinen geäußerten Wünschen entsprechen.


Viele Grüße
Udo



Index: 01_FHEMWEB.pm
===================================================================
--- 01_FHEMWEB.pm (revision 6027)
+++ 01_FHEMWEB.pm (working copy)
@@ -1635,21 +1635,15 @@
     my $fileName = $a[2];
     my $data = "";
     my $cfgDB = defined($a[3]) ? $a[3] : "";
-    if ($cfgDB eq 'configDB') {
-      my $filePath = FW_fileNameToPath($fileName);
-      my ($err,@content) = cfgDB_FileRead($filePath);
-      $data = join("\n",@content);
-    } else {
-      $fileName =~ s,.*/,,g;        # Little bit of security
-      my $filePath = FW_fileNameToPath($fileName);
-      my($err, @data) = FileRead({FileName=>$filePath, ForceType=>"file"} );
-      if($err) {
-        FW_pO "<div id=\"content\">$err</div>";
-        return;
-      }
-      $data = join("\n", @data);
-      close(FH);
+    my $forceType = ($cfgDB eq 'configDB') ? $cfgDB : "file";
+    $fileName =~ s,.*/,,g;        # Little bit of security
+    my $filePath = FW_fileNameToPath($fileName);
+    my($err, @content) = FileRead({FileName=>$filePath, ForceType=>$forceType} );
+    if($err) {
+      FW_pO "<div id=\"content\">$err</div>";
+      return;
     }
+    $data = join("\n", @content);

     $data =~ s/&/&amp;/g;

@@ -1670,35 +1664,23 @@
   } elsif($a[1] eq "save") {
     my $fileName = $a[2];
     my $cfgDB = defined($a[3]) ? $a[3] : "";
+    my $forceType = ($cfgDB eq 'configDB') ? $cfgDB : "file";
     $fileName = $FW_webArgs{saveName}
         if($FW_webArgs{saveAs} && $FW_webArgs{saveName});
     $fileName =~ s,.*/,,g;        # Little bit of security
     my $filePath = FW_fileNameToPath($fileName);

-    if($cfgDB ne 'configDB') { # save file to filesystem
-
-      $FW_data =~ s/\r//g;
-      my $err = FileWrite({FileName=>$filePath, ForceType=>"file"}, split("\n", $FW_data));
-      if($err) {
-        FW_pO "<div id=\"content\">$filePath: $!</div>";
-        return;
-      }
-      my $ret = FW_fC("rereadcfg") if($filePath eq $attr{global}{configfile});
-      $ret = FW_fC("reload $fileName") if($fileName =~ m,\.pm$,);
-      $ret = ($ret ? "<h3>ERROR:</h3><b>$ret</b>" : "Saved the file $fileName");
-      FW_style("style list", $ret);
-      $ret = "";
-
-    } else { # save file to configDB
-      $FW_data =~ s/\r//g if($^O !~ m/Win/);
-      my @content = split(/\n/,$FW_data);
-      cfgDB_FileWrite($filePath,@content);
-      my $ret = FW_fC("reload $fileName") if($fileName =~ m,\.pm$,);
-      $ret = ($ret ? "<h3>ERROR:</h3><b>$ret</b>" :
-                        "Saved the file $fileName to configDB");
-      FW_style("style list", $ret);
-      $ret = "";
+    $FW_data =~ s/\r//g;
+    my $err = FileWrite({FileName=>$filePath, ForceType=>$forceType}, split("\n", $FW_data));
+    if($err) {
+      FW_pO "<div id=\"content\">$filePath: $!</div>";
+      return;
     }
+    my $ret = FW_fC("rereadcfg") if($filePath eq $attr{global}{configfile});
+    $ret = FW_fC("reload $fileName") if($fileName =~ m,\.pm$,);
+    $ret = ($ret ? "<h3>ERROR:</h3><b>$ret</b>" : "Saved the file $fileName to $forceType");
+    FW_style("style list", $ret);
+    $ret = "";

   } elsif($a[1] eq "iconFor") {
     FW_iconTable("iconFor", "icon", "style setIF $a[2] %s", undef);
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

ZitatIch hoffe, das sollte nun alles in allem Deinen geäußerten Wünschen entsprechen.

Ja, sehr, habs eingecheckt.

betateilchen

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!