Derby源代码分析 -- 服务器启动(三)

本文详细剖析了Apache Derby数据库启动过程中的服务启动机制,重点介绍了#startServices()方法的工作原理,包括服务注册、模块实例加载及启动等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看过#getImplementations()之后,来看一下#startServices()方法,这个方法就是启动服务了,前面看到的JDBC服务就是在这里启动的(addProperty("derby.service.jdbc", "org.apache.derby.jdbc.InternalDriver");)

	public void startServices(Properties properties, boolean bootAll) {
if (properties == null)
return;

for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) {
/* 获得服务的键值 */
String key = (String) e.nextElement();
if (key.startsWith(SERVICE)) {// 判断是否以"derby.service."开头
/* 返回服务名 */
String name = key.substring(SERVICE.length());
/* 服务的协议或类型,其实就是类名 */
String protocolOrType = properties.getProperty(key);

try {
/* 如果协议名等于"serviceDirectory" */
if (protocolOrType.equals(Monitor.SERVICE_TYPE_DIRECTORY)) {
if (bootAll)
findProviderAndStartService(name, properties, true);
} else {
/* 开启服务 */
bootService((PersistentService) null, protocolOrType, name, (Properties) null, false);
}

} catch (StandardException se) {
if (!protocolOrType.equals(Monitor.SERVICE_TYPE_DIRECTORY))
reportException(se);
}
}
}
}


这里需要重点留意的是协议名不等于"serviceDirectory"的情况,也就是进入#bootService()方法的分支。

这个方法也是非常长的,我们来研究下,

	protected Object bootService(PersistentService provider, String factoryInterface, String serviceName,
Properties properties, boolean create) throws StandardException {

/*
* 以 "derby.service.jdbc", "org.apache.derby.jdbc.InternalDriver" 为例
* provider = null factoryInterface = protocolOrType
* (org.apache.derby.jdbc.InternalDriver) serviceName = name (jdbc)
* properties = null create = false
*/
if (provider != null)
serviceName = provider.getCanonicalServiceName(serviceName);
/* ProtocolKey里存了两个属性factoryInterface和serviceName */
ProtocolKey serviceKey = ProtocolKey.create(factoryInterface, serviceName);
if (SanityManager.DEBUG && reportOn) {
report("Booting service " + serviceKey + " create = " + create);
}

ContextManager previousCM = contextService.getCurrentContextManager();
ContextManager cm = previousCM;
Object instance;
TopService ts = null;
Context sb = null;

try {
synchronized (this) {

if (inShutdown) {
throw StandardException.newException(SQLState.CLOUDSCAPE_SYSTEM_SHUTDOWN);
}

/*
* 这里services这个变量实在BaseMonitor的构造函数中初始化的 services = new
* Vector(0, 1); services.addElement(new TopService(this)); //
*/
for (int i = 1; i < services.size(); i++) {
TopService ts2 = (TopService) services.elementAt(i);
if (ts2.isPotentialService(serviceKey)) {
// if the service already exists then just return null
return null;
}
}

/* 取得Locale */
Locale serviceLocale = null;
if (create) {
properties = new Properties(properties);
serviceLocale = setLocale(properties);
properties.put(Property.SERVICE_PROTOCOL, factoryInterface);
serviceName = provider.createServiceRoot(serviceName, Boolean.valueOf(
properties.getProperty(Property.DELETE_ON_CREATE)).booleanValue());

serviceKey = ProtocolKey.create(factoryInterface, serviceName);
} else if (properties != null) {
String serverLocaleDescription = properties.getProperty(Property.SERVICE_LOCALE);
if (serverLocaleDescription != null)
serviceLocale = staticGetLocaleFromString(serverLocaleDescription);
}

/* TopService代表了对module实例的描述 */
ts = new TopService(this, serviceKey, provider, serviceLocale);
services.addElement(ts);
}

if (SanityManager.DEBUG) {
if (provider != null) {
SanityManager.ASSERT(provider.getCanonicalServiceName(serviceName).equals(serviceName),
"mismatched canonical names " + provider.getCanonicalServiceName(serviceName) + " != "
+ serviceName);
SanityManager.ASSERT(serviceName.equals(serviceKey.getIdentifier()), "mismatched names "
+ serviceName + " != " + serviceKey.getIdentifier());
}
}

if (properties != null) {
properties.put(PersistentService.ROOT, serviceName);

properties.put(PersistentService.TYPE, provider.getType());
}

if (SanityManager.DEBUG && reportOn) {
dumpProperties("Service Properties: " + serviceKey.toString(), properties);
}

if (previousCM == null) {
cm = contextService.newContextManager();

contextService.setCurrentContextManager(cm);
}
sb = new ServiceBootContext(cm);

UpdateServiceProperties usProperties;
Properties serviceProperties;

boolean inRestore = (properties != null ? properties.getProperty(Property.IN_RESTORE_FROM_BACKUP) != null
: false);

if ((provider != null) && (properties != null)) {
usProperties = new UpdateServiceProperties(provider, serviceName, properties, !(create || inRestore));
serviceProperties = usProperties;
} else {
usProperties = null;
serviceProperties = properties;
}

/* 这个方法比较重要,进行module的启动 */
instance = ts.bootModule(create, null, serviceKey, serviceProperties);

if (create || inRestore) {
provider.saveServiceProperties(serviceName, usProperties.getStorageFactory(), BaseMonitor
.removeRuntimeProperties(properties), false);
usProperties.setServiceBooted();
}

if (cm != previousCM)
cm.cleanupOnError(StandardException.closeException());

} catch (Throwable t) {
StandardException se;
if ((t instanceof StandardException)
&& (((StandardException) t).getSeverity() == ExceptionSeverity.DATABASE_SEVERITY))
se = (StandardException) t;
else
se = Monitor.exceptionStartingModule(t);

if (cm != previousCM) {
cm.cleanupOnError(se);
}

if (ts != null) {
ts.shutdown();
synchronized (this) {
services.removeElement(ts);
}

boolean deleteOnError = (properties != null ? properties.getProperty(Property.DELETE_ROOT_ON_ERROR) != null
: false);
if (create || deleteOnError)
provider.removeServiceRoot(serviceName);
}

Throwable nested = se.getCause();

if (nested instanceof ThreadDeath)
throw (ThreadDeath) nested;

throw se;

} finally {
if ((previousCM == cm) && (sb != null))
sb.popMe();

if (previousCM == null)
contextService.resetCurrentContextManager(cm);
}

/* 这个方法把module实例加入到protocolTable这个Hashtable中 */
ts.setTopModule(instance);

Thread.yield();

return instance;
}


这里instance = ts.bootModule(create, null, serviceKey, serviceProperties);这一步比较重要,这步会找到module的实现类,然后返回module的实例。


	Object bootModule(boolean create, Object service, ProtocolKey key, Properties properties) throws StandardException {

synchronized (this) {
if (inShutdown)
throw StandardException.newException(SQLState.SHUTDOWN_DATABASE, getKey().getIdentifier());
}

/* 查看是否已经启动了这个module,在protocolTable这个Hashtable中先查找实例 */
Object instance = findModule(key, false, properties);
if (instance != null)// 如果有,直接返回
return instance;

if (monitor.reportOn) {
monitor.report("Booting Module " + key.toString() + " create = " + create);
}

synchronized (this) {

for (int i = 0; i < moduleInstances.size(); i++) {// 在运行中的module中查找
/* module的包装类 */
ModuleInstance module = (ModuleInstance) moduleInstances.elementAt(i);

if (!module.isTypeAndName((PersistentService) null, key.getFactoryInterface(), key.getIdentifier()))
continue;

instance = module.getInstance();
if (!BaseMonitor.canSupport(instance, properties))
continue;

// 把实例加入到protocolTable中
if (!addToProtocol(key, module))
continue;

if (monitor.reportOn) {
monitor.report("Started Module " + key.toString());
monitor.report(" Implementation " + instance.getClass().getName());
}

return instance;
}
}

/* 这步就是载入module实例了,以我们之前的JDBC module为例,会找到与当前JDBC版本对应的Driver */
instance = monitor.loadInstance(key.getFactoryInterface(), properties);
if (instance == null) {
throw Monitor.missingImplementation(key.getFactoryInterface().getName());
}
ModuleInstance module = new ModuleInstance(instance, key.getIdentifier(), service,
topModule == null ? (Object) null : topModule.getInstance());

moduleInstances.addElement(module);

try {
/* 这里会调用module的#boot()方法 */
BaseMonitor.boot(instance, create, properties);
} catch (StandardException se) {
moduleInstances.removeElement(module);
throw se;
}

synchronized (this) {
/* 加入到Hashtable中 */
if (addToProtocol(key, module)) {

if (monitor.reportOn) {
monitor.report("Started Module " + key.toString());
monitor.report(" Implementation " + module.getInstance().getClass().getName());
}

return module.getInstance();
}

}
/* 如果加入失败,那么就不能使用这个module了,要shutdown掉 */
TopService.stop(instance);
moduleInstances.removeElement(module);

return findModule(key, true, properties);
}


这个方法有两处还需要重点的研究下,一个是BaseMonitor的#loadInstance(),它负责找到实例。


	protected Object loadInstance(Class factoryInterface, Properties properties) {

Object instance = null;

Vector localImplementations = getImplementations(properties, false);
if (localImplementations != null) {
instance = loadInstance(localImplementations, factoryInterface, properties);
}

/* implementationSets存了前面BaseMonitor的#runWithState()方法中找到的全部实例 */
for (int i = 0; i < implementationSets.length; i++) {
instance = loadInstance(implementationSets[i], factoryInterface, properties);
if (instance != null)
break;
}

return instance;
}

private Object loadInstance(Vector implementations, Class factoryInterface, Properties properties) {

for (int index = 0; true; index++) {

index = findImplementation(implementations, index, factoryInterface);
if (index < 0)
return null;

Object instance = newInstance((Class) implementations.elementAt(index));

if (BaseMonitor.canSupport(instance, properties))
return instance;
}
}

private static int findImplementation(Vector implementations, int startIndex, Class factoryInterface) {

for (int i = startIndex; i < implementations.size(); i++) {

Class factoryClass = (Class) implementations.elementAt(i);
/* 这里用#isAssignableFrom方法来匹配是否是module的实例 */
if (!factoryInterface.isAssignableFrom(factoryClass)) {
continue;
}

return i;
}

return -1;
}


这里第二个需要关注的是BaseMonitor.boot(instance, create, properties);方法,这个方法会调用module实例的#boot()方法,

	static void boot(Object module, boolean create, Properties properties) throws StandardException {
if (module instanceof ModuleControl)
((ModuleControl) module).boot(create, properties);
}


在EmbeddedDriver的载入过程中,以最新的JDK1.6为例,对应的是JDBC4.0。JDBC module(org.apache.derby.jdbc.InternalDriver)会找到的实现类是org.apache.derby.jdbc.Driver40(这个是在module.properties中定义的)。这里BaseMonitor#boot()就会调用Driver40的boot()方法了。最后会把InternalDriver的一个内部静态变量activeDriver设定成当前找到的这个Driver40,这个代码还是很容易理解的,这里就不再列出来了。

至此,Derby的启动部分就分析完了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值