class Net::Ping::TNS
The Ping::TNS
class encapsulates the information and behavior of tns ping.
Constants
- VERSION
The version of the net-tnsping library.
Attributes
Database name.
Database source name.
Database name.
The name of the oracle driver to use for connections. Defaults to OCI8.
Database source name.
The name of the host the database sits on.
A list of hosts for the given database name.
The value of your ORACLE_HOME or ORA_HOME environment variable.
The value of your ORACLE_HOME or ORA_HOME environment variable.
The value of your ORACLE_HOME or ORA_HOME environment variable.
The port used when attempting a connection. The default is 1521.
A list of ports for the given database name
The toplevel tns admin path.
The full path to the tnsnames.ora file.
Public Class Methods
Creates and returns a new Ping::TNS
object. If the db specified cannot be found in the tnsnames.ora file, then a Ping::TNS::Error
is raised.
# File lib/net/tnsping.rb, line 49 def initialize(database, driver='OCI8', host=nil, port=1521, timeout=5) @database = database @dsn = "dbi:#{driver}:" << database @host = host @timeout = timeout @port = port @driver = driver @ports = [] # There can be more than one host/port @hosts = [] # for each dsn. Try them in order. @sid = nil @tns_admin = ENV['TNS_ADMIN'] @ora_home = ENV['ORACLE_HOME'] || ENV['ORA_HOME'] if @tns_admin @tns_file = File.join(@tns_admin, 'tnsnames.ora') elsif @ora_home @tns_file = File.join(@ora_home, 'network', 'admin', 'tnsnames.ora') else home = ENV['HOME'] || ENV['USERPROFILE'] @tns_file = File.join(home, 'tnsnames.ora') end yield self if block_given? # If the host is not specified, look for it in the tnsnames.ora file if host.nil? err_msg = "tnsnames.ora file could not be found" raise Error, err_msg unless File.exists?(@tns_file) parse_tns_file else @hosts.push(host) @ports.push(port) end end
Public Instance Methods
Performs a TCP ping on the listener. The host and port are determined from your tnsnames.ora file. If more than one host and/or port are found in the tnsnames.ora file, then each will be tried. So long as at least one of them connects successfully, true is returned.
If you specify a host and port in the constructor, then the attempt will only be made against that host on the given port.
Remember, this only pings the listener. If you want to ping the listener and the database, use the ping_all? method.
# File lib/net/tnsping.rb, line 108 def ping? if @hosts.empty? raise Error, "No hosts found" end # Use 1521 if no ports were found in the tnsnames.ora file. if @ports.empty? @ports.push(@port) end # If the host is provided, only ping that host if @host 0.upto(@ports.length-1){ |n| @port = @ports[n] return super } else 0.upto(@ports.length-1){ |n| @port = @ports[n] @host = @hosts[n] return super } end end
Simple wrapper for ping_listener? + ping_database?
# File lib/net/tnsping.rb, line 176 def ping_all? return false unless self.ping_listener? return false unless self.ping_database? true end
Attempts to make a connection using a bogus login and password via the DBI class. If an ORA-01017 Oracle error is returned, that means the database is up and running and true is returned.
Note that each of the arguments for this method use the defaults passed to the constructor (or have a default otherwise set). You generally should not pass any arguments to this method. In the event that this method fails, false is returned and the error can be viewed via Ping::TNS#exception.
# File lib/net/tnsping.rb, line 147 def ping_database?(dsn=@dsn, timeout=@timeout, user=@sid, passwd=Time.now.to_s) re = /ORA-01017/ dbh = nil user ||= Time.now.to_s rv = false begin Timeout.timeout(timeout){ dbh = DBI.connect(dsn,user,passwd) } rescue DBI::DatabaseError => e if re.match(e.to_s) rv = true else @exception = e end rescue Timeout::Error, StandardError => e @exception = e ensure if dbh dbh.disconnect if dbh.connected? end end rv end
Sets the port that the Ping::TNS#ping_listener?
method will use. If this is set, then a ping will only be attempted on this port regardless of what is in the tnsnames.ora file.
# File lib/net/tnsping.rb, line 89 def port=(num) @port = num @ports = [num] end
Private Instance Methods
Search for the dsn entry within the tnsnames.ora file and get the host and port information. Private method.
# File lib/net/tnsping.rb, line 189 def parse_tns_file(file=@tns_file, db=@database) re_blank = /^$/ re_comment = /^#/ re_tns_sentry = /^#{db}.*?=/i # specific entry re_tns_gentry = /^\w.*?=/ # generic entry re_tns_pair = /\w+\s*\=\s*[\w\.-]+/ # used to parse key=val re_keys = /\bhost\b|\bport\b|\bsid\b/i data_string = "" found = false IO.foreach(file){ |line| next if re_blank.match(line) next if re_comment.match(line) line.chomp! # Skip over lines until an entry for the db is found. match = re_tns_sentry.match(line) if match found = true data_string << match.post_match # slurp the rest of the line next end # Once found, slurp the lines into a variable until the next # db entry is encountered. if found break if re_tns_gentry.match(line) line.strip! data_string << line end } unless found raise Error, "unable to find '#{db}' in #{file}" end # Break each 'key = value' line into its parts data_string.scan(re_tns_pair).each{ |pair| key, value = pair.split("=") key.strip! value.strip! next unless re_keys.match(key) case key.downcase when 'host' @hosts.push(value) when 'port' @ports.push(value.to_i) when 'sid' @sid = value end } end