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  * ResourceMonitor.java
26  */
27 
28 
29 package com.sun.wbem.solarisprovider.srm;
30 
31 import	java.util.HashSet;
32 
33 /**
34  * Mediator between data model the native interface and the client.
35  * Implements the singleton pattern.
36  * @author Sun Microsystems, Inc.
37  */
38 public final class ResourceMonitor {
39     /**
40      * The UPDATETIME defines a time window in which a data request will
41      *  be served from internal data cache instead of accessing rds, 5 sec.
42      */
43     private static final int UPDATETIME =  5000;
44 
45     /**
46      * The RDSTIMEOUT defines the timeout after which the rds
47      * rds will exit, if it hasn't received command from client, 30 sec.
48      */
49     private static final int RDSTIMEOUT =  30000;
50     /**
51      * The RDSINTERVAL defines a interval in which the rds
52      * will update its data, 1 sec.
53      */
54     private static final int RDSINTERVAL =  1000;
55 
56     private static ResourceMonitor	rm;
57     private static DataModel	dataModel;
58     private long    lastUpdateTime;
59     private int     updateTime	= UPDATETIME;
60     private int     rdsTimeout	= RDSTIMEOUT;
61     private int     rdsInterval = RDSINTERVAL;
62 
63     /**
64      * threads that hold access into the data model
65      */
66     private int			    	activeClients;
67 
68     /**
69      * Ensure that DataModel will be opened and closed once.
70      */
71     private boolean ifOpened = false;
72 
73     /**
74      * Default constructor
75      */
ResourceMonitor()76     private ResourceMonitor() {
77     }
78 
79     /**
80      * Should be used to obtain the singleton instance of this class
81      * @return the singleton instance of this class
82      */
getHandle()83     public static synchronized  ResourceMonitor getHandle() {
84     	if (rm == null) {
85             rm  = new ResourceMonitor();
86      	    // The provider data model used by this monitor
87             dataModel  = DataModel.getHandle(rm);
88     	}
89     	return rm;
90     }
91 
92     /**
93      * Open the data model used by this monitor with the following default
94      * times, timeout after which the rds rds will exit 30 sec., interval in
95      * which the rds will update its data 1 sec., time in which the data model
96      * will refresh its cache 5 sec.
97      */
openDataModel()98     public synchronized void openDataModel() {
99 	openDataModel(rdsTimeout, rdsInterval, updateTime);
100     }
101 
102     /**
103      * Open the data model used by this monitor.
104      * @param rdsTimeout    timeout after which the rds rds will exit,
105      *	    	    	    if -1 the default value 30 sec. will be used
106      * @param rdsInterval   interval in which the rds will update its data
107      *	    	    	    if -1 the default value 1 sec. will be used
108      * @param updateTime    time in which the data model will refresh its cache
109      *	    	    	    if -1 the default value 5 sec. will be used
110      */
openDataModel(int rdsTimeout, int rdsInterval, int updateTime)111     public synchronized void openDataModel(int rdsTimeout,
112 	    int rdsInterval, int updateTime) {
113 
114 	if (ifOpened == false) {
115 	    if (updateTime != -1)
116     	    	this.updateTime = updateTime;
117 	    if (rdsTimeout != -1)
118 	    	this.rdsTimeout = rdsTimeout;
119 	    if (rdsTimeout != -1)
120 	    	this.rdsInterval = rdsInterval;
121 	    dataModel.open(rdsTimeout, rdsInterval);
122 	    ifOpened = true;
123 	}
124 
125     } // end openDataModel
126 
127     /**
128      * Close the data model used by this monitor.
129      */
closeDataModel()130     public synchronized void closeDataModel() {
131 
132 	if (ifOpened == true) {
133 	    dataModel.close();
134 	    ifOpened = false;
135 	}
136 
137     } // end closeDataModel
138 
139     /**
140      * Get the access to the data model. The caller should invoke
141      * releaseDataModel() in order to allow the refresh of the data
142      * model cache after it has finished the data processing.
143      * @return the data model
144      * @throws com.sun.wbem.solarisprovider.srm.SRMException
145      *		if the data model couldn't be updated.
146      */
147     public synchronized
getDataModel(boolean forceUpdate)148     DataModel getDataModel(boolean forceUpdate)
149     throws SRMException {
150 
151 	if (ifOpened == false)
152 	    throw new SRMException("Resource Data Model is not opened");
153 
154 	if (forceUpdate == true) {
155 	    update();
156 	} else {
157 	    long currentTime = System.currentTimeMillis();
158 	    if ((currentTime - lastUpdateTime) > updateTime) {
159 		lastUpdateTime = currentTime;
160 		update();
161 	    }
162 	}
163 	activeClients++;
164     	SRMDebug.trace(SRMDebug.THREAD_SYNC, "srm data cache update locked by "
165 	    	+ activeClients + " clients");
166 	return dataModel;
167 
168     } // end getDataModel
169 
170     /**
171      * Release the lock into the data model. This allows the refresh of the
172      * data model cache.
173      * @param dm the data got from getDataModel() model must not be zero
174      */
releaseDataModel(DataModel dm)175     public synchronized DataModel releaseDataModel(DataModel dm) {
176 
177     	if (dm != null) {
178     	    activeClients--;
179     	    SRMDebug.trace(SRMDebug.THREAD_SYNC,
180 	    	    "srm data cache update locked by "
181 		    + activeClients + " clients");
182     	    notifyAll();
183 	}
184 	return null;
185     } // end releaseDataModel
186 
187     /**
188      * Wait till all data model readers release their lock, then do the update
189      */
update()190     private void update() throws SRMException {
191 
192     	    beforeUpdate();
193 	    SRMDebug.trace(SRMDebug.THREAD_SYNC,
194 	    	"starting srm data cache update, at: "
195 	    	+System.currentTimeMillis()+"ms");
196 	    dataModel.update();
197 	    SRMDebug.trace(SRMDebug.THREAD_SYNC,
198 	    	"finished srm data cache update, at: "
199 	    	+System.currentTimeMillis()+"ms");
200     }
201 
202     private static final int WAITTIME =  500;
203 
204     /**
205      * Wait till all data model readers release their lock. To ensure
206      * liveness only wait max. 10 * WAITTIME;
207      */
beforeUpdate()208     private synchronized void beforeUpdate() {
209     	int tries = 10;
210 
211 	while (activeClients > 0) {
212 	    try {
213 	    	--tries;
214 	    	wait(WAITTIME);
215 		if (tries == 0)
216 		    activeClients = 0;
217 	    } catch (InterruptedException ex) {
218 	    }
219     	}
220     }
221 
222 } // end class ResourceMonitor
223