2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 09:16:53 +00:00

93_DbRep: contrib 8.40.7

git-svn-id: https://svn.fhem.de/fhem/trunk@22725 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2020-09-03 21:43:23 +00:00
parent 6f023412d4
commit faf6f92f13

View File

@ -1,5 +1,5 @@
##########################################################################################################
# $Id: 93_DbRep.pm 22455 2020-07-23 21:09:07Z DS_Starter $
# $Id: 93_DbRep.pm 22678 2020-08-27 17:05:24Z DS_Starter $
##########################################################################################################
# 93_DbRep.pm
#
@ -41,8 +41,8 @@ package main;
use strict;
use warnings;
use POSIX qw(strftime);
use Time::HiRes qw(gettimeofday tv_interval);
use POSIX qw(strftime SIGALRM);
use Time::HiRes qw(gettimeofday tv_interval ualarm);
use Scalar::Util qw(looks_like_number);
eval "use DBI;1" or my $DbRepMMDBI = "DBI";
eval "use FHEM::Meta;1" or my $modMetaAbsent = 1;
@ -57,6 +57,8 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
# Version History intern
our %DbRep_vNotesIntern = (
"8.40.7" => "03.09.2020 consider attr timeout in function DbRep_dbValue (blocking function) ",
"8.40.6" => "27.08.2020 commandRef revised ",
"8.40.5" => "29.07.2020 fix crash if delEntries startet without any time limits, Forum:#113202 ",
"8.40.4" => "23.07.2020 new aggregation value 'minute', some fixes ",
"8.40.3" => "22.07.2020 delete prototypes ",
@ -11487,12 +11489,12 @@ sub DbRep_setVersionInfo {
if($modules{$type}{META}{x_prereqs_src} && !$hash->{HELPER}{MODMETAABSENT}) {
# META-Daten sind vorhanden
$modules{$type}{META}{version} = "v".$v; # Version aus META.json überschreiben, Anzeige mit {Dumper $modules{SMAPortal}{META}}
if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id: 93_DbRep.pm 22455 2020-07-23 21:09:07Z DS_Starter $ im Kopf komplett! vorhanden )
if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id: 93_DbRep.pm 22678 2020-08-27 17:05:24Z DS_Starter $ im Kopf komplett! vorhanden )
$modules{$type}{META}{x_version} =~ s/1.1.1/$v/g;
} else {
$modules{$type}{META}{x_version} = $v;
}
return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbRep.pm 22455 2020-07-23 21:09:07Z DS_Starter $ im Kopf komplett! vorhanden )
return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbRep.pm 22678 2020-08-27 17:05:24Z DS_Starter $ im Kopf komplett! vorhanden )
if(__PACKAGE__ eq "FHEM::$type" || __PACKAGE__ eq $type) {
# es wird mit Packages gearbeitet -> Perl übliche Modulversion setzen
# mit {<Modul>->VERSION()} im FHEMWEB kann Modulversion abgefragt werden
@ -11511,15 +11513,19 @@ return;
# liefert Ergebnis sofort zurück, setzt keine Readings
####################################################################################################
sub DbRep_dbValue {
my ($name,$cmd) = @_;
my $name = shift;
my $cmd = shift;
my $hash = $defs{$name};
my $dbloghash = $defs{$hash->{HELPER}{DBLOGDEVICE}};
my $dbconn = $dbloghash->{dbconn};
my $dbuser = $dbloghash->{dbuser};
my $dblogname = $dbloghash->{NAME};
my $dbpassword = $attr{"sec$dblogname"}{secret};
my $utf8 = defined($hash->{UTF8})?$hash->{UTF8}:0;
my $utf8 = $hash->{UTF8} // 0;
my $srs = AttrVal($name, "sqlResultFieldSep", "|" );
my $to = AttrVal($name, "timeout", 86400);
my ($err,$ret,$dbh);
readingsDelete ($hash, "errortext");
@ -11532,21 +11538,18 @@ sub DbRep_dbValue {
Log3 ($name, 2, "DbRep $name - $err");
ReadingsSingleUpdateValue ($hash, "errortext", $err, 1);
ReadingsSingleUpdateValue ($hash, "state", "error", 1);
return ($err);
return $err;
}
my $sql = ($cmd =~ m/\;$/)?$cmd:$cmd.";";
my $sql = ($cmd =~ m/\;$/xs) ? $cmd : $cmd.";";
# Ausgaben
Log3 ($name, 4, "DbRep $name - -------- New selection --------- ");
Log3 ($name, 4, "DbRep $name - Command: dbValue");
Log3 ($name, 4, "DbRep $name - SQL execute: $sql");
# split SQL-Parameter Statement falls mitgegeben
# z.B. SET @open:=NULL, @closed:=NULL; Select ...
my $set;
if($cmd =~ /^SET.*;/i) {
$cmd =~ m/^(SET.*?;)(.*)/i;
if($cmd =~ /^SET.*;/i) { # split SQL-Parameter Statement falls mitgegeben ->
$cmd =~ m/^(SET.*?;)(.*)/i; # z.B. SET @open:=NULL, @closed:=NULL; Select ...
$set = $1;
$sql = $2;
}
@ -11555,6 +11558,7 @@ sub DbRep_dbValue {
Log3($name, 4, "DbRep $name - Set SQL session variables: $set");
eval {$dbh->do($set);}; # @\RB = Resetbit wenn neues Selektionsintervall beginnt
}
if ($@) {
$err = $@;
Log3 ($name, 2, "DbRep $name - $err");
@ -11563,21 +11567,45 @@ sub DbRep_dbValue {
return ($err);
}
# SQL-Startzeit
my $st = [gettimeofday];
my $st = [gettimeofday]; # SQL-Startzeit
my ($sth,$r);
eval {$sth = $dbh->prepare($sql);
my $totxt = qq{Timeout occured (limit: $to seconds). You may be able to adjust the "Timeout" attribute.};
my ($sth,$r,$failed);
eval { # outer eval fängt Alarm auf, der gerade vor diesem Alarm feuern könnte(0)
POSIX::sigaction(SIGALRM, POSIX::SigAction->new(sub {die "Timeout\n"})); # \n ist nötig !
alarm($to);
eval {
$sth = $dbh->prepare($sql);
$r = $sth->execute();
1;
};
alarm(0); # Alarm aufheben (wenn der Code schnell lief)
if ($@) {
$err = $@;
if($@ eq "Timeout\n") { # timeout
$failed = $totxt;
} else { # ein anderer Fehler
$failed = $@;
}
}
1;
} or $failed = $@;
alarm(0); # Schutz vor Race Condition
if ($failed) {
$err = $failed eq "Timeout\n" ? $totxt : $failed;
Log3 ($name, 2, "DbRep $name - $err");
$sth->finish if($sth);
$dbh->disconnect;
ReadingsSingleUpdateValue ($hash, "errortext", $err, 1);
ReadingsSingleUpdateValue ($hash, "state", "error", 1);
return ($err);
return $err;
}
my $nrows = 0;
@ -11586,8 +11614,7 @@ sub DbRep_dbValue {
Log3 ($name, 4, "DbRep $name - SQL result: @line");
$ret .= "\n" if($nrows); # Forum: #103295
$ret .= join("$srs", @line);
# Anzahl der Datensätze
$nrows++;
$nrows++; # Anzahl der Datensätze
}
} else {
@ -11599,7 +11626,7 @@ sub DbRep_dbValue {
$dbh->disconnect;
ReadingsSingleUpdateValue ($hash, "errortext", $err, 1);
ReadingsSingleUpdateValue ($hash, "state", "error", 1);
return ($err);
return $err;
}
$ret = $nrows;
}
@ -11607,18 +11634,16 @@ sub DbRep_dbValue {
$sth->finish;
$dbh->disconnect;
# SQL-Laufzeit ermitteln
my $rt = tv_interval($st);
my $rt = tv_interval($st); # SQL-Laufzeit ermitteln
my $com = (split(" ",$sql, 2))[0];
Log3 ($name, 4, "DbRep $name - Number of entries processed in db $hash->{DATABASE}: $nrows by $com");
# Readingaufbereitung
readingsBeginUpdate ($hash);
ReadingsBulkUpdateTimeState ($hash,undef,$rt,"done");
readingsEndUpdate ($hash, 1);
return ($ret);
return $ret;
}
####################################################################################################
@ -12497,7 +12522,7 @@ return;
<b>Note: <br>
To avoid FHEM from blocking, you have to operate DbLog in asynchronous mode if the table
optimization want to be used ! </b> <br><br>
optimization is used ! </b> <br><br>
After the dump a FHEM-command can be executed as well (see attribute "executeAfterProc"). <br><br>
@ -12518,7 +12543,7 @@ return;
The target directory can be set by <a href="#DbRepattr">attribute</a> "dumpDirRemote".
It must be located on the MySQL-Host and has to be writable by the MySQL-server process. <br>
The used database user must have the "FILE"-privilege. <br><br>
The used database user must have the <b>FILE</b> privilege (see <a href="https://wiki.fhem.de/wiki/DbRep_-_Reporting_und_Management_von_DbLog-Datenbankinhalten#3._Backup_durchf.C3.BChren_2">Wiki</a>). <br><br>
<b>Note:</b> <br>
If the internal version management of DbRep should be used and the size of the created dumpfile be
@ -13065,6 +13090,7 @@ return;
<br><br>
<b>Usage of clientSide-Dumps </b> <br>
The used database user needs the <b>FILE</b> privilege (see <a href="https://wiki.fhem.de/wiki/DbRep_-_Reporting_und_Management_von_DbLog-Datenbankinhalten#4._Restore_2">Wiki</a>). <br>
All tables and views (if present) are restored.
The directory which contains the dump files has to be set by attribute <a href="#dumpDirLocal">dumpDirLocal</a>
to make it usable by the DbRep device. <br>
@ -15088,7 +15114,7 @@ sub bdump {
Das Zielverzeichnis kann mit dem <a href="#DbRepattr">Attribut</a> "dumpDirRemote" verändert werden.
Es muß sich auf dem MySQL-Host gefinden und durch den MySQL-Serverprozess beschreibbar sein. <br>
Der verwendete Datenbankuser benötigt das "FILE"-Privileg. <br><br>
Der verwendete Datenbankuser benötigt das <b>FILE</b> Privileg (siehe <a href="https://wiki.fhem.de/wiki/DbRep_-_Reporting_und_Management_von_DbLog-Datenbankinhalten#3._Backup_durchf.C3.BChren_2">Wiki</a>). <br><br>
<b>Hinweis:</b> <br>
Soll die interne Versionsverwaltung und die Dumpfilekompression des Moduls genutzt, sowie die Größe des erzeugten
@ -15646,6 +15672,7 @@ sub bdump {
Die Funktion stellt über eine Drop-Down Liste eine Dateiauswahl für den Restore zur Verfügung. <br><br>
<b>Verwendung eines serverSide-Dumps </b> <br>
Der verwendete Datenbankuser benötigt das <b>FILE</b> Privileg (siehe <a href="https://wiki.fhem.de/wiki/DbRep_-_Reporting_und_Management_von_DbLog-Datenbankinhalten#4._Restore_2">Wiki</a>). <br>
Es wird der Inhalt der history-Tabelle aus einem serverSide-Dump wiederhergestellt.
Dazu ist das Verzeichnis "dumpDirRemote" des MySQL-Servers auf dem Client zu mounten
und im Attribut <a href="#dumpDirLocal">dumpDirLocal</a> dem DbRep-Device bekannt zu machen. <br>