diff --git a/AN/Tools.pm b/AN/Tools.pm index cfc85f01..8b3362fe 100755 --- a/AN/Tools.pm +++ b/AN/Tools.pm @@ -19,6 +19,7 @@ my $THIS_FILE = "Tools.pm"; ### Methods; # data # environment +# nice_exit # _add_hash_reference # _hostname # _make_hash_reference @@ -127,7 +128,14 @@ sub new UUID => "", }, sys => { + database => { + local_lock_active => 0, + locking_reap_age => 300, + log_transactions => 0, + maximum_batch_size => 25000, + }, host_type => "", + use_base2 => 1, }, }; @@ -283,6 +291,32 @@ sub environment return ($an->{ENV_VALUES}{ENVIRONMENT}); } +=head2 nice_exit + +This is a simple method to exit cleanly, closing database connections and exiting with the set exit code. + +Parameters; + +=head3 exit_code (optional) + +If set, this will be the exit code. The default is to exit with code C<< 0 >>. + +=cut +sub nice_exit +{ + my $self = shift; + my $parameter = shift; + my $an = $self; + + my $exit_code = defined $parameter->{exit_code} ? $parameter->{exit_code} : 0; + + # Close database connections (if any). + $an->Database->disconnect(); + + exit($exit_code); +} + + ############################################################################################################# # Public methods used to access sub modules. # ############################################################################################################# @@ -608,16 +642,16 @@ sub _set_paths # Executables $an->data->{path} = { - configs => { + configs => { 'pg_hba.conf' => "/var/lib/pgsql/data/pg_hba.conf", 'postgresql.conf' => "/var/lib/pgsql/data/postgresql.conf", ssh_config => "/etc/ssh/ssh_config", 'striker.conf' => "/etc/striker/striker.conf", }, - data => { + data => { passwd => "/etc/passwd", }, - directories => { + directories => { backups => "/usr/sbin/striker/backups", 'cgi-bin' => "/var/www/cgi-bin", html => "/var/www/html", @@ -625,7 +659,8 @@ sub _set_paths tools => "/usr/sbin/striker", units => "/usr/lib/systemd/system", }, - exe => { + exe => { + 'an-report-memory' => "/usr/sbin/an-report-memory", 'chmod' => "/usr/bin/chmod", 'chown' => "/usr/bin/chown", cp => "/usr/bin/cp", @@ -640,12 +675,16 @@ sub _set_paths logger => "/usr/bin/logger", 'mkdir' => "/usr/bin/mkdir", ping => "/usr/bin/ping", + pgrep => "/usr/bin/pgrep", psql => "/usr/bin/psql", 'postgresql-setup' => "/usr/bin/postgresql-setup", su => "/usr/bin/su", systemctl => "/usr/bin/systemctl", uuidgen => "/usr/bin/uuidgen", }, + 'lock' => { + database => "/tmp/an-tools.database.lock", + }, secure => { postgres_pgpass => "/var/lib/pgsql/.pgpass", }, diff --git a/AN/Tools/Alert.pm b/AN/Tools/Alert.pm index 7d96fc55..a6d2e019 100755 --- a/AN/Tools/Alert.pm +++ b/AN/Tools/Alert.pm @@ -72,7 +72,7 @@ sub parent This is used by scan agents that need to track whether an alert was sent when a sensor dropped below/rose above a set alert threshold. For example, if a sensor alerts at 20°C and clears at 25°C, this will be called when either value is passed. When passing the warning threshold, the alert is registered and sent to the user. Once set, no further warning alerts are sent. When the value passes over the clear threshold, this is checked and if an alert was previously registered, it is removed and an "all clear" message is sent. In this way, multiple alerts will not go out if a sensor floats around the warning threshold and a "cleared" message won't be sent unless a "warning" message was previously sent. -If there is a problem, C<< undef >> is returned. +If there is a problem, C<< !!error!! >> is returned. Parameters; @@ -125,7 +125,7 @@ sub check_alert_sent { # Nope $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0093"}); - return(undef); + return("!!error!!"); } # Do we have an alert name? @@ -133,7 +133,7 @@ sub check_alert_sent { # Nope $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->check_alert_sent()", parameter => "name" }}); - return(undef); + return("!!error!!"); } # Do we have an record locator? @@ -141,7 +141,7 @@ sub check_alert_sent { # Nope $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->check_alert_sent()", parameter => "record_locator" }}); - return(undef); + return("!!error!!"); } # Do we know who is setting this?? @@ -149,7 +149,7 @@ sub check_alert_sent { # Nope $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->check_alert_sent()", parameter => "set_by" }}); - return(undef); + return("!!error!!"); } # Are we setting or clearing? @@ -157,7 +157,7 @@ sub check_alert_sent { # Neither... $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0097"}); - return(undef); + return("!!error!!"); } # This will get set to '1' if an alert is added or removed. @@ -218,7 +218,7 @@ WHERE alert_name => $name, modified_date => $modified_date, }}); - return(undef); + return("!!error!!"); } else { @@ -282,7 +282,7 @@ AND This registers an alert to be sent later. -If anything goes wrong, C<< undef >> will be returned. +If anything goes wrong, C<< !!error!! >> will be returned. =cut sub register_alert @@ -313,17 +313,17 @@ sub register_alert if (not $set_by) { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->register_alert()", parameter => "set_by" }}); - return(undef); + return("!!error!!"); } if (not $message_key) { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Alert->register_alert()", parameter => "message_key" }}); - return(undef); + return("!!error!!"); } if (($header) && (not $title_key)) { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0101"}); - return(undef); + return("!!error!!"); } # zero-pad sort numbers so that they sort properly. diff --git a/AN/Tools/Convert.pm b/AN/Tools/Convert.pm index f5032ffc..d596b876 100755 --- a/AN/Tools/Convert.pm +++ b/AN/Tools/Convert.pm @@ -6,13 +6,19 @@ package AN::Tools::Convert; use strict; use warnings; use Data::Dumper; +use Math::BigInt; our $VERSION = "3.0.0"; my $THIS_FILE = "Convert.pm"; ### Methods; +# add_commas +# bytes_to_human_readable # cidr # hostname_to_ip +# human_readable_to_bytes +# round + =pod @@ -68,6 +74,404 @@ sub parent # Public methods # ############################################################################################################# +=head2 add_commas + +This takes an integer and inserts commas to make it more readable by people. + +If the input string isn't a string of digits, it is simply returned as-is. + +Parameters; + +=head3 number (required) + +This is the number to add commas to. + +=cut +sub add_commas +{ + my $self = shift; + my $parameter = shift; + my $an = $self->parent; + + # Now see if the user passed the values in a hash reference or directly. + my $number = defined $parameter->{number} ? $parameter->{number} : ""; + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { number => $number }}); + + # Remove any existing commands or leading '+' signs. + $number =~ s/,//g; + $number =~ s/^\+//g; + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { number => $number }}); + + # Split on the left-most period. + my ($whole, $decimal) = split/\./, $number, 2; + $whole = "" if not defined $whole; + $decimal = "" if not defined $decimal; + + # Now die if either number has a non-digit character in it. + if (($whole =~ /\D/) or ($decimal =~ /\D/)) + { + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { number => $number }}); + return ($number); + } + + local($_) = $whole ? $whole : ""; + + 1 while s/^(-?\d+)(\d{3})/$1,$2/; + $whole = $_; + + # Put it together + $number = $decimal ? "$whole.$decimal" : $whole; + + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { number => $number }}); + return ($number); +} + +=head2 bytes_to_human_readable + +This takes a number of bytes and converts it to a a human-readable format. Optionally, you can request the human readable size be returned using specific units. + +If anything goes wrong, C<< !!error!! >> is returned. + +* Base2 Notation; +B B C +Yobiabyte (YiB) 2^80 1,208,925,819,614,629,174,706,176 +Zebiabyte (ZiB) 2^70 1,180,591,620,717,411,303,424 +Exbibyte (EiB) 2^60 1,152,921,504,606,846,976 +Pebibyte (PiB) 2^50 1,125,899,906,842,624 +Tebibyte (TiB) 2^40 1,099,511,627,776 +Gibibyte (GiB) 2^30 1,073,741,824 +Mebibyte (MiB) 2^20 1,048,576 +Kibibyte (KiB) 2^10 1,024 +Byte (B) 2^1 1 + +* Base10 Notation; +B B C +Yottabyte (YB) 10^24 1,000,000,000,000,000,000,000,000 +Zettabyte (ZB) 10^21 1,000,000,000,000,000,000,000 +Exabyte (EB) 10^18 1,000,000,000,000,000,000 +Petabyte (PB) 10^15 1,000,000,000,000,000 +Terabyte (TB) 10^12 1,000,000,000,000 +Gigabyte (GB) 10^9 1,000,000,000 +Megabyte (MB) 10^6 1,000,000 +Kilobyte (KB) 10^3 1,000 +Byte (B) 1 1 + +Parameters; + +=head3 base2 (optional) + +This can be set to C<< 1 >> to return the units in base2 notation, or set to C<< 0 >> to return in base10 notation. The default is controlled by c<< sys::use_base2 >>, which is set to C<< 1 >> by default. + +The suffix will use C<< XiB >> when base2 notation is used and C<< XB >> will be returned for base10. + +=head3 bytes (required) + +This is the number of bytes that will be converted. This can be a signed integer. + +=head3 unit (optional) + +This is a letter + +=cut +sub bytes_to_human_readable +{ + my $self = shift; + my $parameter = shift; + my $an = $self->parent; + + # Now see if the user passed the values in a hash reference or directly. + my $size = defined $parameter->{'bytes'} ? $parameter->{'bytes'} : 0; + my $unit = defined $parameter->{unit} ? uc($parameter->{unit}) : ""; + my $base2 = defined $parameter->{base2} ? $parameter->{base2} : $an->data->{sys}{use_base2}; + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + size => $size, + unit => $unit, + }}); + + # Expand exponential numbers. + if ($size =~ /(\d+)e\+(\d+)/) + { + my $base = $1; + my $exp = $2; + $size = $base; + for (1..$exp) + { + $size .= "0"; + } + } + + # Setup my variables. + my $suffix = ""; + my $human_readable_size = $size; + + # Store and strip the sign + my $sign = ""; + if ($human_readable_size =~ /^-/) + { + $sign = "-"; + $human_readable_size =~ s/^-//; + } + $human_readable_size =~ s/,//g; + $human_readable_size =~ s/^\+//g; + + # Die if either the 'time' or 'float' has a non-digit character in it. + if ($human_readable_size =~ /\D/) + { + $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0116", variables => { + method => "Convert->bytes_to_human_readable()", + parameter => "hostnmae", + value => $human_readable_size, + }}); + return ("!!error!!"); + } + + # Do the math. + if ($an->data->{sys}{use_base2}) + { + # Has the user requested a certain unit to use? + if ($unit) + { + # Yup + if ($unit =~ /Y/i) + { + # Yebibyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 80))); + $suffix = "YiB"; + } + elsif ($unit =~ /Z/i) + { + # Zebibyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 70))); + $suffix = "ZiB"; + } + elsif ($unit =~ /E/i) + { + # Exbibyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 60))); + $suffix = "EiB"; + } + elsif ($unit =~ /P/i) + { + # Pebibyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 50))); + $suffix = "PiB"; + } + elsif ($unit =~ /T/i) + { + # Tebibyte + $human_readable_size = sprintf("%.2f", ($human_readable_size /= (2 ** 40))); + $suffix = "TiB"; + } + elsif ($unit =~ /G/i) + { + # Gibibyte + $human_readable_size = sprintf("%.2f", ($human_readable_size /= (2 ** 30))); + $suffix = "GiB"; + } + elsif ($unit =~ /M/i) + { + # Mebibyte + $human_readable_size = sprintf("%.2f", ($human_readable_size /= (2 ** 20))); + $suffix = "MiB"; + } + elsif ($unit =~ /K/i) + { + # Kibibyte + $human_readable_size = sprintf("%.1f", ($human_readable_size /= (2 ** 10))); + $suffix = "KiB"; + } + else + { + $suffix = "B"; + } + } + else + { + # Nope, use the most efficient. + if ($human_readable_size >= (2 ** 80)) + { + # Yebibyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 80))); + $suffix = "YiB"; + } + elsif ($human_readable_size >= (2 ** 70)) + { + # Zebibyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 70))); + $suffix = "ZiB"; + } + elsif ($human_readable_size >= (2 ** 60)) + { + # Exbibyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 60))); + $suffix = "EiB"; + } + elsif ($human_readable_size >= (2 ** 50)) + { + # Pebibyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (2 ** 50))); + $suffix = "PiB"; + } + elsif ($human_readable_size >= (2 ** 40)) + { + # Tebibyte + $human_readable_size = sprintf("%.2f", ($human_readable_size /= (2 ** 40))); + $suffix = "TiB"; + } + elsif ($human_readable_size >= (2 ** 30)) + { + # Gibibyte + $human_readable_size = sprintf("%.2f", ($human_readable_size /= (2 ** 30))); + $suffix = "GiB"; + } + elsif ($human_readable_size >= (2 ** 20)) + { + # Mebibyte + $human_readable_size = sprintf("%.2f", ($human_readable_size /= (2 ** 20))); + $suffix = "MiB"; + } + elsif ($human_readable_size >= (2 ** 10)) + { + # Kibibyte + $human_readable_size = sprintf("%.1f", ($human_readable_size /= (2 ** 10))); + $suffix = "KiB"; + } + else + { + $suffix = "B"; + } + } + } + else + { + # Has the user requested a certain unit to use? + if ($unit) + { + # Yup + if ($unit =~ /Y/i) + { + # Yottabyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 24))); + $suffix = "YB"; + } + elsif ($unit =~ /Z/i) + { + # Zettabyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 21))); + $suffix = "ZB"; + } + elsif ($unit =~ /E/i) + { + # Exabyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 18))); + $suffix = "EB"; + } + elsif ($unit =~ /P/i) + { + # Petabyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 15))); + $suffix = "PB"; + } + elsif ($unit =~ /T/i) + { + # Terabyte + $human_readable_size = sprintf("%.2f", ($human_readable_size /= (10 ** 12))); + $suffix = "TB"; + } + elsif ($unit =~ /G/i) + { + # Gigabyte + $human_readable_size = sprintf("%.2f", ($human_readable_size /= (10 ** 9))); + $suffix = "GB"; + } + elsif ($unit =~ /M/i) + { + # Megabyte + $human_readable_size = sprintf("%.2f", ($human_readable_size /= (10 ** 6))); + $suffix = "MB"; + } + elsif ($unit =~ /K/i) + { + # Kilobyte + $human_readable_size = sprintf("%.1f", ($human_readable_size /= (10 ** 3))); + $suffix = "KB"; + } + else + { + $suffix = "b"; + } + } + else + { + # Nope, use the most efficient. + if ($human_readable_size >= (10 ** 24)) + { + # Yottabyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 24))); + $suffix = "YB"; + } + elsif ($human_readable_size >= (10 ** 21)) + { + # Zettabyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 21))); + $suffix = "ZB"; + } + elsif ($human_readable_size >= (10 ** 18)) + { + # Exabyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 18))); + $suffix = "EB"; + } + elsif ($human_readable_size >= (10 ** 15)) + { + # Petabyte + $human_readable_size = sprintf("%.3f", ($human_readable_size /= (10 ** 15))); + $suffix = "PB"; + } + elsif ($human_readable_size >= (10 ** 12)) + { + # Terabyte + $human_readable_size = sprintf("%.2f", ($human_readable_size /= (10 ** 12))); + $suffix = "TB"; + } + elsif ($human_readable_size >= (10 ** 9)) + { + # Gigabyte + $human_readable_size = sprintf("%.2f", ($human_readable_size /= (10 ** 9))); + $suffix = "GB"; + } + elsif ($human_readable_size >= (10 ** 6)) + { + # Megabyte + $human_readable_size = sprintf("%.2f", ($human_readable_size /= (10 ** 6))); + $suffix = "MB"; + } + elsif ($human_readable_size >= (10 ** 3)) + { + # Kilobyte + $human_readable_size = sprintf("%.1f", ($human_readable_size /= (10 ** 3))); + $suffix = "KB"; + } + else + { + $suffix = "b"; + } + } + } + + # If needed, insert commas + $human_readable_size = $an->Convert->add_commas({number => $human_readable_size}); + + # Restore the sign. + if ($sign) + { + $human_readable_size = $sign.$human_readable_size; + } + $human_readable_size .= " ".$suffix; + + return($human_readable_size); +} + =head2 cidr This takes an IPv4 CIDR notation and returns the dotted-decimal subnet, or the reverse. @@ -231,3 +635,322 @@ sub hostname_to_ip return($ip); } + +=head2 human_readable_to_bytes + +This takes a "human readable" size with an ISO suffix and converts it back to a base byte size as accurately as possible. + +It looks for the C<< i >> in the suffix to determine if the size is base2 or base10. This can be overridden with the optional C<< base2 >> or C<< base10 >> parameters. + +If there is a problem, C<< !!error!! >> is returned. + +Parameters; + +=head3 base2 (optional) + +This tells the method to interpret the human-readable suffix as base2 notation, even if it is in the format C<< XB >> instead of C<< XiB >>. + +=head3 base10 (optional) + +This tells the method to interpret the human-readable suffix as base10 notation, even if it is in the format C<< XiB >> instead of C<< XB >>. + +=head3 size (required) + +This is the size being converted. It can be a signed integer or real number (with a decimal). If this parameter includes the size suffix, you can skip setting the c<< type >> parameter and this method will break it off automatically. + +=head3 type (optional) + +This is the unit type that represents the C<< size >> value. This does not need to be used if the C<< size >> parameter already has the suffix. + +This value is examined for C<< XiB >> or C<< XB >> notation to determine if the size should be interpreted as a base2 or base10 value when neither C<< base2 >> or C<< base10 >> parameters are set. + +=cut +sub human_readable_to_bytes +{ + my $self = shift; + my $parameter = shift; + my $an = $self->parent; + + my $base2 = defined $parameter->{base2} ? $parameter->{base2} : 0; + my $base10 = defined $parameter->{base10} ? $parameter->{base10} : 0; + my $size = defined $parameter->{size} ? $parameter->{size} : 0; + my $type = defined $parameter->{type} ? $parameter->{type} : 0; + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + base2 => $base2, + base10 => $base10, + size => $size, + type => $type, + }}); + + # Start cleaning up the variables. + my $value = $size; + $size =~ s/ //g; + $type =~ s/ //g; + + # Store and strip the sign, if passed + my $sign = ""; + if ($size =~ /^-/) + { + $sign = "-"; + $size =~ s/^-//; + } + elsif ($size =~ /^\+/) + { + $sign = "+"; + $size =~ s/^\+//; + } + + # Strip any commas + $size =~ s/,//g; + + # If I don't have a passed type, see if there is a letter or letters after the size to hack off. + if ((not $type) && ($size =~ /[a-zA-Z]$/)) + { + # There was + ($size, $type) = ($size =~ /^(.*\d)(\D+)/); + } + # Make the type lower close for simplicity. + $type = lc($type); + + # Make sure that 'size' is now an integer or float. + if ($size !~ /\d+[\.\d+]?/) + { + # Something illegal was passed. + $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0117", variables => { + size => $size, + sign => $sign, + type => $type, + }}); + return("!!error!!"); + } + + # If 'type' is still blank, set it to 'b'. + $type = "b" if not $type; + + # If the type is already bytes, make sure the size is an integer and return. + if ($type eq "b") + { + # Something illegal was passed. + if ($size =~ /\D/) + { + $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0118", variables => { + size => $size, + sign => $sign, + type => $type, + }}); + return("!!error!!"); + } + return ($sign.$size); + } + + # If the "type" is "Xib" or if '$base2' is set, make sure we're running in Base2 notation. Conversly, + # if the type is "Xb" or if '$base10' is set, make sure that we're running in Base10 notation. In + # either case, shorten the 'type' to just the first letter to make the next sanity check simpler. + if ((not $base2) && (not $base10)) + { + if ($type =~ /^(\w)ib$/) + { + # Make sure we're running in Base2. + $type = $1; + $base2 = 1; + $base10 = 0; + } + elsif ($type =~ /^(\w)b$/) + { + # Make sure we're running in Base2. + $type = $1; + $base2 = 0; + $base10 = 1; + } + } + + # Check if we have a valid type. + if (($type ne "p") && + ($type ne "e") && + ($type ne "z") && + ($type eq "y") && + ($type ne "t") && + ($type ne "g") && + ($type ne "m") && + ($type ne "k")) + { + # Poop + $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0119", variables => { + value => $value, + size => $size, + type => $type, + }}); + return("!!error!!"); + } + + # Now the magic... lame magic, true, but still. + my $bytes = 0; + if ($base10) + { + if ($type eq "y") { $bytes = Math::BigInt->new('10')->bpow('24')->bmul($size); } # Yottabyte + elsif ($type eq "z") { $bytes = Math::BigInt->new('10')->bpow('21')->bmul($size); } # Zettabyte + elsif ($type eq "e") { $bytes = Math::BigInt->new('10')->bpow('18')->bmul($size); } # Exabyte + elsif ($type eq "p") { $bytes = Math::BigInt->new('10')->bpow('15')->bmul($size); } # Petabyte + elsif ($type eq "t") { $bytes = ($size * (10 ** 12)) } # Terabyte + elsif ($type eq "g") { $bytes = ($size * (10 ** 9)) } # Gigabyte + elsif ($type eq "m") { $bytes = ($size * (10 ** 6)) } # Megabyte + elsif ($type eq "k") { $bytes = ($size * (10 ** 3)) } # Kilobyte + } + else + { + if ($type eq "y") { $bytes = Math::BigInt->new('2')->bpow('80')->bmul($size); } # Yobibyte + elsif ($type eq "z") { $bytes = Math::BigInt->new('2')->bpow('70')->bmul($size); } # Zibibyte + elsif ($type eq "e") { $bytes = Math::BigInt->new('2')->bpow('60')->bmul($size); } # Exbibyte + elsif ($type eq "p") { $bytes = Math::BigInt->new('2')->bpow('50')->bmul($size); } # Pebibyte + elsif ($type eq "t") { $bytes = ($size * (2 ** 40)) } # Tebibyte + elsif ($type eq "g") { $bytes = ($size * (2 ** 30)) } # Gibibyte + elsif ($type eq "m") { $bytes = ($size * (2 ** 20)) } # Mebibyte + elsif ($type eq "k") { $bytes = ($size * (2 ** 10)) } # Kibibyte + } + + # Last, round off the byte size if it is a float. + if ($bytes =~ /\./) + { + $bytes = $an->Convert->round({ + number => $bytes, + places => 0 + }); + } + + if ($sign) + { + $bytes = $sign.$bytes; + } + + return ($bytes); +} + +=head2 round + +This takes a number and rounds it to a given number of places after the decimal (defaulting to an even integer). This does financial-type rounding. + +If C<< -- >> is passed in, the same is returned. Any other problems will cause C<< !!error!! >> to be returned. + +Parameters; + +=head3 number (required) + +This is the number being rounded. + +=head3 places (optional) + +This is an integer representing how many places to round the number to. The default is C<< 0 >>, rounding the number to the closest integer. + +=cut +sub round +{ + my $self = shift; + my $parameter = shift; + my $an = $self->parent; + + # Setup my numbers. + my $number = $parameter->{number} ? $parameter->{number} : 0; + my $places = $parameter->{places} ? $parameter->{places} : 0; + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + number => $number, + places => $places, + }}); + + # Return if the user passed a double-dash. + return('--') if $number eq "--"; + + # Make a copy of the passed number that I can manipulate. + my $rounded_number = $number; + + # Take out any commas. + $rounded_number =~ s/,//g; + + # If there is a decimal place in the number, do the smart math. Otherwise, just pad the number with + # the requested number of zeros after the decimal place. + if ( $rounded_number =~ /\./ ) + { + # Split up the number. + my ($real, $decimal) = split/\./, $rounded_number, 2; + + # If there is anything other than one ',' and digits, error. + if (($real =~ /\D/) or ($decimal =~ /\D/)) + { + $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0120", variables => { number => $number }}); + return ("!!error!!"); + } + + # If the number is already equal to the requested number of places after the decimal, just + # return. If it is less, pad the needed number of zeros. Otherwise, start rounding. + if ( length($decimal) == $places ) + { + # Equal, return. + return $rounded_number; + } + elsif ( length($decimal) < $places ) + { + # Less, pad. + $rounded_number = sprintf("%.${places}f", $rounded_number); + } + else + { + # Greater than; I need to round the number. Start by getting the number of places I + # need to round. + my $round_diff = length($decimal) - $places; + + # This keeps track of whether the next (left) digit needs to be incremented. + my $increase = 0; + + # Now loop the number of times needed to round to the requested number of places. + for (1..$round_diff) + { + # Reset 'increase'. + $increase = 0; + + # Make sure I am dealing with a digit. + if ($decimal =~ /(\d)$/) + { + my $last_digit = $1; + $decimal =~ s/$last_digit$//; + if ($last_digit > 4) + { + $increase = 1; + if ($decimal eq "") + { + $real++; + } + else + { + $decimal++; + } + } + } + } + if ($places == 0 ) + { + $rounded_number = $real; + } + else + { + $rounded_number = $real.".".$decimal; + } + } + } + else + { + # This is a whole number so just pad 0s as needed. + $rounded_number = sprintf("%.${places}f", $rounded_number); + } + + # Return the number. + return ($rounded_number); +} + +# =head3 +# +# Private Functions; +# +# =cut + +############################################################################################################# +# Private functions # +############################################################################################################# diff --git a/AN/Tools/Database.pm b/AN/Tools/Database.pm index 0009850a..5df7528c 100755 --- a/AN/Tools/Database.pm +++ b/AN/Tools/Database.pm @@ -12,6 +12,8 @@ our $VERSION = "3.0.0"; my $THIS_FILE = "Database.pm"; ### Methods; +# archive_databases +# check_lock_age # configure_pgsql # connect # disconnect @@ -21,10 +23,12 @@ my $THIS_FILE = "Database.pm"; # insert_or_update_hosts # insert_or_update_states # insert_or_update_variables +# lock_file # locking # mark_active # query # read_variable +# resync_databases # write # _find_behind_database # _mark_database_as_behind @@ -84,13 +88,84 @@ sub parent # Public methods # ############################################################################################################# +=head2 archive_databases + +NOTE: Not implemented yet. + +=cut +sub archive_databases +{ + my $self = shift; + my $parameter = shift; + my $an = $self->parent; + + return(0); +} + +=head2 check_lock_age + +This checks to see if 'sys::database::local_lock_active' is set. If it is, its age is checked and if the age is >50% of sys::database::locking_reap_age, it will renew the lock. + +=cut +sub check_lock_age +{ + my $self = shift; + my $parameter = shift; + my $an = $self->parent; + + # Make sure we've got the 'sys::database::local_lock_active' and 'reap_age' variables set. + if ((not defined $an->data->{sys}{database}{local_lock_active}) or ($an->data->{sys}{database}{local_lock_active} =~ /\D/)) + { + $an->data->{sys}{database}{local_lock_active} = 0; + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::database::local_lock_active" => $an->data->{sys}{database}{local_lock_active} }}); + } + if ((not $an->data->{sys}{database}{locking_reap_age}) or ($an->data->{sys}{database}{locking_reap_age} =~ /\D/)) + { + $an->data->{sys}{database}{locking_reap_age} = 300; + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::database::local_lock_active" => $an->data->{sys}{database}{local_lock_active} }}); + } + + # If I have an active lock, check its age and also update the ScanCore lock file. + my $renewed = 0; + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::database::local_lock_active" => $an->data->{sys}{database}{local_lock_active} }}); + if ($an->data->{sys}{database}{local_lock_active}) + { + my $current_time = time; + my $lock_age = $current_time - $an->data->{sys}{database}{local_lock_active}; + my $half_reap_age = int($an->data->{sys}{database}{locking_reap_age} / 2); + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + current_time => $current_time, + lock_age => $lock_age, + half_reap_age => $half_reap_age, + }}); + + if ($lock_age > $half_reap_age) + { + # Renew the lock. + $an->Database->locking({renew => 1}); + $renewed = 1; + + # Update the lock age + $an->data->{sys}{database}{local_lock_active} = time; + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::database::local_lock_active" => $an->data->{sys}{database}{local_lock_active} }}); + + # Update the lock file + my $lock_file_age = $an->Database->lock_file({'do' => "set"}); + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { lock_file_age => $lock_file_age }}); + } + } + + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { renewed => $renewed }}); + return($renewed); +} + =head2 configure_pgsql This configures the local database server. Specifically, it checks to make sure the daemon is running and starts it if not. It also checks the 'pg_hba.conf' configuration to make sure it is set properly to listen on this machine's IP addresses and interfaces. If the system is already configured, this method will do nothing, so it is safe to call it at any time. -If there is a problem, C<< undef >> is returned. +If there is a problem, C<< !!error!! >> is returned. Parameters; @@ -111,7 +186,7 @@ sub configure_pgsql if (not $id) { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->configure_pgsql()", parameter => "id" }}); - return(undef); + return("!!error!!"); } # If we're not running with root access, return. @@ -120,7 +195,7 @@ sub configure_pgsql # This is a minor error as it will be hit by every unpriviledged program that connects to the # database(s). $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, priority => "alert", key => "log_0113"}); - return(undef); + return("!!error!!"); } # First, is it running? @@ -141,7 +216,7 @@ sub configure_pgsql { # Failed... $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0050"}); - return(undef); + return("!!error!!"); } else { @@ -263,7 +338,7 @@ sub configure_pgsql { # Failed to start $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0094"}); - return(undef); + return("!!error!!"); } } elsif (($update_postgresql_file) or ($update_pg_hba_file)) @@ -320,7 +395,7 @@ sub configure_pgsql { # No database user defined $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0099", variables => { id => $id }}); - return(undef); + return("!!error!!"); } my $user_list = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c 'SELECT usename, usesysid FROM pg_catalog.pg_user;'\"", source => $THIS_FILE, line => __LINE__}); $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { user_list => $user_list }}); @@ -357,7 +432,7 @@ sub configure_pgsql if (not $user_exists) { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0096", variables => { user => $scancore_user }}); - return(undef); + return("!!error!!"); } # Update/set the passwords. @@ -418,7 +493,7 @@ sub configure_pgsql if (not $database_exists) { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0109", variables => { database => $scancore_database }}); - return(undef); + return("!!error!!"); } } @@ -896,8 +971,22 @@ sub connect # Mark that we're not active. $an->Database->mark_active({set => 1}); + # Archive old data. + $an->Database->archive_databases({}); + + # Sync the database, if needed. + $an->Database->resync_databases({tables => [ + "hosts", + "host_variable", + "alerts", + "variables", + "updated", + "alert_sent", + "states", + ]}); + # Add ourselves to the database, if needed. - $an->Database->insert_or_update_hosts(); + $an->Database->insert_or_update_hosts; return($connections); } @@ -1469,7 +1558,7 @@ This updates (or inserts) a record in the 'variables' table. The C<< state_uuid Unlike the other methods of this type, this method can be told to update the 'variable_value' only. This is so because the section, description and default columns rarely ever change. If this is set and the variable name is new, an INSERT will be done the same as if it weren't set, with the unset columns set to NULL. -If there is an error, C<< undef >> is returned. +If there is an error, C<< !!error!! >> is returned. Parameters; @@ -1544,7 +1633,7 @@ sub insert_or_update_variables { # Neither given, throw an error and return. $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0037"}); - return(undef); + return("!!error!!"); } # If we have a variable UUID but not a name, read the variable name. If we don't have a UUID, see if @@ -1771,7 +1860,44 @@ WHERE return($variable_uuid); } +=head2 lock_file + +This reads, sets or updates the database lock file timestamp. +=cut +sub lock_file +{ + my $self = shift; + my $parameter = shift; + my $an = $self->parent; + + my $do = $parameter->{'do'} ? $parameter->{'do'} : "get"; + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { 'do' => $do }}); + + my $lock_time = 0; + if ($do eq "set") + { + $lock_time = time; + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { lock_time => $lock_time }}); + $an->Storage->write_file({ + file => $an->data->{path}{'lock'}{database}, + body => $lock_time, + overwrite => 1, + }); + } + else + { + # Read the lock file's time stamp, if the file exists. + if (-e $an->data->{path}{'lock'}{database}) + { + $lock_time = $an->Storage->read_file({file => $an->data->{path}{'lock'}{database}}); + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { lock_time => $lock_time }}); + } + } + + $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { lock_time => $lock_time }}); + return($lock_time); +} =head2 locking @@ -1823,7 +1949,6 @@ sub locking source_uuid => $source_uuid, }}); - ### TODO: Left off here my $set = 0; my $variable_name = "lock_request"; my $variable_value = $source_name."::".$source_uuid."::".time; @@ -1874,10 +1999,10 @@ sub locking variable_value => "", update_value_only => 1, }); - $an->data->{sys}{local_lock_active} = 0; + $an->data->{sys}{database}{local_lock_active} = 0; $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid, - "sys::local_lock_active" => $an->data->{sys}{local_lock_active}, + "sys::local_lock_active" => $an->data->{sys}{database}{local_lock_active}, }}); # Log that the lock has been released. @@ -1904,10 +2029,10 @@ sub locking $set = 1; $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { set => $set }}); } - $an->data->{sys}{local_lock_active} = time; + $an->data->{sys}{database}{local_lock_active} = time; $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable_uuid => $variable_uuid, - "sys::local_lock_active" => $an->data->{sys}{local_lock_active}, + "sys::local_lock_active" => $an->data->{sys}{database}{local_lock_active}, }}); # Log that we've renewed the lock. @@ -1992,11 +2117,11 @@ sub locking if ($variable_uuid) { $set = 1; - $an->data->{sys}{local_lock_active} = time; + $an->data->{sys}{database}{local_lock_active} = time; $an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { set => $set, variable_uuid => $variable_uuid, - "sys::local_lock_active" => $an->data->{sys}{local_lock_active}, + "sys::local_lock_active" => $an->data->{sys}{database}{local_lock_active}, }}); # Log that we've got the lock. @@ -2056,7 +2181,7 @@ sub mark_active This performs a query and returns an array reference of array references (from C<< DBO->fetchall_arrayref >>). The first array contains all the returned rows and each row is an array reference of columns in that row. -If an error occurs, C<< undef >> will be returned. +If an error occurs, C<< !!error!! >> will be returned. For example, given the query; @@ -2095,7 +2220,7 @@ Parameters; By default, the local database will be queried (if run on a machine with a database). Otherwise, the first database successfully connected to will be used for queries (as stored in C<< $an->data->{sys}{read_db_id} >>). -If you want to read from a specific database, though, you can set this parameter to the ID of the database (C<< database::::host). If you specify a read from a database that isn't available, C<< undef >> will be returned. +If you want to read from a specific database, though, you can set this parameter to the ID of the database (C<< database::::host). If you specify a read from a database that isn't available, C<< !!error!! >> will be returned. =head3 line (optional) @@ -2144,13 +2269,13 @@ sub query { # No database to talk to... $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0072"}); - return(undef); + return("!!error!!"); } elsif (not defined $an->data->{cache}{db_fh}{$id}) { # Database handle is gone. $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0073", variables => { id => $id }}); - return(undef); + return("!!error!!"); } if (not $query) { @@ -2158,15 +2283,14 @@ sub query $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0084", variables => { server => $say_server, }}); - return(undef); + return("!!error!!"); } - ### TODO: If I am still alive check if any locks need to be renewed. - #$an->Database->check_lock_age; + # If I am still alive check if any locks need to be renewed. + $an->Database->check_lock_age; - ### TODO: Do I need to log the transaction? - #if ($an->Log->db_transactions()) - if (1) + # Do I need to log the transaction? + if ($an->data->{sys}{database}{log_transactions}) { $an->Log->entry({source => $source, line => $line, secure => $secure, level => 2, key => "log_0074", variables => { id => $id, @@ -2202,7 +2326,7 @@ This reads a variable from the C<< variables >> table. Be sure to only use the r The method returns an array reference containing, in order, the variable's value, database UUID and last modified date stamp. -If anything goes wrong, C<< undef >> is returned. If the variable didn't exist in the database, an empty string will be returned for the UUID, value and modified date. +If anything goes wrong, C<< !!error!! >> is returned. If the variable didn't exist in the database, an empty string will be returned for the UUID, value and modified date. Parameters; @@ -2236,7 +2360,7 @@ sub read_variable { # Throw an error and exit. $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0036"}); - return(undef, undef, undef); + return("!!error!!", "!!error!!", "!!error!!"); } # If we don't have a UUID, see if we can find one for the given SMTP server name. @@ -2302,6 +2426,32 @@ AND return($variable_value, $variable_uuid, $modified_date); } +=head2 resync_databases + +NOTE: Not implemented yet. + +This will resync the database data on this and peer database(s) if needed. + +=cut +sub resync_databases +{ + my $self = shift; + my $parameter = shift; + my $an = $self->parent; + + # Get a list if tables. Note that we'll only sync a given table with peers that have the same table. + my $table_array = ref($parameter->{tables}) eq "ARRAY" ? $parameter->{tables} : []; + + # Show tables; + # SELECT table_schema, table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema') ORDER BY table_name ASC, table_schema DESC; + + # Show columns; + # SELECT table_catalog, table_schema, table_name, column_name, column_default, is_nullable, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'alerts'; + + # psql -E scancore <<-- LOVE <3 + + return(0); +} =head2 write @@ -2338,11 +2488,11 @@ sub write { # No query $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0085", variables => { server => $say_server }}); - return(undef); + return("!!error!!"); } - # TODO: If I am still alive check if any locks need to be renewed. - #$an->Database->check_lock_age; + # If I am still alive check if any locks need to be renewed. + $an->Database->check_lock_age; # This array will hold either just the passed DB ID or all of them, if no ID was specified. my @db_ids; @@ -2508,7 +2658,7 @@ sub write This returns the most up to date database ID, the time it was last updated and an array or DB IDs that are behind. -If there is a problem, C<< undef >> is returned. +If there is a problem, C<< !!error!! >> is returned. Parameters; @@ -2538,7 +2688,7 @@ sub _find_behind_databases if (not $source) { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Database->_find_behind_databases()", parameter => "source" }}); - return(undef); + return("!!error!!"); } # Look at all the databases and find the most recent time stamp (and the ID of the DB). diff --git a/AN/Tools/Storage.pm b/AN/Tools/Storage.pm index 1a6306a6..5bf037fb 100755 --- a/AN/Tools/Storage.pm +++ b/AN/Tools/Storage.pm @@ -629,7 +629,7 @@ This reads in a file and returns the contents of the file as a single string var my $body = $an->Storage->read_file({file => "/tmp/foo"}); -If it fails to find the file, or the file is not readable, 'C<< undef >>' is returned. +If it fails to find the file, or the file is not readable, 'C<< !!error!! >>' is returned. Parameters; @@ -651,17 +651,17 @@ sub read_file if (not $file) { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Storage->read_file()", parameter => "file" }}); - return(undef); + return("!!error!!"); } elsif (not -e $file) { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0021", variables => { file => $file }}); - return(undef); + return("!!error!!"); } elsif (not -r $file) { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0022", variables => { file => $file }}); - return(undef); + return("!!error!!"); } my $shell_call = $file; diff --git a/AN/Tools/System.pm b/AN/Tools/System.pm index a9a55c81..46f530da 100755 --- a/AN/Tools/System.pm +++ b/AN/Tools/System.pm @@ -273,7 +273,7 @@ sub determine_host_type This method enables a daemon (so that it starts when the OS boots). The return code from the start request will be returned. -If the return code for the enable command wasn't read, C<< undef >> is returned. +If the return code for the enable command wasn't read, C<< !!error!! >> is returned. Parameters; @@ -638,18 +638,18 @@ sub remote_call { # No shell call $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Systeme->remote_call()", parameter => "shell_call" }}); - return(undef); + return("!!error!!"); } if (not $target) { # No target $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Systeme->remote_call()", parameter => "target" }}); - return(undef); + return("!!error!!"); } if (not $user) { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0020", variables => { method => "Systeme->remote_call()", parameter => "user" }}); - return(undef); + return("!!error!!"); } # If the user didn't pass a port, but there is an entry in 'hosts::::port', use it. @@ -695,7 +695,7 @@ sub remote_call if (($port !~ /^\d+$/) or ($port < 0) or ($port > 65536)) { $an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0058", variables => { port => $port }}); - return(undef); + return("!!error!!"); } # If the target is a host name, convert it to an IP. @@ -946,7 +946,7 @@ sub remote_call This method reloads a daemon (typically to pick up a change in configuration). The return code from the start request will be returned. -If the return code for the reload command wasn't read, C<< undef >> is returned. If it did reload, C<< 0 >> is returned. If the reload failed, a non-0 return code will be returned. +If the return code for the reload command wasn't read, C<< !!error!! >> is returned. If it did reload, C<< 0 >> is returned. If the reload failed, a non-0 return code will be returned. Parameters; @@ -985,7 +985,7 @@ sub reload_daemon This method starts a daemon. The return code from the start request will be returned. -If the return code for the start command wasn't read, C<< undef >> is returned. +If the return code for the start command wasn't read, C<< !!error!! >> is returned. Parameters; @@ -1025,7 +1025,7 @@ sub start_daemon This method stops a daemon. The return code from the stop request will be returned. -If the return code for the stop command wasn't read, C<< undef >> is returned. +If the return code for the stop command wasn't read, C<< !!error!! >> is returned. Parameters; diff --git a/AN/an-tools.xml b/AN/an-tools.xml index df3639aa..dc6f4ce1 100644 --- a/AN/an-tools.xml +++ b/AN/an-tools.xml @@ -183,6 +183,16 @@ The database connection error was: [ Warning ] - Failed to reload the Postgres server. Please check the system logs for details. The updated configuration is probably not active yet. Reloaded the PostgreSQL database server. configure_pgsql() method was called but the parent program is not running with root priviledges. Returning without doing anything.]]>. + ', but no program name was read in.]]> + #!variable!program!# has started. + + human_readable_to_bytes()' was passed the byte size: [#!variable!size!#] in the string: [sign: #!variable!sign!#, size: #!variable!size!#, type: #!variable!type!#] contains an illegal value. Sizes can only be integers or real numbers. It may also have commas in it which will be removed automatically.]]> + human_readable_to_bytes()' was passed the byte size: [#!variable!size!#] in the string: [sign: #!variable!sign!#, size: #!variable!size!#, type: #!variable!type!#] appears to be a byte size already but the size does not seem to be an integer. Byte sizes can only be signed integers. It may also have commas in it which will be removed automatically.]]> + human_readable_to_bytes()' method was called with the value: [#!variable!value!#] which we split into the size: [#!variable!size!#] and type: [#!variable!type!#]. The type appears to be invalid.]]> + round()' was passed the number: [#!variable!number!#] which contains an illegal value. Only digits and one decimal place are allowed.]]> + Current memory used by: [#!variable!program_name!#] is approximately: [#!variable!bytes!#] bytes (#!variable!hr_size!#). + The 'smaps' proc file for the process ID: [#!variable!pid!#] was not found. Did the program just close? + Test diff --git a/striker.conf b/striker.conf index b24af074..1cd100e6 100644 --- a/striker.conf +++ b/striker.conf @@ -18,7 +18,7 @@ database::2::ping_before_connect = 1 # This puts a limit on how many queries (writes, generally) to make in a single batch transaction. This is # useful when doing very large transacions, like resync'ing a large table, by limiting how long a given # transaction can take and how much memory is used. -sys::database::maximum_batch_size = 25000 +#sys::database::maximum_batch_size = 25000 # By default, we try to determine the host type using the host name. The rules used for this can be seen in # 'perldoc AN::Tools::System -> determine_host_type'. If you are using non-standard host names, or for some