<?php defined('SYSPATH') or die('No direct access allowed.');

/**
 *
 * @package    PTA
 * @subpackage Nodes
 * @category   Models
 * @author     Deon George
 * @copyright  (c) 2010 phpTSMadmin Development Team
 * @license    http://phptsmadmin.sf.net/license.html
 */
class Model_NODE extends ORM_TSM {
	protected $_table_name = 'NODES';
	protected $_primary_key = 'NODE_NAME';
	protected $_sorting = array(
		'NODE_NAME'=>'ASC',
	);

	protected $_has_one = array(
		'DOMAIN'=>array('foreign_key'=>'DOMAIN_NAME','far_key'=>'DOMAIN_NAME'),
	);
	protected $_has_many = array(
		'ACTLOG'=>array('foreign_key'=>'NODENAME','far_key'=>'NODE_NAME'),
		'FILESPACE'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODE_NAME'),
		'VOLUMEUSAGE'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODE_NAME'),
		'ASSOCIATION'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODE_NAME'),
		'MGMTCLASS'=>array('foreign_key'=>'DOMAIN_NAME','far_key'=>'DOMAIN_NAME'),
		'CLIENTOPT'=>array('foreign_key'=>'OPTIONSET_NAME','far_key'=>'OPTION_SET'),
		'SUMMARY'=>array('foreign_key'=>'ENTITY','far_key'=>'NODE_NAME'),
		'EVENT'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODE_NAME'),
		'OCC'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODE_NAME'),
	);

	protected $_tsm = array(
		'db2'=>array(
			'_primary_key'=>'NODENAME',
			'_sorting'=>array(
				'NODENAME'=>'ASC',
			),
			'_has_one'=>array(
				'DOMAIN'=>array('foreign_key'=>'DOMAIN_NAME','far_key'=>'DOMAINNAME'),
			),
			'_has_many'=>array(
				'FILESPACE'=>array('foreign_key'=>'NODEID','far_key'=>'NODEID'),
				'VOLUMEUSAGE'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODENAME'),
				'ASSOCIATION'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODENAME'),
				'MGMTCLASS'=>array('foreign_key'=>'DOMAIN_NAME','far_key'=>'DOMAIN_NAME'),
				'CLIENTOPT'=>array('foreign_key'=>'OPTIONSET_NAME','far_key'=>'OPTIONSET'),
				'SUMMARY'=>array('foreign_key'=>'ENTITY','far_key'=>'NODENAME'),
				'EVENT'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODENAME'),
				'OCC'=>array('foreign_key'=>'NODE_NAME','far_key'=>'NODENAME'),
			),
			'translate'=>array(
				'NODE_NAME'=>'NODENAME',
				'CLIENT_VERSION'=>'CLNTVERSION',
				'CLIENT_RELEASE'=>'CLNTRELEASE',
				'CLIENT_LEVEL'=>'CLNTLEVEL',
				'CLIENT_SUBLEVEL'=>'CLNTSUBLEVEL',
				'PLATFORM_NAME'=>'OSNAME',
				'CLIENT_OS_LEVEL'=>'CLNTOSLEVEL',
				'LASTACC_TIME'=>'LACDATE',
				'REG_TIME'=>'REGDATE',
				'PWSET_TIME'=>'PWSETDATE',
				'LASTSESS_SENT'=>'SESSSENT',
				'LASTSESS_RECVD'=>'SESSRECVD',
				'LASTSESS_DURATION'=>'SESSDURATION',
				'LASTSESS_IDLEWAIT'=>'SESSIDLEWAIT',
				'LASTSESS_COMMWAIT'=>'SESSCOMMWAIT',
				'LASTSESS_MEDIAWAIT'=>'SESSMEDIAWAIT',
				'TCP_ADDRESS'=>NULL,
				'EMAIL_ADDRESS'=>NULL,
				'REG_ADMIN'=>'REGISTRAR',
				'PASSEXP'=>NULL,
				'INVALID_PW_COUNT'=>'INVPWCOUNT',
				'LOCKED'=>'LOCKSTATE',
				'DOMAIN_NAME'=>'DOMAINNAME',
				'OPTION_SET'=>'OPTIONSET',
				'COLLOCGROUP_NAME'=>NULL,
				'COMPRESSION'=>'COMPRESS',
				'ARCHDELETE'=>'ARCHDEL',
				'BACKDELETE'=>'BACKDEL',
				'KEEP_MP'=>NULL,
				'MAX_MP_ALLOWED'=>'MAXNUMMP',
			),
		),
	);

	protected $_display_filters = array(
		'REG_TIME'=>array(
			array('ORM_TSM::date',array(':value','d-M-Y')),
		),
		'PWSET_TIME'=>array(
			array('ORM_TSM::date',array(':value','d-M-Y')),
		),
		'LASTACC_TIME'=>array(
			array('ORM_TSM::date',array(':value','d-M-Y')),
		),
		'LASTSESS_SENT'=>array(
			array('number_format',array(':value',0)),
		),
		'LASTSESS_RECVD'=>array(
			array('number_format',array(':value',0)),
		),
		'LASTSESS_DURATION'=>array(
			array('number_format',array(':value',2)),
		),
		'LASTSESS_IDLEWAIT'=>array(
			array('number_format',array(':value',2)),
		),
		'LASTSESS_COMMWAIT'=>array(
			array('number_format',array(':value',2)),
		),
		'LASTSESS_MEDIAWAIT'=>array(
			array('number_format',array(':value',2)),
		),
	);

	/**
	 * Get all the ACTIVITIY LOG for this NODE
	 */
	private function _actlog() {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s',__METHOD__,$this->NODE_NAME);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			// We cant load all records here, like we do with the others, there is too much data!
			$result = $this->ACTLOG->find_all();

			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Get all the ACTIVITY SUMMARY for this NODE
	 */
	private function _actsum() {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s',__METHOD__,$this->NODE_NAME);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$result = array();

			// In the interest of performance, we load all the records and get PHP to process it.
			// Our ORM caching we reduce the hit on TSM.
			foreach (ORM::factory('ACTSUM')->find_all() as $o)
				if ($o->ENTITY == $this->NODE_NAME)
					array_push($result,$o);

			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Get all the FILESPACES for this NODE
	 */
	private function _filespaces() {
		$result = array();

		// In the interest of performance, we load all the records and get PHP to process it.
		// Our ORM caching we reduce the hit on TSM.
		foreach (ORM::factory('FILESPACE')->find_all() as $o)
			if ($o->NODE_NAME == $this->NODE_NAME)
				array_push($result,$o);

		return $result;
	}

	/**
	 * Get all the OCCUPANCY for this NODE
	 */
	private function _occupancy() {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s',__METHOD__,$this->NODE_NAME);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$result = array();

			// In the interest of performance, we load all the records and get PHP to process it.
			// Our ORM caching we reduce the hit on TSM.
			foreach (ORM::factory('OCC')->find_all() as $o)
				if ($o->NODE_NAME == $this->NODE_NAME)
					array_push($result,$o);

			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Get all the VOLUMES for this NODE
	 */
	private function _volumeusage() {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s',__METHOD__,$this->NODE_NAME);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$result = array();

			// In the interest of performance, we load all the records and get PHP to process it.
			// Our ORM caching we reduce the hit on TSM.
			foreach (ORM::factory('VOLUMEUSAGE')->find_all() as $o)
				if ($o->NODE_NAME == $this->NODE_NAME)
					array_push($result,$o);

			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Return the version of the TSM client
	 */
	public function version() {
		if ($this->CLIENT_VERSION)
			return sprintf('%s.%s.%s.%s',$this->CLIENT_VERSION,$this->CLIENT_RELEASE,$this->CLIENT_LEVEL,$this->CLIENT_SUBLEVEL);
		else
			return '';
	}

	/**
	 * Return the OS version for the TSM client
	 */
	public function platform() {
		return sprintf('%s %s',$this->PLATFORM_NAME,$this->CLIENT_OS_LEVEL ? '('.$this->CLIENT_OS_LEVEL.')' : '');
	}

	// @todo This needs to return the global configuration.
	public function passexp() {
		if ($this->PASSEXP)
			return 'TBA';
		else
			return _('No Set');
	}

	// @todo This needs to be validated as a correct calculation
	public function lasttransferpercent() {
		$x = 100-($this->LASTSESS_IDLEWAIT+$this->LASTSESS_COMMWAIT+$this->LASTSESS_MEDIAWAIT);
		return $x < 0 ? 0 : $x;
	}

	// @todo This needs to be validated as a correct calculation
	public function lasttransfertime() {
		if ($this->LASTSESS_DURATION)
			return $this->LASTSESS_DURATION*($this->lasttransferpercent()/100);
		else
			return 0;
	}

	// @todo This needs to be validated as a correct calculation
	public function lastsendperformance() {
		if ($this->lasttransfertime())
			return $this->LASTSESS_SENT/$this->lasttransfertime()/1024/1024;
		else
			return 0;
	}

	// @todo This needs to be validated as a correct calculation
	public function lastreceiveperformance() {
		if ($this->lasttransfertime())
			return $this->LASTSESS_RECVD/$this->lasttransfertime()/1024/1024;
		else
			return 0;
	}

	/**
	 * The last sent aggregate performance
	 */
	public function lastsendaggperformance() {
		if ((real)$this->LASTSESS_DURATION)
			return $this->LASTSESS_SENT/$this->LASTSESS_DURATION/1024/1024;
		else
			return 0;
	}

	/**
	 * The last receive aggregate performance
	 */
	public function lastreceiveaggperformance() {
		if ((real)$this->LASTSESS_DURATION)
			return $this->LASTSESS_RECVD/$this->LASTSESS_DURATION/1024/1024;
		else
			return 0;
	}

	// @todo This should return the system setting (cloptset), if the node setting is not configured.
	public function txngroupmax() {
		return $this->TXNGROUPMAX;
	}

	// Test to see if a node has any data of type
	// @param $type is BACKUP/ARCHIVE/SPACE MANAGED
	public function hasData($type) {
		return $this->vols_byctype($type) ? TRUE : FALSE;
	}

	public function activity() {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s',__METHOD__,$this->NODE_NAME);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$result = array();

			$result = $this->ACTLOG->ExcludeBA()->find_all();

			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Get all the ACTIVITY LOG information for a SESSION
	 * @param $sid Session ID
	 * @param $start Session Start Time (to illiminate any duplication session data)
	 */
	public function actlog_session($sid,$start) {
		$result = array();

		foreach ($this->_actlog() as $alo)
			if ($alo->SESSION == $sid AND $alo->start() >= $start)
				array_push($result,$alo);

		return $result;
	}

	/**
	 * Return the ACTIVITY of this NODE
	 * @param $type is Bkup/Arch/SpMg
	 */
	public function act_bybtype($type) {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s-%s',__METHOD__,$this->NODE_NAME,$type);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$result = array();

			foreach ($this->_actsum() as $aso)
				if ($aso->ACTIVITY == $this->datatypemap($type))
					array_push($result,$aso);

			Sort::MASort($result,'SCHEDULE_NAME,START_TIME');
			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Return the Schedules used for all activites of type
	 * @param $type is Bkup/Arch/SpMg
	 */
	public function act_schedules($type) {
		$result = array();

		foreach ($this->act_bybtype($type) as $ao)
			if (! in_array($ao->SCHEDULE_NAME,$result))
				array_push($result,$ao->SCHEDULE_NAME);

		return $result;
	}

	/**
	 * Return the BACKUP TYPES used by this NODE
	 * ie: Bkup/Arch/SpMg
	 */
	public function btypes() {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s',__METHOD__,$this->NODE_NAME);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$result = array();

			foreach ($this->_occupancy() as $oo)
				if (! in_array($oo->TYPE,$result))
					array_push($result,$oo->TYPE);

			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Return the total of a field for this NODE has by backup TYPE
	 * @param $field the field to check
	 * @param $data the value of that field to match
	 * @param $metric is metric of the storpage pool, eg: NUM_FILES
	 */
	private function _data_int($field,$data,$metric) {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s-%s-%s-%s',__METHOD__,$this->NODE_NAME,$field,$data,$metric);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$result = 0;

			foreach ($this->_occupancy() as $oo)
				if ($oo->{$field} == $data)
					$result += $oo->{$metric};

			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Return the data that this NODE has in a STORAGE POOL by backup TYPE
	 * @param $pool is STORAGE POOL NAME
	 * @param $metric is metric of the storpage pool, eg: NUM_FILES
	 * @param $type is Bkup/Arch/SpMg
	 */
	private function _data_bypoolbybtype($pool,$metric,$type) {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s-%s-%s-%s',__METHOD__,$this->NODE_NAME,$pool,$metric,$type);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$result = 0;

			foreach ($this->_occupancy() as $oo)
				if ($oo->STGPOOL_NAME == $pool AND $oo->TYPE == $type)
					$result += $oo->{$metric};

			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Return the FILES that this NODE has by backup TYPE
	 * @param $type is Bkup/Arch/SpMg
	 */
	public function file_bybtype($type) {
		Log::instance()->add(LOG::DEBUG,'FLYBY :method',array(':method'=>__METHOD__));
		return $this->_data_int('TYPE',$type,'NUM_FILES');
	}

	/**
	 * Return the FILES that this NODE has in a STORAGE POOL
	 * @param $pool is STORAGE POOL NAME
	 */
	public function file_bypool($pool) {
		Log::instance()->add(LOG::DEBUG,'FLYBY :method',array(':method'=>__METHOD__));
		return $this->_data_int('STGPOOL_NAME',$pool,'NUM_FILES');
	}

	public function file_bypoolbybtype($pool,$type) {
		Log::instance()->add(LOG::DEBUG,'FLYBY :method',array(':method'=>__METHOD__));
		return $this->_data_bypoolbybtype($pool,'NUM_FILES',$type);
	}

	/**
	 * Return the FILES that this NODE has in a STORAGE POOL TYPE
	 * @param $type is ACTIVEDATA/PRIMARY/COPY
	 */
	public function file_byptype($type) {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$result = 0;

		foreach ($this->stgpools_byptype($type) as $spo)
			$result += $this->file_bypool($spo);

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	public function fs() {
		return $this->_filespaces();
	}

	/**
	 * Return a Graph of the Schedule Backup Activity
	 * @param $type is Bkup/Arch/SpMg
	 * @see [node/json_backup]
	 */
	public function graph_backup($type='Bkup',$schedule='') {
		$chart = 'ComboChart';

		$google = GoogleChart::factory($chart)
			->title(sprintf('%s Activity',$type))
			->div(sprintf('%s_%s',$type,$schedule))
			->dataurl(URL::site(sprintf('node/ajax_jsonbackup/%s?c=%s&s=%s&t=%s',$this->NODE_NAME,$chart,$schedule,$type)));

		return (string)$google;
	}

	/**
	 * Return the LOGICAL_MB that this NODE has by backup TYPE
	 * @param $type is Bkup/Arch/SpMg
	 */
	public function logmb_bybtype($type) {
		Log::instance()->add(LOG::DEBUG,'FLYBY :method',array(':method'=>__METHOD__));
		return $this->_data_int('TYPE',$type,'LOGICAL_MB');
	}

	/**
	 * Return the LOGICAL_MB that this NODE has in a STORAGE POOL
	 * @param $pool is STORAGE POOL NAME
	 */
	public function logmb_bypool($pool) {
		Log::instance()->add(LOG::DEBUG,'FLYBY :method',array(':method'=>__METHOD__));
		return $this->_data_int('STGPOOL_NAME',$pool,'LOGICAL_MB');
	}

	public function logmb_bypoolbybtype($pool,$type) {
		Log::instance()->add(LOG::DEBUG,'FLYBY :method',array(':method'=>__METHOD__));
		return $this->_data_bypoolbybtype($pool,'LOGICAL_MB',$type);
	}

	/**
	 * Return the FILES that this NODE has in a STORAGE POOL TYPE
	 * @param $type is ACTIVEDATA/PRIMARY/COPY
	 */
	public function logmb_byptype($type) {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$result = 0;

		foreach ($this->stgpools_byptype($type) as $spo)
			$result += $this->logmb_bypool($spo);

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	public function occupancy() {
		return $this->_occupancy();
	}

	/**
	 * Return the STORAGE POOLS this NODE has data in
	 */
	public function stgpools() {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s',__METHOD__,$this->NODE_NAME);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$x = $result = array();

			foreach ($this->_occupancy() as $oo)
				if (! in_array($oo->STGPOOL_NAME,$x)) {
					array_push($result,$oo->STGPOOL);
					array_push($x,$oo->STGPOOL_NAME);
				}

			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Return the STORAGE POOL TYPES used by this NODE
	 * ie: ACTIVE/PRIMARY/COPY
	 * @todo This should be sorted by PRIMARY/ACTIVE/COPY
	 */
	public function stgpooltypes() {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s',__METHOD__,$this->NODE_NAME);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$result = array();

			foreach ($this->stgpools() as $spo)
				if (! in_array($spo->POOLTYPE,$result))
					array_push($result,$spo->POOLTYPE);

			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Return the STORAGE POOLS that this NODE uses by BACKUP TYPE
	 * @param $type is Bkup/Arch/SpMg
	 */
	public function stgpools_bybtype($type) {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s-%s',__METHOD__,$this->NODE_NAME,$type);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$x = $result = array();

			foreach ($this->_occupancy() as $oo)
				if ($oo->TYPE == $type AND ! in_array($oo->STGPOOL_NAME,$x)) {
					array_push($result,$oo->STGPOOL);
					array_push($x,$oo->STGPOOL_NAME);
				}

			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Return the STORAGE POOLS that this NODE uses by BACKUP TYPE
	 * @param $type is ACTIVEDATA/PRIMARY/COPY
	 */
	public function stgpools_byptype($type) {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s-%s',__METHOD__,$this->NODE_NAME,$type);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$result = array();

			foreach ($this->stgpools() as $spo)
				if ($spo->POOLTYPE == $type)
					array_push($result,$spo);

			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	public function vols_bybtype($type) {
		return $this->vols_byctype($this->datatypemap($type));
	}

	private function _vols_metric($metric,$data) {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s-%s-%s',__METHOD__,$this->NODE_NAME,$metric,$data);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$x = $result = array();

			foreach ($this->_volumeusage() as $vuo)
				if ($vuo->{$metric} == $data AND ! in_array($vuo->VOLUME_NAME,$x)) {
					array_push($result,$vuo->VOLUME);
					array_push($x,$vuo->VOLUME_NAME);
				}

			Sort::MASort($result,'VOLUME_NAME');
			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Return the VOLUMES that this NODE uses by BACKUP TYPE
	 * @param $type is BACKUP/ARCHIVE/SPACE MANAGED
	 */
	public function vols_byctype($type) {
		return $this->_vols_metric('COPY_TYPE',$type);
	}

	/**
	 * Return the VOLUMES that this NODE uses
	 * @param $pool is STORAGE POOL NAME
	 */
	public function vols_bypool($pool) {
		return $this->_vols_metric('STGPOOL_NAME',$pool);
	}

	/**
	 * Return the VOLUMES that this NODE has in a STORAGE POOL TYPE
	 * @param $type is ACTIVEDATA/PRIMARY/COPY
	 */
	public function vols_byptype($type) {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$result = array();

		foreach ($this->stgpools_byptype($type) as $spo)
			$result = array_merge($result,$this->vols_bypool($spo));

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	/**
	 * Return the VOLUMES that this NODE uses by POOL and BACKUP TYPE
	 * @param $pool is STORAGE POOL NAME
	 * @param $type is Bkup/Arch/SpMg
	 */
	public function vols_bypoolbybtype($pool,$type) {
		return $this->vols_bypoolbyctype($pool,$this->datatypemap($type));
	}

	/**
	 * Return the VOLUMES that this NODE uses by POOL and BACKUP TYPE
	 * @param $pool is STORAGE POOL NAME
	 * @param $type is BACKUP/ARCHIVE/SPACE MANAGED
	 */
	public function vols_bypoolbyctype($pool,$type) {
		Log::instance()->add(LOG::DEBUG,'ENTER :method',array(':method'=>__METHOD__));

		$k = sprintf('%s-%s-%s-%s',__METHOD__,$this->NODE_NAME,$pool,$type);
		$c = Kohana::$config->load('config')->cache;

		if (is_null($result = Cache::instance($c)->get($k))) {
			$result = array();

			foreach ($this->_volumeusage() as $vuo)
				if ($vuo->STGPOOL_NAME == $pool AND $vuo->COPY_TYPE == $type AND ! in_array($vuo->VOLUME_NAME,$result))
					array_push($result,$vuo->VOLUME);

			Sort::MASort($result,'VOLUME_NAME');
			// @todo Cache time should be configurble
			Cache::instance($c)->set($k,$result,300);
		}

		Log::instance()->add(LOG::DEBUG,'EXIT :method',array(':method'=>__METHOD__));
		return $result;
	}

	public function volumeusage() {
		return $this->_volumeusage();
	}
}
?>
