OraMon.java 5.68 KB
package se.lil.om;

import java.sql.*;
import java.util.Properties;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class OraMon {
	Connection conn = null;
	String conString = "jdbc:oracle:thin:@//hostname:1521/SID";
	String conUser = "system";
	String conPass = "passw0rd";
	String dbName = null;
	
	Collector col = new Collector();
	
	int getDataCalls = 0;
	int getDataSucess = 0;
	
	public int getDataCalled() {
		return getDataCalls;
	}
	
	public int getDataSucceeded() {
		return getDataSucess;
	}
	
	public int getDataFailed() {
		return getDataCalls - getDataSucess;
	}
	
	public String getConString() {
		return this.conString;
	}
	
	//NUM_CPUS
	int numCpus = 0;
	public long getNumberOfCPUs() throws Throwable {
		return numCpus;
	}
	
	//DB CPU
	LongDelta cpuTime = new LongDelta();
	public double getCPUPercent() throws Throwable {
		double perSec = cpuTime.getPerSecondValue();
		double totSec = numCpus * 1000;
		double percent = (perSec / totSec) * 100;
		return percent;
	}
	
	public long getCPUTimePerSecond() throws Throwable {
		return cpuTime.getPerSecondValue();
	}

	public long getPerSecondValue(String name) throws Throwable {
		return col.getPerSecValue(name);
	}
	
	public String getDBName() throws Throwable {
		return this.dbName;
	}
	
	public double getBufferCacheHitRatioPercent() throws Throwable {
		double conGetsCache = getPerSecondValue("consistent gets from cache");
		double dbBlocksCache = getPerSecondValue("db block gets from cache");
		double physReadsCache = getPerSecondValue("physical reads cache");
		if (conGetsCache + dbBlocksCache + physReadsCache == 0) {
			return 100;
		}
		if (conGetsCache + dbBlocksCache == 0 && physReadsCache > 0) {
			return 0;
		}
		double buffCacheHitRatio = 1 - (physReadsCache/(conGetsCache + dbBlocksCache));
		return buffCacheHitRatio * 100;
	}
	
	public double getCacheHitRatioPercent() throws Throwable {
		double conGets = getPerSecondValue("consistent gets");
		double dbBlocks = getPerSecondValue("db block gets");
		double physReads = getPerSecondValue("physical reads");
		if (conGets + dbBlocks + physReads == 0) {
			return 100;
		}
		if (conGets + dbBlocks == 0 && physReads > 0) {
			return 0;
		}
		double cacheHitRatio = 1 - (physReads/(conGets + dbBlocks));
		return cacheHitRatio * 100;
	}
	
	public long getLogicalReadsPerSecond() throws Throwable {
		return getPerSecondValue("consistent gets") + getPerSecondValue("db block gets");
	}
	
	long lastRTns = 0;
	public long getLastRTms() {
		return lastRTns / (1000 * 1000);
	}
	
	long lastFetchTSns = 0;
	public boolean getData(long ageTs) throws Throwable {
		if ((System.nanoTime() - lastFetchTSns) > (ageTs * 1000 * 1000 * 1000)) return getData();
		else return false;
	}
	
	public long getAgeTs() {
		return (System.nanoTime() - lastFetchTSns)/(1000*1000*1000);
	}
	
	Lock lock = new ReentrantLock();
	
 	public boolean getData() throws Throwable {
 		// Start thread safe
 		// Try to get a lock
 		boolean haveLock = lock.tryLock();
		if( haveLock == false) {
			// We could not get the lock, someone else is updating. Wait for it to complete by waiting for a lock, then unlock and return.
			try {
				lock.lock();
			} finally {
				lock.unlock();
			}
			return false;
		}
		// We do have the lock. Do the rest in a try catch everything and if we catch anything, re throw the catch but always release the lock.
		try {
	 		long startTSns = System.nanoTime();
	 		getDataCalls++;
	 		if(conn == null) open();
	 		if(conn.isClosed()) open();
	 		boolean stale = true;
	 		try {
	 			if (conn.isValid(20)) {
	 				stale = false;
	 			}
	 		} catch (SQLException e) {
	 			stale = true;
	 		}
	 		if(stale) {
	 			open();
	 		}
			Statement stmt = conn.createStatement();
			ResultSet rset = null;
			
			//Get the database name once
			if(this.dbName == null) {
				rset = stmt.executeQuery("select value from V$SYSTEM_PARAMETER where name = 'db_name'");
				rset.next();
				this.dbName = rset.getString(1);
				rset.close(); 
			}
			
			//Get values for CPU calculation
			rset = stmt.executeQuery("select value from V$OSSTAT where STAT_NAME = 'NUM_CPUS'");
			rset.next();
			this.numCpus = rset.getInt(1);
			rset.close(); 
			
			cpuTime.update(stmt.executeQuery("select systimestamp, value from V$SYS_TIME_MODEL where stat_name='DB CPU'"), true);
	
			// Get the entire V_$SYSSTAT table from DB
			col.update(stmt.executeQuery("select systimestamp, name, value from V$SYSSTAT"));
			
			stmt.close(); 
			getDataSucess++;
			lastFetchTSns = System.nanoTime();
			lastRTns = lastFetchTSns - startTSns;
			return true;
		} catch (Throwable e) {
			throw (e);
		} finally {
			lock.unlock();
		}
		// End thread safe
	}
	
	public OraMon() {
		// TODO Auto-generated constructor stub
	}
	
	public OraMon(String con, String user, String pass) {
		this.conString = con;
		this.conUser = user;
		this.conPass = pass;
	}
	
	public void open() throws Throwable {
		Class.forName ("oracle.jdbc.OracleDriver");
		Properties jdbcProps = new Properties();
		jdbcProps.put("user", conUser);
		jdbcProps.put("password", conPass);
		jdbcProps.put("v$session.program","LIL Oracle Monitor");
		this.conn = DriverManager.getConnection(conString, jdbcProps);
		
	}
	
	public void open(String con, String user, String pass) throws Throwable {
		Class.forName ("oracle.jdbc.OracleDriver");
		if(con != null) this.conString = con;
		if(user != null) this.conUser = user;
		if(pass != null) this.conPass = pass;
		Properties jdbcProps = new Properties();
		jdbcProps.put("user", conUser);
		jdbcProps.put("password", conPass);
		jdbcProps.put("v$session.program","LIL Oracle Monitor");
		this.conn = DriverManager.getConnection(conString, jdbcProps);
	}
	
	public void close() throws Throwable {
		if(conn != null) conn.close();
	}
}