001: /*
002:
003: Derby - Class org.apache.derby.impl.services.monitor.TopService
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.services.monitor;
023:
024: import org.apache.derby.iapi.services.monitor.ModuleControl;
025: import org.apache.derby.iapi.services.monitor.Monitor;
026:
027: import org.apache.derby.iapi.services.monitor.PersistentService;
028: import org.apache.derby.iapi.error.StandardException;
029:
030: import org.apache.derby.iapi.services.sanity.SanityManager;
031: import org.apache.derby.iapi.reference.SQLState;
032: import org.apache.derby.iapi.reference.EngineType;
033:
034: import java.util.Hashtable;
035: import java.util.Vector;
036: import java.util.Properties;
037: import java.util.Locale;
038:
039: /**
040: A description of an instance of a module.
041: */
042:
043: final class TopService {
044:
045: /*
046: ** Fields.
047: */
048:
049: /**
050: The idenity of this service, note that it may not be active yet.
051: */
052: ProtocolKey key;
053:
054: /**
055: The top module instance
056: */
057: ModuleInstance topModule;
058:
059: /**
060: List of protocols.
061: */
062: Hashtable protocolTable;
063:
064: /**
065: */
066: Vector moduleInstances;
067:
068: /**
069: */
070: BaseMonitor monitor;
071:
072: boolean inShutdown;
073:
074: /**
075: The type of service this was created by. If null then this is a non-persistent service.
076: */
077: PersistentService serviceType;
078:
079: Locale serviceLocale;
080:
081: /*
082: ** Constructor
083: */
084:
085: TopService(BaseMonitor monitor) {
086: super ();
087: this .monitor = monitor;
088: protocolTable = new Hashtable();
089: moduleInstances = new Vector(0, 5);
090: }
091:
092: TopService(BaseMonitor monitor, ProtocolKey key,
093: PersistentService serviceType, Locale serviceLocale) {
094: this (monitor);
095:
096: this .key = key;
097: this .serviceType = serviceType;
098: this .serviceLocale = serviceLocale;
099: }
100:
101: void setTopModule(Object instance) {
102: synchronized (this ) {
103: for (int i = 0; i < moduleInstances.size(); i++) {
104: ModuleInstance module = (ModuleInstance) moduleInstances
105: .elementAt(i);
106: if (module.getInstance() == instance) {
107: topModule = module;
108: notifyAll();
109: break;
110: }
111: }
112:
113: // now add an additional entry into the hashtable
114: // that maps the server name as seen by the user
115: // onto the top module. This allows modules to find their
116: // top most service moduel using the monitor.getServiceName() call,
117: // e.g. Monitor.findModule(ref, inferface, Monitor.getServiceName(ref));
118: if (getServiceType() != null) {
119: ProtocolKey userKey = new ProtocolKey(key
120: .getFactoryInterface(), monitor
121: .getServiceName(instance));
122: addToProtocol(userKey, topModule);
123: }
124:
125: }
126: }
127:
128: Object getService() {
129:
130: return topModule.getInstance();
131: }
132:
133: boolean isPotentialService(ProtocolKey otherKey) {
134:
135: String otherCanonicalName;
136:
137: if (serviceType == null)
138: otherCanonicalName = otherKey.getIdentifier();
139: else {
140: try {
141: otherCanonicalName = serviceType
142: .getCanonicalServiceName(otherKey
143: .getIdentifier());
144: } catch (StandardException se) {
145: return false;
146: }
147:
148: // if the service name cannot be converted into a canonical name then it is not a service.
149: if (otherCanonicalName == null)
150: return false;
151: }
152:
153: if (topModule != null)
154: return topModule.isTypeAndName(serviceType, key
155: .getFactoryInterface(), otherCanonicalName);
156:
157: if (!otherKey.getFactoryInterface().isAssignableFrom(
158: key.getFactoryInterface()))
159: return false;
160:
161: return serviceType.isSameService(key.getIdentifier(),
162: otherCanonicalName);
163: }
164:
165: boolean isActiveService() {
166: synchronized (this ) {
167: return (topModule != null);
168: }
169: }
170:
171: boolean isActiveService(ProtocolKey otherKey) {
172:
173: synchronized (this ) {
174: if (inShutdown)
175: return false;
176:
177: if (!isPotentialService(otherKey))
178: return false;
179:
180: if (topModule != null) {
181: if (SanityManager.DEBUG) {
182: SanityManager.ASSERT(topModule.isTypeAndName(
183: serviceType, key.getFactoryInterface(), key
184: .getIdentifier()));
185: }
186:
187: return true;
188: }
189:
190: // now wait for topModule to be set
191: while (!inShutdown && (topModule == null)) {
192: try {
193: wait();
194: } catch (InterruptedException ioe) {
195: return false;
196: }
197: }
198:
199: if (inShutdown)
200: return false;
201:
202: return true;
203: }
204: }
205:
206: /**
207: Find an module in the protocol table that supports the required protocol
208: name combination and can handle the properties.
209:
210: Returns the instance of the module or null if one does not exist in
211: the protocol table.
212: */
213: synchronized Object findModule(ProtocolKey key, boolean findOnly,
214: Properties properties) {
215:
216: ModuleInstance module = (ModuleInstance) protocolTable.get(key);
217:
218: if (module == null)
219: return null;
220:
221: Object instance = module.getInstance();
222:
223: if (findOnly || BaseMonitor.canSupport(instance, properties))
224: return instance;
225:
226: return null;
227: }
228:
229: /**
230: Boot a module, performs three steps.
231:
232: <OL>
233: <LI> Look for an existing module in the protocol table
234: <LI> Look for a module in the implementation table that handles this protocol
235: <LI> Create an instance that handles this protocol.
236: </OL>
237: */
238: Object bootModule(boolean create, Object service, ProtocolKey key,
239: Properties properties) throws StandardException {
240:
241: synchronized (this ) {
242: if (inShutdown)
243: throw StandardException.newException(
244: SQLState.SHUTDOWN_DATABASE, getKey()
245: .getIdentifier());
246: }
247:
248: // see if this system already has a module that will work.
249: Object instance = findModule(key, false, properties);
250: if (instance != null)
251: return instance;
252:
253: if (monitor.reportOn) {
254: monitor.report("Booting Module " + key.toString()
255: + " create = " + create);
256: }
257:
258: // see if a running implementation will handle this protocol
259: synchronized (this ) {
260:
261: for (int i = 0; i < moduleInstances.size(); i++) {
262: ModuleInstance module = (ModuleInstance) moduleInstances
263: .elementAt(i);
264:
265: if (!module.isTypeAndName((PersistentService) null, key
266: .getFactoryInterface(), key.getIdentifier()))
267: continue;
268:
269: instance = module.getInstance();
270: if (!BaseMonitor.canSupport(instance, properties))
271: continue;
272:
273: // add it to the protocol table, if this returns false then we can't use
274: // this module, continue looking.
275: if (!addToProtocol(key, module))
276: continue;
277:
278: if (monitor.reportOn) {
279: monitor
280: .report("Started Module "
281: + key.toString());
282: monitor.report(" Implementation "
283: + instance.getClass().getName());
284: }
285:
286: return instance;
287: }
288: }
289:
290: // try and load an instance that will support this protocol
291: instance = monitor.loadInstance(key.getFactoryInterface(),
292: properties);
293: if (instance == null) {
294: throw Monitor.missingImplementation(key
295: .getFactoryInterface().getName());
296: }
297: ModuleInstance module = new ModuleInstance(instance, key
298: .getIdentifier(), service,
299: topModule == null ? (Object) null : topModule
300: .getInstance());
301:
302: moduleInstances.addElement(module);
303:
304: try {
305: BaseMonitor.boot(instance, create, properties);
306: } catch (StandardException se) {
307: moduleInstances.removeElement(module);
308: throw se;
309: }
310:
311: synchronized (this ) {
312:
313: // add it to the protocol table, if this returns false then we can't use
314: // this module, shut it down.
315: if (addToProtocol(key, module)) {
316:
317: if (monitor.reportOn) {
318: monitor
319: .report("Started Module "
320: + key.toString());
321: monitor
322: .report(" Implementation "
323: + module.getInstance().getClass()
324: .getName());
325: }
326:
327: return module.getInstance();
328: }
329:
330: }
331:
332: TopService.stop(instance);
333: moduleInstances.removeElement(module);
334:
335: // if we reached here it's because someone else beat us adding the module, so use theirs.
336: return findModule(key, true, properties);
337: }
338:
339: /**
340: If the service is already beign shutdown we return false.
341: */
342: boolean shutdown() {
343:
344: synchronized (this ) {
345: if (inShutdown)
346: return false;
347:
348: inShutdown = true;
349: notifyAll();
350: }
351:
352: for (;;) {
353:
354: ModuleInstance module;
355:
356: synchronized (this ) {
357:
358: if (moduleInstances.isEmpty())
359: return true;
360:
361: module = (ModuleInstance) moduleInstances.elementAt(0);
362:
363: }
364:
365: Object instance = module.getInstance();
366: TopService.stop(instance);
367:
368: synchronized (this ) {
369: moduleInstances.removeElementAt(0);
370: }
371: }
372: }
373:
374: /**
375: Add a running module into the protocol hash table. Return true
376: if the module was added successfully, false if it couldn't
377: be added. In the latter case the module should be shutdown
378: if its reference count is 0.
379: */
380:
381: private boolean addToProtocol(ProtocolKey key, ModuleInstance module) {
382:
383: String identifier = module.getIdentifier();
384:
385: synchronized (this ) {
386:
387: Object value = protocolTable.get(key);
388: if (value == null) {
389:
390: protocolTable.put(key, module);
391: return true;
392: }
393:
394: if (value == module)
395: return true;
396:
397: return false;
398: }
399: }
400:
401: boolean inService(Object instance) {
402:
403: for (int i = 0; i < moduleInstances.size(); i++) {
404:
405: ModuleInstance mi = (ModuleInstance) moduleInstances
406: .elementAt(i);
407: if (mi.getInstance() == instance)
408: return true;
409: }
410: return false;
411: }
412:
413: public ProtocolKey getKey() {
414: return key;
415: }
416:
417: PersistentService getServiceType() {
418: return serviceType;
419: }
420:
421: private static void stop(Object instance) {
422: if (instance instanceof ModuleControl) {
423: ((ModuleControl) instance).stop();
424: }
425: }
426: }
|