<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">package TaskManager::DB;

use strict;
use warnings;

use DBI;

use TaskManager::Constants;
use TaskManager::System;

use Common::Log;

use constant DB_MYSQL_GONE_AWAY =&gt; 2006;
use constant DB_MYSQL_LOST_CONNECT =&gt; 2013;


our $dbh;
our $error;

our @ISA = qw(Exporter);
our @EXPORT = qw(
	connect_db
	disconnect_db
);


END {
	drop_log("Still having db connection on exit for pid=$$")
		if $dbh;
}

sub unbreakable_sleep {
    my $timeout = shift;
    my $endtime = time()+$timeout;
    while (1) {
        my $tosleep = $endtime - time();
        
        last unless ( $tosleep&gt;0 );
        
        sleep($tosleep);
    }
}

sub connect_db {

	if( $dbh &amp;&amp; $dbh-&gt;ping() ) {
#		drop_log("Use current DB connection for pid=$$");
		return $dbh;
	}

	$dbh-&gt;disconnect()
		if( $dbh );

	my $i = 0;
	do {
		#sleep $CFG-&gt;{'DB_CONNECTION_INTERVAL'}
        unbreakable_sleep($CFG-&gt;{'DB_CONNECTION_INTERVAL'})
			if $i++;
		$dbh = DBI-&gt;connect("DBI:mysql:$CFG-&gt;{DB_NAME}:$CFG-&gt;{DB_HOST}",$CFG-&gt;{'DB_USER'},$CFG-&gt;{'DB_PASSWORD'},{AutoCommit=&gt;1});
	}
	while( !$dbh &amp;&amp; $i &lt; $CFG-&gt;{'DB_CONNECTION_ATTEMPTS'} );

	make_die("Can't connect to mysql server for $CFG-&gt;{DB_CONNECTION_ATTEMPTS} attempts: ".$DBI::errstr)
		unless( $dbh );

	if( $i&gt;1 ) {
		drop_log("DB connection reestablished at $i attempt for pid=$$");
	}
	else {
#		drop_log("Connected to DB for pid=$$");
	}

	return $dbh;
}


sub disconnect_db {

	return undef
		unless $dbh;

	$dbh-&gt;disconnect();
	$dbh = undef;

#	drop_log("Disconnected from DB for pid=$$");

	return undef;
}


sub do_query {
	my $query = shift || die "No query given!";

	connect_db();

	my $i = 0;
	my $is_fatal = 0;
	my $err;

	do {
		$err = 0;
		$error = '';

		if( $i ) {
			drop_log("Lost connection, reconnecting for $i time for $$..");
			disconnect_db();
			unbreakable_sleep($CFG-&gt;{'DB_CONNECTION_INTERVAL'}) if $CFG-&gt;{'DB_CONNECTION_INTERVAL'};
			connect_db();
		}

		eval {
			$err = $dbh-&gt;err
				unless $dbh-&gt;do($query, undef, @_);
		};

		if( ($err &amp;&amp; $err!=DB_MYSQL_GONE_AWAY &amp;&amp; $err!=DB_MYSQL_LOST_CONNECT) || $@ ) {
			$is_fatal = 1;
			$error = $dbh-&gt;errstr || $@;
			drop_log("Error $err : $error for $$");
		}

		$i++;
	}
	while( $err &amp;&amp; !$is_fatal &amp;&amp; $i&lt;$CFG-&gt;{'DB_CONNECTION_ATTEMPTS'} );

	$error .= ", can't run for $CFG-&gt;{DB_CONNECTION_ATTEMPTS} attempts!"
		if( $err==DB_MYSQL_GONE_AWAY || $err==DB_MYSQL_LOST_CONNECT );

	write_log($CFG-&gt;{'DB_LOGFILE'}, $$."\t".$query.',('.__params_str(@_).')'.($err ? '; ERR:'.$err : '').($error ? '; ERROR:'.$error : ''), {'script_name'=&gt;0})
		if $CFG-&gt;{'DB_LOGFILE'};

	make_die($error)
		if $is_fatal;

	return $err ? 0 : 1;
}


sub __params_str {
	my $str = '';
	$str .= ($str ? ',' : '').(defined $_ ? $_ : '')
		for(@_);
	return $str;
}


sub select_query {
	my $query = shift || die "No query given!";

	connect_db();

	my $i = 0;
	my $is_fatal = 0;
	my $err;
	my $sth;

	do {
		$err = 0;
		$error = '';

		if( $i ) {
			drop_log("Lost connection, reconnecting for $i time for $$..");
			disconnect_db();
			connect_db();
		}

		eval {
			$err = $dbh-&gt;err
				unless ( $sth = $dbh-&gt;prepare($query) );

			unless( $err ) {
				$err = $sth-&gt;err
					unless $sth-&gt;execute(@_);
			}
		};

		if( ($err &amp;&amp; $err!=DB_MYSQL_GONE_AWAY &amp;&amp; $err!=DB_MYSQL_LOST_CONNECT) || $@ ) {
			$is_fatal = 1;
			$error = $dbh-&gt;errstr || $sth-&gt;errstr || $@ || "MYSQLERRCODE:$err";
		}

		$i++;
	}
	while( $err &amp;&amp; !$is_fatal &amp;&amp; $i&lt;$CFG-&gt;{'DB_CONNECTION_ATTEMPTS'} );

	$error .= ", can't run for $CFG-&gt;{DB_CONNECTION_ATTEMPTS} attempts!"
		if( $err==DB_MYSQL_GONE_AWAY || $err==DB_MYSQL_LOST_CONNECT );

	write_log($CFG-&gt;{'DB_LOGFILE'}, $$."\t".$query.',('.__params_str(@_).')'.($err ? '; ERR:'.$err : '').($error ? '; ERROR:'.$error : ''), {'script_name'=&gt;0})
		if $CFG-&gt;{'DB_LOGFILE'};

	make_die($error)
		if $is_fatal;

	my $REZ = [];
	while( my $hash = $sth-&gt;fetchrow_hashref() ) {
		push @$REZ, $hash;
	}

	$sth-&gt;finish();

	return $REZ;
}


1;
</pre></body></html>