Home | History | Annotate | Download | only in srm
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright (c) 2001 by Sun Microsystems, Inc.
     23  * All rights reserved.
     24  *
     25  * DataModel.java
     26  */
     27 
     28 package com.sun.wbem.solarisprovider.srm;
     29 
     30 import java.util.HashMap;
     31 import java.util.Vector;
     32 import java.util.Iterator;
     33 
     34 
     35 /**
     36  * Aggregation of all users, projects, and sets metrics data.
     37  * Implements the singleton pattern
     38  * @author Sun Microsystems, Inc.
     39  */
     40 class DataModel {
     41 
     42     private static DataModel		dm;
     43     private static SRMDataReader	dr;
     44     private static boolean		doAlive;
     45     /**
     46      * syncObject guards the calls of SRMDataReader methods between the
     47      * current data model thread and the KeepAlive thread.
     48      */
     49     private static Object		syncObject;
     50     /**
     51      * rdsKeepAliveTimeout: how long the KeepAlive thread should keep
     52      * the connection opened.
     53      */
     54     private static int rdsKeepAliveTimeout = 30 * 60000;
     55     private static KeepAlive	ka;
     56     private static boolean	kaError;
     57     private static boolean  	msacct = false;
     58 
     59     private static final int PROCESSESHASHSIZE = 500;
     60     private static final int USERPROCSHASHSIZE = 200;
     61     private static final int PROJPROCSHASHSIZE = 100;
     62     private static final int USERSHASHSIZE = 200;
     63     private static final int PROJSHASHSIZE = 100;
     64     private static final int L_PRC_SI = 1;
     65     private static final int L_USR_SI = 2;
     66     private static final int L_PRJ_SI = 3;
     67     private static final int L_AC_USR = 4;
     68     private static final int L_AC_PRJ = 5;
     69     private static final int L_SYSTEM = 6;
     70     private static final int L_ALL  = 20;
     71 
     72     // RDS exec command
     73     private static final String RDSPGM = "/usr/sadm/lib/wbem/rds";
     74 
     75     private static final int	TIMEOUTIDX  = 3;
     76     private static final int	INTERVALIDX = 5;
     77 
     78     // RDS commands
     79     private static final String CMD_GETALL	= "-pUuJjS";
     80     private static final String CMD_GETPL	= "-p";
     81     private static final String CMD_GETUL	= "-u";
     82     private static final String CMD_GETAUL	= "-U";
     83     private static final String CMD_GETJL	= "-j";
     84     private static final String CMD_GETAJL	= "-J";
     85     private static final String CMD_GETASL	= "-S";
     86     private static final String CMD_ALIVE	= "alive";
     87     private static final String CMD_EXIT	= "exit";
     88 
     89     private static boolean updating; // set if udpdateing is in progress
     90     private static boolean running;  // set if the rds is running
     91 
     92     private int rdsTimeout;
     93     private int rdsInterval;
     94     private String rdsArgs[];
     95     protected HashMap processes	= new HashMap(PROCESSESHASHSIZE);
     96     protected HashMap users	= new HashMap(USERSHASHSIZE);
     97     protected HashMap userprocs	= new HashMap(USERPROCSHASHSIZE);
     98     protected HashMap projs	= new HashMap(PROJSHASHSIZE);
     99     protected HashMap projprocs	= new HashMap(PROJPROCSHASHSIZE);
    100     protected SystemDataModel sdm = new  SystemDataModel();
    101 
    102     /**
    103      * Default constructor
    104      */
    105     private DataModel() {
    106     }
    107 
    108     /**
    109      * Should be used to obtain the singleton instance of this class
    110      * @return	the singleton instance of this class
    111      */
    112     static DataModel getHandle(Object syncObj) {
    113 
    114     	if (dm == null) {
    115 	    dm = new DataModel();
    116 	    dr = new SRMDataReader(dm);
    117 	    syncObject = syncObj;
    118 	    try {
    119 	    	if (Util.propertyKEEPALIVETIMEOUT != null) {
    120 	    	    rdsKeepAliveTimeout =
    121 		    	Integer.parseInt(Util.propertyKEEPALIVETIMEOUT);
    122 	    	}
    123 	    	if (Util.propertyMSACCT != null) {
    124 	    	    msacct = Util.propertyMSACCT.equalsIgnoreCase("true");
    125 	    	}
    126 	    } catch (Exception e) { };
    127     	}
    128 	return dm;
    129     }
    130 
    131     /**
    132      * Initialize the rds timeouts, the actually opening is deleted
    133      * until the first update call.
    134      */
    135     void open(int rdsTimeout, int rdsInterval) {
    136     	Vector args  = new Vector(6);
    137     	String dbfile = null;
    138 
    139 	this.rdsTimeout = rdsTimeout;
    140 	this.rdsInterval = rdsInterval;
    141     	args.add(RDSPGM);
    142     	args.add("-a");
    143     	args.add("-t");
    144     	args.add(""+rdsTimeout);
    145     	args.add("-i");
    146     	args.add(""+rdsInterval);
    147 	if (Util.propertyRDSDATABASE != null) {
    148     	    args.add("-f");
    149     	    args.add(Util.propertyRDSDATABASE);
    150 	}
    151     	if (Util.propertyMSACCT != null &&
    152 	    Util.propertyMSACCT.equalsIgnoreCase("true")) {
    153     	    args.add("-m");
    154 	}
    155 	if (Util.propertyRDSLOGFILE != null) {
    156     	    args.add("-L");
    157     	    args.add(Util.propertyRDSLOGFILE);
    158 	}
    159 	rdsArgs = new String[args.size()];
    160 	args.toArray(rdsArgs);
    161 
    162     } // end open
    163 
    164     /**
    165      * Close the rds communication pipe.
    166      */
    167     void close() {
    168 
    169 	if (running) {
    170 	    doAlive = false;
    171 	    ka.interrupt();
    172     	    synchronized (syncObject) {
    173 	    	/*
    174 		 * check again, since AliveThread could already close RDS
    175 		 * when this thread was waiting on syncObject
    176 		 */
    177 	    	if (running) {
    178 		    dr.closeRDS();
    179 		    running = false;
    180 		}
    181 	    }
    182 	}
    183 
    184     } // end close
    185 
    186     /**
    187      * Close the rds communication pipe after an error has raised. In this
    188      * case the rds will be shutdown instead of gently closed.
    189      */
    190     void closeONError() {
    191 	doAlive = false;
    192     	ka.interrupt();
    193     	dr.shutdownRDS();
    194     	running = false;
    195     }
    196 
    197     /**
    198      * Get a provider data model object identified by id from the list defined
    199      * by listt.
    200      * @return	the provider data model object or null if other the  list type
    201      *		or the provider object id are unsupported.
    202      */
    203     SRMProviderDataModel getProviderDataModel(int listt, String id) {
    204 
    205 	try {
    206 	    switch (listt) {
    207 		case  L_PRC_SI : return getProcess(Integer.parseInt(id));
    208 		case  L_USR_SI : return getUserprocs(id);
    209 		case  L_PRJ_SI : return getProjprocs(id);
    210 		case  L_AC_USR : return getUser(id);
    211 		case  L_AC_PRJ : return getProject(id);
    212 		case  L_SYSTEM : return sdm;
    213 		default: return null;
    214 	    }
    215 	} catch (NumberFormatException e) {
    216 	    return null;
    217 	}
    218     }
    219 
    220     /**
    221      * Get process metrics object.
    222      * @param	pid the process id
    223      * @return	metrics object with process metrics or new empty
    224      *		object at first call.
    225      */
    226     ProcessDataModel getProcess(int pid) {
    227 
    228 	ProcessDataModel pdm = null;
    229 	Integer pidI = new Integer(pid);
    230 
    231 	if ((pdm = (ProcessDataModel) processes.get(pidI)) == null) {
    232 	    if (updating == false)
    233 	    	return null;
    234 	    pdm = new ProcessDataModel(pid);
    235 	    processes.put(pidI, pdm);
    236 	}
    237 	if (updating == true)
    238 	    pdm.setUpdated(true);
    239 
    240 	return pdm;
    241     }
    242 
    243     /**
    244      * Get user metrics object.
    245      * @param	uid the user id
    246      * @return	metrics object with process metrics or new empty object at
    247      *		first call.
    248      */
    249     UserProcessAggregateDataModel getUserprocs(String uidStr) {
    250 
    251 	UserProcessAggregateDataModel  padm = null;
    252 
    253 	if ((padm = (UserProcessAggregateDataModel)
    254 		userprocs.get(uidStr)) == null) {
    255 	    if (updating == false)
    256 	    	return null;
    257 	    padm = new UserProcessAggregateDataModel(uidStr);
    258 	    userprocs.put(uidStr, padm);
    259 	}
    260 
    261 	if (updating == true)
    262 	    padm.setUpdated(true);
    263 
    264 	return padm;
    265     }
    266 
    267     /**
    268      * Get project metrics object.
    269      * @return	metrics object with process metrics or new empty
    270      *		object at first call.
    271      */
    272     ProjectProcessAggregateDataModel getProjprocs(String name) {
    273 
    274 	ProjectProcessAggregateDataModel  padm = null;
    275 
    276 	if ((padm = (ProjectProcessAggregateDataModel)
    277 		projprocs.get(name)) == null) {
    278 	    if (updating == false)
    279 	    	return null;
    280 	    padm = new ProjectProcessAggregateDataModel(name);
    281 	    projprocs.put(name, padm);
    282 	}
    283 	if (updating == true)
    284 	    padm.setUpdated(true);
    285 
    286 	return padm;
    287     }
    288 
    289     /**
    290      * Get active user object.
    291      * @param	name the user id as string
    292      * @return	active user object.
    293      */
    294     ActiveUserModel getUser(String name) {
    295 
    296 	ActiveUserModel aum = null;
    297 
    298 	if ((aum = (ActiveUserModel) users.get(name)) == null) {
    299 	    if (updating == false)
    300 	    	return null;
    301 	    aum = new ActiveUserModel(name);
    302 	    users.put(name, aum);
    303 	}
    304 	if (updating == true)
    305 	    aum.setUpdated(true);
    306 
    307 	return aum;
    308     }
    309 
    310     /**
    311      * Get active project object.
    312      * @param	name the project
    313      * @return	project object.
    314      */
    315     ActiveProjectModel getProject(String name) {
    316 
    317 	ActiveProjectModel apm = null;
    318 
    319 	if ((apm = (ActiveProjectModel) projs.get(name)) == null) {
    320 	    if (updating == false)
    321 	    	return null;
    322 	    apm = new ActiveProjectModel(name);
    323 	    projs.put(name, apm);
    324 	}
    325 	if (updating == true)
    326 	    apm.setUpdated(true);
    327 
    328 	return apm;
    329     }
    330 
    331     /**
    332      * Returns an iterator over the Processes.
    333      * @return iterator
    334      */
    335     Iterator getProcessIterator() {
    336 	return processes.values().iterator();
    337     }
    338 
    339     /**
    340      * Returns an iterator over the Users.
    341      * @return iterator
    342      */
    343     Iterator getUserIterator() {
    344 	return users.values().iterator();
    345     }
    346 
    347     /**
    348      * Returns an iterator over the Projects.
    349      * @return iterator
    350      */
    351     Iterator getProjectIterator() {
    352 	return projs.values().iterator();
    353     }
    354 
    355     /**
    356      * Returns an iterator over the user process aggregation.
    357      * @return iterator
    358      */
    359     Iterator getUserprocsIterator() {
    360 	    return userprocs.values().iterator();
    361     }
    362 
    363     /**
    364      * Returns an iterator over the project process aggregation.
    365      * @return iterator
    366      */
    367     Iterator getProjprocsIterator() {
    368 	return projprocs.values().iterator();
    369     }
    370 
    371     /**
    372      * Update the metrics data.
    373      * @exception SRMProtocolException
    374      */
    375     void  update() throws SRMProtocolException {
    376 
    377 	SRMProviderDataModel pdm;
    378 	int tries = 2;
    379 
    380 	while (tries-- > 0) {
    381 	    if (!running) {
    382 		dr.startRDS(rdsArgs);
    383 		running = true;
    384 	    	ka = new KeepAlive(rdsKeepAliveTimeout);
    385 		ka.start();
    386 	    }
    387 	    try {
    388 		synchronized (syncObject) {
    389 		    /* check if AliveThread has set error flag */
    390 		    if (kaError) {
    391 		    	closeONError();
    392 			continue;
    393 	    	    /*
    394 		     * check if rds is still running, since AliveThread
    395 		     * could already close RDS when this thread was waiting
    396 		     * on syncObject
    397 		     */
    398 		    } else if (running) {
    399     	    	    	updating = true;
    400 		    	dr.getUpdate(CMD_GETALL);
    401 		    } else {
    402 		    	tries = 2;
    403 		    	continue;
    404 		    }
    405 		}
    406 		ka.resetTimeout();
    407 		updating = false;
    408 		tries = 0;
    409 	    } catch (SRMProtocolException e) {
    410 	    	SRMDebug.trace(SRMDebug.TRACE_ALL, e.getMessage());
    411 	    	closeONError();
    412 		if (tries == 0)
    413 		    throw e;
    414 	    }
    415 	}
    416 	cleanUp();
    417 
    418     } // end update
    419 
    420     /**
    421      * Remove all dead processes, users or projects.
    422      */
    423     private void cleanUp() {
    424 
    425 	cleanUpList(processes);
    426 	cleanUpList(users);
    427 	cleanUpList(userprocs);
    428 	cleanUpList(projs);
    429 	cleanUpList(projprocs);
    430     }
    431 
    432     /**
    433      * Remove all elements that heven't been updated in last update.
    434      */
    435     private void cleanUpList(HashMap map) {
    436 	Iterator i;
    437 	SRMProviderDataModel pdm;
    438 
    439 	for (i = map.values().iterator(); i.hasNext(); ) {
    440 	    if (!((pdm = (SRMProviderDataModel) i.next()).isUpdated())) {
    441 		i.remove();
    442 	    } else {
    443 		pdm.setUpdated(false);
    444 	    }
    445 	}
    446     }
    447 
    448     /**
    449      * This thread keeps the rds and the communication with it alive by
    450      * sending the alive message to rds.
    451      */
    452     class KeepAlive extends Thread {
    453     	int keepAliveTimeout, save;
    454 
    455     	/**
    456      	 * Constructor
    457      	 * @param timeout how long to run at all
    458      	 */
    459 	public KeepAlive(int timeout) {
    460 	    super("KeepAlive");
    461 	    kaError = false;
    462 	    keepAliveTimeout = timeout;
    463 	    save = keepAliveTimeout;
    464 	}
    465 
    466 	synchronized public void run() {
    467 	    int myTimeout = 0;
    468 	    int waitTime = rdsTimeout / 2;
    469 
    470 	    doAlive = true;
    471 
    472 	    while (doAlive) {
    473 	    	/*
    474 		 * the keepAliveTimeout value is set in constructor and
    475 		 * in the resetTimeout() method. If its value is reseted
    476 		 * the internal timer myTimeout value will be wind up.
    477 		 */
    478 	    	if (keepAliveTimeout > 0) {
    479 		    myTimeout = keepAliveTimeout;
    480 		    keepAliveTimeout = 0;
    481 		}
    482 		try {
    483     	    	    synchronized (syncObject) {
    484 		    	/*
    485 			 * this thread has gained the sync object, but it
    486 			 * also should check the doAlive flag since
    487 			 * the dataModel thread could already removed it
    488 			 * because of a protocol error
    489 			 */
    490 		    	if (doAlive) {
    491 		    	    myTimeout -= waitTime;
    492     	    	    	    kaError = true;
    493 		    	    if (myTimeout <= 0) {
    494 		    	    	dr.closeRDS();
    495 		    	    	running = false;
    496 		    	    	return;
    497 		    	    } else {
    498 		    	    	dr.alive();
    499 			    }
    500 			    kaError = false;
    501 			} else {
    502 			    return;
    503 			}
    504 		    }
    505 		    wait(waitTime);
    506 		} catch (InterruptedException e) {
    507 	    	    SRMDebug.trace(SRMDebug.TRACE_ALL, e.getMessage());
    508 		    return;
    509     	    	} catch (SRMProtocolException e) {
    510 	    	    SRMDebug.trace(SRMDebug.TRACE_ALL, e.getMessage());
    511 		    return;
    512 		}
    513 	    }
    514 	}
    515 
    516     	/**
    517      	 * Reset the absolute timeout
    518      	 */
    519 	public void resetTimeout() {
    520 	    keepAliveTimeout = save;
    521 	}
    522 
    523     } // end class KeepAlive
    524 
    525 
    526     class ProjectProcessAggregateDataModel extends ProcessAggregateDataModel {
    527 	public ProjectProcessAggregateDataModel(String id) {
    528 	    super(id);
    529 	}
    530 
    531 	protected void setCIMInstance(boolean newInstance) {
    532 	    super.setCIMInstance(newInstance);
    533 	    setStrProp(newInstance, CREATIONCLASSNAME,
    534 	      SOLARIS_PROJECTPROCESSAGGREGATESTATISTICALINFORMATION);
    535 	    setStrProp(newInstance, NAME, name);
    536 	}
    537     }
    538 
    539     class UserProcessAggregateDataModel extends ProcessAggregateDataModel {
    540 	public UserProcessAggregateDataModel(String id) {
    541 	    super(id);
    542 	}
    543 
    544 	protected void setCIMInstance(boolean newInstance) {
    545 	    super.setCIMInstance(newInstance);
    546 	    setStrProp(newInstance, CREATIONCLASSNAME,
    547 	      SOLARIS_USERPROCESSAGGREGATESTATISTICALINFORMATION);
    548 	    setStrProp(newInstance, NAME, name);
    549 	}
    550     }
    551 
    552 } // end class DataModel
    553