Gentlemen,
Happy Valentine, so don't forget your ladies!
And it works fine, but I can see that the memory used by the
ldirector process grows linearly, until crash the server some days
after...
That is certainly not good. Is there any chance that you could
test a newer ldirectord to see if the problem has already been
resolved? The one shipped in the linux-ha (heartbeat) 2.6.8
tarball should be the latest.
I was bored for a couple of minutes and very interested in my freshly
installed Eclipse environment under Windows, so I skimmed over
ldirectord (for some reason my mercurial in eclipse didn't work, so I
had to download ldirectord by hand, create a temporary CVS repository
and diff it against my local CVS :)) for a while and came up with this
little patch as a base for further discussions. Rough changelog:
o Probable whitespace damage fix.
o s/$dbh->err/$dbh-errstr()/ to get meaningful messages for
all DBMS instead of numbers.
o Added error handling and db handle disconnect to
the prepare query; yes, it can fail :).
o Updated comment regarding the number of fetched rows,
since this is not a very reliable number from my little
experience with perl->DBI.
o Explicit finish() and disconnect() calls for the place we
should never get to and added comment, so we know if someone
actually hits that undesired code path.
o Added support for Oracle DBMS checking (totally untested).
o Removed old code indicating that once the rows were actually
fetched and maybe the original thought was to compare the rows
to some string. Nevertheless, this simplifies the code a bit
and stresses out why the undesired code path could be hit.
o Cosmetic function calling consistency brushup.
This has received no testing, since I don't run a LVS system, however I
believe the changes are relatively safe and straight-forward. They could
also give a hint or even address the memory leak observed by the
original poster.
Please review carefully and consider applying the fragments that look
fine to you, Horms.
Best regards,
Roberto Nibali, ratz
--
echo
'[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq' | dc
### Eclipse Workspace Patch 1.0
#P ldirectord
Index: ldirectord.pl
===================================================================
RCS file: /data/CVSROOT/ldirectord/CVSROOT/ldirectord.pl,v
retrieving revision 1.1
diff -u -r1.1 ldirectord.pl
--- ldirectord.pl 14 Feb 2007 19:29:06 -0000 1.1
+++ ldirectord.pl 14 Feb 2007 22:26:29 -0000
@@ -294,7 +294,7 @@
On means no checking will take place and real servers will always be
activated. Default is I<negotiate>.
-B<service =
ftp>|B<smtp>|B<http>|B<pop>|B<pops>|B<nntp>|B<imap>|B<imaps>|B<ldap>|B<https>|B<dns>|B<radius>|B<mysql>|B<pgsql>|B<sip>|B<none>
+B<service =
ftp>|B<smtp>|B<http>|B<pop>|B<pops>|B<nntp>|B<imap>|B<imaps>|B<ldap>|B<https>|B<dns>|B<radius>|B<mysql>|B<pgsql>|B<oracle>|B<sip>|B<none>
The type of service to monitor when using checktype=negotiate. None denotes
a service that will not be monitored.
@@ -326,6 +326,8 @@
=item * Virtual server port is 995: pops
+=item * Virtual server port is 1521: oracle
+
=item * Virtual server port is 1812: radius
=item * Virtual server port is 3306: mysql
@@ -354,7 +356,7 @@
For a DNS check this should the name of an A record, or the address
of a PTR record to look up.
-For a MySQL or PostgeSQL checks, this should be a SQL query.
+For a MySQL, PostgeSQL or Oracle checks, this should be a SQL query.
The data returned is not checked, only that the
answer is one or more rows. This is a required setting.
@@ -389,7 +391,7 @@
B<login = ">I<username>B<">
-Username to use to login to FTP, IMAP, LDAP, MySQL, POP, PostgreSQL.
+Username to use to login to FTP, IMAP, LDAP, MySQL, POP, PostgreSQL, Oracle.
For Radius the passwd is used for the attribute User-Name.
@@ -402,7 +404,7 @@
=item * FTP: Anonymous
-=item * MySQL and PostgreSQL: Must be specified in the configuration
+=item * MySQL, PostgreSQL and Oracle: Must be specified in the configuration
=item * SIP: ldirectord\@<hostname>, hostname is derived as per the passwd
option below.
@@ -414,7 +416,7 @@
B<passwd = ">I<password>B<">
-Password to use to login to FTP, IMAP, LDAP, MySQL, POP, PostgreSQL
+Password to use to login to FTP, IMAP, LDAP, MySQL, POP, PostgreSQL, Oracle
and SIP servers.
For Radius the passwd is used for the attribute User-Password.
@@ -428,14 +430,14 @@
run time, or sourced from uname if unset.
=item * Otherwise: empty string.
- In the case of LDAP, MySQL and PostgreSQL this means
+ In the case of LDAP, MySQL, PostgreSQL and Oracle this means
that authentication will not be performed.
=back 4
B<database = ">I<databasename>B<">
-Database to use for MySQL and PostgreSQL servers, this is the database that
+Database to use for MySQL, PostgreSQL or Oracle servers, this is the database
that
the query (set by B<receive> above) will be performed against. This is a
required setting.
@@ -843,7 +845,7 @@
# If we get a sinal then log it and quit
sub ld_handler_term
{
- my ($signal) = (@_);
+ my ($signal) = (@_);
if (defined $DAEMON_TERM) {
$SIG{'__DIE__'} = "IGNORE";
@@ -1145,8 +1147,8 @@
}
} elsif ($rcmd =~ /^service\s*=\s*(.*)/) {
lc($1);
- $1 =~ /(\w+)/ && ($1 eq "http" || $1 eq
"https" || $1 eq "ldap" || $1 eq "ftp" || $1 eq "none" || $1 eq "smtp" || $1 eq
"pop" || $1 eq "pops" || $1 eq "imap" || $1 eq "imaps" || $1 eq "nntp" || $1 eq
"dns" || $1 eq "mysql" || $1 eq "pgsql" || $1 eq "radius" || $1 eq "sip")
- or &config_error($line, "service
must be http, https, ftp, smtp, pop, pops, imap, imaps, ldap, nntp, dns, mysql,
pgsql, radius, sip, or none");
+ $1 =~ /(\w+)/ && ($1 eq "http" || $1 eq
"https" || $1 eq "ldap" || $1 eq "ftp" || $1 eq "none" || $1 eq "smtp" || $1 eq
"pop" || $1 eq "pops" || $1 eq "imap" || $1 eq "imaps" || $1 eq "nntp" || $1 eq
"dns" || $1 eq "mysql" || $1 eq "pgsql" || $1 eq "oracle" || $1 eq "radius" ||
$1 eq "sip")
+ or &config_error($line, "service
must be http, https, ftp, smtp, pop, pops, imap, imaps, ldap, nntp, dns, mysql,
pgsql, oracle, radius, sip, or none");
$vsrv{service} = $1;
if($vsrv{service} eq "ftp" and
$vsrv{login} eq "") {
@@ -1384,10 +1386,13 @@
}
elsif ($vsrv->{port} eq "3306") {
$vsrv->{service} = "mysql";
- }
+ }
elsif ($vsrv->{port} eq "5432") {
$vsrv->{service} = "pgsql";
}
+ elsif ($vsrv->{port} eq "1521") {
+ $vsrv->{service} = "oracle";
+ }
elsif ($vsrv->{port} eq "5060") {
$vsrv->{service} = "sip";
}
@@ -2061,6 +2066,8 @@
$$r{num_connects} = 0 if
(check_mysql($v, $r));
} elsif ($$v{service} eq "pgsql") {
$$r{num_connects} = 0 if
(check_pgsql($v, $r));
+ } elsif ($$v{service} eq "oracle") {
+ $$r{num_connects} = 0 if
(check_oracle($v, $r));
} else {
$$r{num_connects} = 0 if
(check_none($v, $r));
}
@@ -2460,6 +2467,11 @@
return check_sql(@_, "Pg", "dbname");
}
+sub check_oracle
+{
+ return check_sql(@_, "Oracle", "");
+}
+
sub check_sql
{
require DBI;
@@ -2470,43 +2482,44 @@
$query =~ s#^/##;
unless ($$v{login} && $query) {
service_set($v, $r, "down");
- &ld_log("Error: Must specify a login and request string for
mysql and postgresql checks. Not adding $$r{server}.\n");
+ &ld_log("Error: Must specify a login and request string for
mysql, postgresql or oracle checks. Not adding $$r{server}.\n");
return 1;
}
$result=2; # Set result flag. Only ok if ends up at zero.
&ld_debug(2, "Checking $$v{server} server=$$r{server} port=$port\n");
$dbh =
DBI->connect("dbi:$dbd:$dbname=$$v{database};host=$$r{server};port=$port",
$$v{login}, $$v{passwd});
unless ($dbh) {
- &ld_debug(4, "Failed to bind to $$r{server} with $dbh->err");
+ &ld_debug(4, "Failed to bind to $$r{server} with
$dbh->errstr()");
service_set($v, $r, "down");
return 1;
}
$result--;
$sth = $dbh->prepare($query);
- $rows = $sth->execute;
- ld_debug(4, "Database search returned $rows rows");
+ unless ($sth) {
+ &ld_log("Error preparing statement:" . $dbh->errstr() . ". Not
adding $$r{server}.\n");
+ $dbh->disconnect();
+ return 1;
+ }
+ $rows = $sth->execute();
+ &ld_debug(4, "Database search returned $rows rows");
if ($rows gt 0) {
# If it returns with a number, it is ok.
# Disallows query of an empty table.
+ # Only works with select and update statements, however
+ # most people will want to use select statements for
+ # health checks.
$result--;
- }
- # If user defined a receive string (number of rows returned), only do
- # the check if the previous fetchall_arrayref succeeded.
- #if (defined $$r{receive} && $result eq 0) {
- # # Receive string specifies an exact number of rows
- # if ($rows ne $$r{receive}) {
- # ld_debug(2,"Service down, receive=$$r{receive}");
- # $result=1;
- # }
- #}
- if ($result == 1) {
- # Should never get here
+ } else {
+ # Should never get here (why? --ratz)
+ &ld_log("Prior executing statement returned $rows rows: not
adding $$r{server}.\n");
service_set($v, $r, "down");
+ $sth->finish();
+ $dbh->disconnect();
return 1;
}
service_set($v, $r, "up");
- $sth->finish;
- $dbh->disconnect;
+ $sth->finish();
+ $dbh->disconnect();
return 0;
}
|