mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-22 20:24:36 +00:00
93_DbRep: improve 'restore' setlist, revised comRef
git-svn-id: https://svn.fhem.de/fhem/trunk@21965 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
4582675dc6
commit
2a4f35d114
@ -1,5 +1,6 @@
|
|||||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||||
# Do not insert empty lines here, update check depends on it.
|
# Do not insert empty lines here, update check depends on it.
|
||||||
|
- change: 93_DbRep: improve 'restore' setlist, revised comRef
|
||||||
- feature: 82_LGTV_WebOS: add DuplexIPTV App support
|
- feature: 82_LGTV_WebOS: add DuplexIPTV App support
|
||||||
- feature: 00_RSS: new img type SVG (forum #111271)
|
- feature: 00_RSS: new img type SVG (forum #111271)
|
||||||
- bugfix: 73_AutoShuttersControl: fix bug after privacyDown and open window
|
- bugfix: 73_AutoShuttersControl: fix bug after privacyDown and open window
|
||||||
|
@ -58,6 +58,7 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
|
|||||||
|
|
||||||
# Version History intern
|
# Version History intern
|
||||||
our %DbRep_vNotesIntern = (
|
our %DbRep_vNotesIntern = (
|
||||||
|
"8.40.1" => "18.05.2020 improve 'restore' setlist, revised comRef, fix compare timesettings for delEntries,reduceLog ",
|
||||||
"8.40.0" => "30.03.2020 new attribute 'autoForward' ",
|
"8.40.0" => "30.03.2020 new attribute 'autoForward' ",
|
||||||
"8.39.0" => "28.03.2020 option 'writeToDBInTime' for function 'sumValue' and 'averageValue' ",
|
"8.39.0" => "28.03.2020 option 'writeToDBInTime' for function 'sumValue' and 'averageValue' ",
|
||||||
"8.38.0" => "21.03.2020 sqlSpecial readingsDifferenceByTimeDelta, fix FHEM crash if no time-attribute is set and time ".
|
"8.38.0" => "21.03.2020 sqlSpecial readingsDifferenceByTimeDelta, fix FHEM crash if no time-attribute is set and time ".
|
||||||
@ -541,12 +542,12 @@ sub DbRep_Set($@) {
|
|||||||
opendir(DIR,$dir);
|
opendir(DIR,$dir);
|
||||||
if ($dbmodel =~ /MYSQL/) {
|
if ($dbmodel =~ /MYSQL/) {
|
||||||
$dbname = $hash->{DATABASE};
|
$dbname = $hash->{DATABASE};
|
||||||
$sd = $dbname.".*(csv|sql)";
|
$sd = $dbname."_.*?(csv|sql)";
|
||||||
} elsif ($dbmodel =~ /SQLITE/) {
|
} elsif ($dbmodel =~ /SQLITE/) {
|
||||||
$dbname = $hash->{DATABASE};
|
$dbname = $hash->{DATABASE};
|
||||||
$dbname = (split /[\/]/, $dbname)[-1];
|
$dbname = (split /[\/]/, $dbname)[-1];
|
||||||
$dbname = (split /\./, $dbname)[0];
|
$dbname = (split /\./, $dbname)[0];
|
||||||
$sd = $dbname."_.*.sqlitebkp";
|
$sd = $dbname."_.*?.sqlitebkp";
|
||||||
}
|
}
|
||||||
while (my $file = readdir(DIR)) {
|
while (my $file = readdir(DIR)) {
|
||||||
next unless (-f "$dir/$file");
|
next unless (-f "$dir/$file");
|
||||||
@ -807,7 +808,9 @@ sub DbRep_Set($@) {
|
|||||||
return " Set attribute 'allowDeletion' if you want to allow deletion of any database entries. Use it with care !";
|
return " Set attribute 'allowDeletion' if you want to allow deletion of any database entries. Use it with care !";
|
||||||
}
|
}
|
||||||
delete $hash->{HELPER}{DELENTRIES};
|
delete $hash->{HELPER}{DELENTRIES};
|
||||||
$hash->{HELPER}{DELENTRIES} = \@a;
|
shift @a;
|
||||||
|
shift @a;
|
||||||
|
$hash->{HELPER}{DELENTRIES} = \@a if(@a);
|
||||||
DbRep_beforeproc($hash, "delEntries");
|
DbRep_beforeproc($hash, "delEntries");
|
||||||
DbRep_Main($hash,$opt);
|
DbRep_Main($hash,$opt);
|
||||||
|
|
||||||
@ -1843,7 +1846,9 @@ sub DbRep_dbConnect($$) {
|
|||||||
AutoCommit => 1,
|
AutoCommit => 1,
|
||||||
AutoInactiveDestroy => 1,
|
AutoInactiveDestroy => 1,
|
||||||
mysql_enable_utf8 => $utf8
|
mysql_enable_utf8 => $utf8
|
||||||
} ); };
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
if ($@) {
|
if ($@) {
|
||||||
$err = $@;
|
$err = $@;
|
||||||
@ -2040,7 +2045,7 @@ sub DbRep_Main($$;$) {
|
|||||||
my ($yyyy2, $mm2, $dd2, $hh2, $min2, $sec2) = ($runtime_string_next =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/);
|
my ($yyyy2, $mm2, $dd2, $hh2, $min2, $sec2) = ($runtime_string_next =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/);
|
||||||
my $nthants = timelocal($sec1, $min1, $hh1, $dd1, $mm1-1, $yyyy1-1900);
|
my $nthants = timelocal($sec1, $min1, $hh1, $dd1, $mm1-1, $yyyy1-1900);
|
||||||
my $othants = timelocal($sec2, $min2, $hh2, $dd2, $mm2-1, $yyyy2-1900);
|
my $othants = timelocal($sec2, $min2, $hh2, $dd2, $mm2-1, $yyyy2-1900);
|
||||||
if($nthants >= $othants) {
|
if($nthants > $othants) {
|
||||||
ReadingsSingleUpdateValue ($hash, "state", "Error - Wrong time limits. The <nn> (days newer than) option must be greater than the <no> (older than) one !", 1);
|
ReadingsSingleUpdateValue ($hash, "state", "Error - Wrong time limits. The <nn> (days newer than) option must be greater than the <no> (older than) one !", 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2139,7 +2144,7 @@ sub DbRep_Main($$;$) {
|
|||||||
my ($yyyy2, $mm2, $dd2, $hh2, $min2, $sec2) = ($runtime_string_next =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/);
|
my ($yyyy2, $mm2, $dd2, $hh2, $min2, $sec2) = ($runtime_string_next =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/);
|
||||||
my $nthants = timelocal($sec1, $min1, $hh1, $dd1, $mm1-1, $yyyy1-1900);
|
my $nthants = timelocal($sec1, $min1, $hh1, $dd1, $mm1-1, $yyyy1-1900);
|
||||||
my $othants = timelocal($sec2, $min2, $hh2, $dd2, $mm2-1, $yyyy2-1900);
|
my $othants = timelocal($sec2, $min2, $hh2, $dd2, $mm2-1, $yyyy2-1900);
|
||||||
if($nthants >= $othants) {
|
if($nthants > $othants) {
|
||||||
ReadingsSingleUpdateValue ($hash, "state", "Error - Wrong time limits. The <nn> (days newer than) option must be greater than the <no> (older than) one !", 1);
|
ReadingsSingleUpdateValue ($hash, "state", "Error - Wrong time limits. The <nn> (days newer than) option must be greater than the <no> (older than) one !", 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -4347,18 +4352,12 @@ sub del_DoParse($) {
|
|||||||
# Background-Startzeit
|
# Background-Startzeit
|
||||||
my $bst = [gettimeofday];
|
my $bst = [gettimeofday];
|
||||||
|
|
||||||
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoCommit => 1, AutoInactiveDestroy => 1 });};
|
|
||||||
|
|
||||||
if ($@) {
|
|
||||||
$err = encode_base64($@,"");
|
|
||||||
Log3 ($name, 2, "DbRep $name - $@");
|
|
||||||
return "$name|''|''|$err|''|''|''";
|
|
||||||
}
|
|
||||||
|
|
||||||
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
|
# ist Zeiteingrenzung und/oder Aggregation gesetzt ? (wenn ja -> "?" in SQL sonst undef)
|
||||||
my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
|
my ($IsTimeSet,$IsAggrSet) = DbRep_checktimeaggr($hash);
|
||||||
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
|
Log3 ($name, 5, "DbRep $name - IsTimeSet: $IsTimeSet, IsAggrSet: $IsAggrSet");
|
||||||
|
|
||||||
|
BlockingInformParent("DbRep_delHashValFromBlocking", [$name, "HELPER","DELENTRIES"], 1);
|
||||||
|
|
||||||
# SQL zusammenstellen für DB-Operation
|
# SQL zusammenstellen für DB-Operation
|
||||||
if ($IsTimeSet || $IsAggrSet) {
|
if ($IsTimeSet || $IsAggrSet) {
|
||||||
$sql = DbRep_createDeleteSql($hash,$table,$device,$reading,$runtime_string_first,$runtime_string_next,'');
|
$sql = DbRep_createDeleteSql($hash,$table,$device,$reading,$runtime_string_first,$runtime_string_next,'');
|
||||||
@ -4366,6 +4365,14 @@ sub del_DoParse($) {
|
|||||||
$sql = DbRep_createDeleteSql($hash,$table,$device,$reading,undef,undef,'');
|
$sql = DbRep_createDeleteSql($hash,$table,$device,$reading,undef,undef,'');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoCommit => 1, AutoInactiveDestroy => 1 });};
|
||||||
|
|
||||||
|
if ($@) {
|
||||||
|
$err = encode_base64($@,"");
|
||||||
|
Log3 ($name, 2, "DbRep $name - $@");
|
||||||
|
return "$name|''|''|$err|''|''|''";
|
||||||
|
}
|
||||||
|
|
||||||
$sth = $dbh->prepare($sql);
|
$sth = $dbh->prepare($sql);
|
||||||
|
|
||||||
Log3 ($name, 4, "DbRep $name - SQL execute: $sql");
|
Log3 ($name, 4, "DbRep $name - SQL execute: $sql");
|
||||||
@ -8263,7 +8270,7 @@ sub mysql_RestoreClientSide($) {
|
|||||||
my $bst = [gettimeofday];
|
my $bst = [gettimeofday];
|
||||||
|
|
||||||
# Verbindung mit DB
|
# Verbindung mit DB
|
||||||
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoCommit => 1 });};
|
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoInactiveDestroy => 1, AutoCommit => 1 });};
|
||||||
if ($@) {
|
if ($@) {
|
||||||
$e = $@;
|
$e = $@;
|
||||||
$err = encode_base64($e,"");
|
$err = encode_base64($e,"");
|
||||||
@ -8498,7 +8505,7 @@ sub DbRep_syncStandby($) {
|
|||||||
my $bst = [gettimeofday];
|
my $bst = [gettimeofday];
|
||||||
|
|
||||||
# Verbindung zur Quell-DB
|
# Verbindung zur Quell-DB
|
||||||
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoCommit => 1, mysql_enable_utf8 => $utf8 });};
|
eval {$dbh = DBI->connect("dbi:$dbconn", $dbuser, $dbpassword, { PrintError => 0, RaiseError => 1, AutoCommit => 1, AutoInactiveDestroy => 1, mysql_enable_utf8 => $utf8 });};
|
||||||
if ($@) {
|
if ($@) {
|
||||||
$err = encode_base64($@,"");
|
$err = encode_base64($@,"");
|
||||||
Log3 ($name, 2, "DbRep $name - $@");
|
Log3 ($name, 2, "DbRep $name - $@");
|
||||||
@ -12568,7 +12575,7 @@ return;
|
|||||||
<table>
|
<table>
|
||||||
<colgroup> <col width=5%> <col width=95%> </colgroup>
|
<colgroup> <col width=5%> <col width=95%> </colgroup>
|
||||||
<tr><td> dumpCompress </td><td>: compress of dump files after creation </td></tr>
|
<tr><td> dumpCompress </td><td>: compress of dump files after creation </td></tr>
|
||||||
<tr><td> dumpDirLocal </td><td>: the local mounted directory dumpDirRemote </td></tr>
|
<tr><td> dumpDirLocal </td><td>: Target directory of the dumpfiles </td></tr>
|
||||||
<tr><td> dumpFilesKeep </td><td>: number of dump files to keep </td></tr>
|
<tr><td> dumpFilesKeep </td><td>: number of dump files to keep </td></tr>
|
||||||
<tr><td> executeBeforeProc </td><td>: execution of FHEM command (or Perl-routine) before dump </td></tr>
|
<tr><td> executeBeforeProc </td><td>: execution of FHEM command (or Perl-routine) before dump </td></tr>
|
||||||
<tr><td> executeAfterProc </td><td>: execution of FHEM command (or Perl-routine) after dump </td></tr>
|
<tr><td> executeAfterProc </td><td>: execution of FHEM command (or Perl-routine) after dump </td></tr>
|
||||||
@ -13020,16 +13027,16 @@ return;
|
|||||||
<b>Usage of serverSide-Dumps </b> <br>
|
<b>Usage of serverSide-Dumps </b> <br>
|
||||||
The content of history-table will be restored from a serverSide-Dump.
|
The content of history-table will be restored from a serverSide-Dump.
|
||||||
Therefore the remote directory "dumpDirRemote" of the MySQL-Server has to be mounted on the
|
Therefore the remote directory "dumpDirRemote" of the MySQL-Server has to be mounted on the
|
||||||
Client and make it usable to the DbRep-device by setting <a href="#DbRepattr">attribute</a>
|
Client and make it usable to the DbRep device by setting attribute <a href="#dumpDirLocal">dumpDirLocal</a>
|
||||||
"dumpDirLocal" to the appropriate value. <br>
|
to the appropriate value. <br>
|
||||||
All files with extension "csv[.gzip]" and if the filename is beginning with the name of the connected database
|
All files with extension "csv[.gzip]" and if the filename is beginning with the name of the connected database
|
||||||
(see Internal DATABASE) are listed.
|
(see Internal DATABASE) are listed.
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
<b>Usage of clientSide-Dumps </b> <br>
|
<b>Usage of clientSide-Dumps </b> <br>
|
||||||
All tables and views (if present) are restored.
|
All tables and views (if present) are restored.
|
||||||
The directory which contains the dump files has to be set by <a href="#DbRepattr">attribute</a>
|
The directory which contains the dump files has to be set by attribute <a href="#dumpDirLocal">dumpDirLocal</a>
|
||||||
"dumpDirLocal" to make it usable by the DbRep device. <br>
|
to make it usable by the DbRep device. <br>
|
||||||
All files with extension "sql[.gzip]" and if the filename is beginning with the name of the connected database
|
All files with extension "sql[.gzip]" and if the filename is beginning with the name of the connected database
|
||||||
(see Internal DATABASE) are listed. <br>
|
(see Internal DATABASE) are listed. <br>
|
||||||
The restore speed depends of the server variable "<b>max_allowed_packet</b>". You can change
|
The restore speed depends of the server variable "<b>max_allowed_packet</b>". You can change
|
||||||
@ -13620,11 +13627,11 @@ return $ret;
|
|||||||
<li><b>dumpCompress </b> - if set, the dump files are compressed after operation of "dumpMySQL" bzw. "dumpSQLite" </li> <br>
|
<li><b>dumpCompress </b> - if set, the dump files are compressed after operation of "dumpMySQL" bzw. "dumpSQLite" </li> <br>
|
||||||
|
|
||||||
<a name="dumpDirLocal"></a>
|
<a name="dumpDirLocal"></a>
|
||||||
<li><b>dumpDirLocal </b> - Target directory of database dumps by command "dumpMySQL clientSide"
|
<li><b>dumpDirLocal </b> - Target directory of database dumps by command "dumpMySQL clientSide" or "dumpSQLite"
|
||||||
(default: "{global}{modpath}/log/" on the FHEM-Server). <br>
|
(default: "{global}{modpath}/log/" on the FHEM-Server). <br>
|
||||||
In this directory also the internal version administration searches for old backup-files
|
In this directory also the internal version administration searches for old backup-files
|
||||||
and deletes them if the number exceeds attribute "dumpFilesKeep".
|
and deletes them if the number exceeds attribute "dumpFilesKeep".
|
||||||
The attribute is also relevant to publish a local mounted directory "dumpDirRemote" to
|
The attribute is also relevant to publish a local mounted directory "dumpDirRemote" (dumpMySQL serverSide) to
|
||||||
DbRep. </li> <br>
|
DbRep. </li> <br>
|
||||||
|
|
||||||
<a name="dumpDirRemote"></a>
|
<a name="dumpDirRemote"></a>
|
||||||
@ -15137,7 +15144,7 @@ sub bdump {
|
|||||||
<table>
|
<table>
|
||||||
<colgroup> <col width=5%> <col width=95%> </colgroup>
|
<colgroup> <col width=5%> <col width=95%> </colgroup>
|
||||||
<tr><td> dumpCompress </td><td>: Komprimierung des Dumpfiles nach der Erstellung </td></tr>
|
<tr><td> dumpCompress </td><td>: Komprimierung des Dumpfiles nach der Erstellung </td></tr>
|
||||||
<tr><td> dumpDirLocal </td><td>: Directory des lokal gemounteten dumpDirRemote-Verzeichnisses </td></tr>
|
<tr><td> dumpDirLocal </td><td>: Zielverzeichnis der Dumpfiles </td></tr>
|
||||||
<tr><td> dumpFilesKeep </td><td>: Anzahl der aufzubwahrenden Dumpfiles </td></tr>
|
<tr><td> dumpFilesKeep </td><td>: Anzahl der aufzubwahrenden Dumpfiles </td></tr>
|
||||||
<tr><td> executeBeforeProc </td><td>: ausführen FHEM Kommando (oder Perl-Routine) vor dem Dump </td></tr>
|
<tr><td> executeBeforeProc </td><td>: ausführen FHEM Kommando (oder Perl-Routine) vor dem Dump </td></tr>
|
||||||
<tr><td> executeAfterProc </td><td>: ausführen FHEM Kommando (oder Perl-Routine) nach dem Dump </td></tr>
|
<tr><td> executeAfterProc </td><td>: ausführen FHEM Kommando (oder Perl-Routine) nach dem Dump </td></tr>
|
||||||
@ -15610,14 +15617,14 @@ sub bdump {
|
|||||||
<b>Verwendung eines serverSide-Dumps </b> <br>
|
<b>Verwendung eines serverSide-Dumps </b> <br>
|
||||||
Es wird der Inhalt der history-Tabelle aus einem serverSide-Dump wiederhergestellt.
|
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
|
Dazu ist das Verzeichnis "dumpDirRemote" des MySQL-Servers auf dem Client zu mounten
|
||||||
und im <a href="#DbRepattr">Attribut</a> "dumpDirLocal" dem DbRep-Device bekannt zu machen. <br>
|
und im Attribut <a href="#dumpDirLocal">dumpDirLocal</a> dem DbRep-Device bekannt zu machen. <br>
|
||||||
Es werden alle Files mit der Endung "csv[.gzip]" und deren Name mit der
|
Es werden alle Files mit der Endung "csv[.gzip]" und deren Name mit der
|
||||||
verbundenen Datenbank beginnt (siehe Internal DATABASE), aufgelistet.
|
verbundenen Datenbank beginnt (siehe Internal DATABASE), aufgelistet.
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
<b>Verwendung eines clientSide-Dumps </b> <br>
|
<b>Verwendung eines clientSide-Dumps </b> <br>
|
||||||
Es werden alle Tabellen und eventuell vorhandenen Views wiederhergestellt.
|
Es werden alle Tabellen und eventuell vorhandenen Views wiederhergestellt.
|
||||||
Das Verzeichnis, in dem sich die Dump-Files befinden, ist im <a href="#DbRepattr">Attribut</a> "dumpDirLocal" dem
|
Das Verzeichnis, in dem sich die Dump-Files befinden, ist im Attribut <a href="#dumpDirLocal">dumpDirLocal</a> dem
|
||||||
DbRep-Device bekannt zu machen. <br>
|
DbRep-Device bekannt zu machen. <br>
|
||||||
Es werden alle Files mit der Endung "sql[.gzip]" und deren Name mit der
|
Es werden alle Files mit der Endung "sql[.gzip]" und deren Name mit der
|
||||||
verbundenen Datenbank beginnt (siehe Internal DATABASE), aufgelistet. <br>
|
verbundenen Datenbank beginnt (siehe Internal DATABASE), aufgelistet. <br>
|
||||||
@ -16224,11 +16231,11 @@ return $ret;
|
|||||||
<li><b>dumpCompress </b> - wenn gesetzt, werden die Dumpfiles nach "dumpMySQL" bzw. "dumpSQLite" komprimiert </li> <br>
|
<li><b>dumpCompress </b> - wenn gesetzt, werden die Dumpfiles nach "dumpMySQL" bzw. "dumpSQLite" komprimiert </li> <br>
|
||||||
|
|
||||||
<a name="dumpDirLocal"></a>
|
<a name="dumpDirLocal"></a>
|
||||||
<li><b>dumpDirLocal </b> - Zielverzeichnis für die Erstellung von Dumps mit "dumpMySQL clientSide".
|
<li><b>dumpDirLocal </b> - Zielverzeichnis für die Erstellung von Dumps mit "dumpMySQL clientSide" oder "dumpSQLite".
|
||||||
default: "{global}{modpath}/log/" auf dem FHEM-Server. <br>
|
default: "{global}{modpath}/log/" auf dem FHEM-Server. <br>
|
||||||
Ebenfalls werden in diesem Verzeichnis alte Backup-Files durch die interne Versionsverwaltung von
|
Ebenfalls werden in diesem Verzeichnis alte Backup-Files durch die interne Versionsverwaltung
|
||||||
"dumpMySQL" gesucht und gelöscht wenn die gefundene Anzahl den Attributwert "dumpFilesKeep"
|
gesucht und gelöscht wenn die gefundene Anzahl den Attributwert "dumpFilesKeep"
|
||||||
überschreitet. Das Attribut dient auch dazu ein lokal gemountetes Verzeichnis "dumpDirRemote"
|
überschreitet. Das Attribut dient auch dazu ein lokal gemountetes Verzeichnis "dumpDirRemote" (bei dumpMySQL serverSide)
|
||||||
DbRep bekannt zu machen. </li> <br>
|
DbRep bekannt zu machen. </li> <br>
|
||||||
|
|
||||||
<a name="dumpDirRemote"></a>
|
<a name="dumpDirRemote"></a>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user