HSQLDB实现学习笔记-数据库服务器创建
publicint start() { serverThread = new ServerThread("HSQLDB Server "); if (isDaemon) { serverThread.setDaemon(true); } serverThread.start(); }?
?
该线程被设置为守护线程,该线程的run 方法调用server类的run 方法实现数据库的启动。
1.2.2 ? ? ServerThread->Run()
(1) 创建一个服务器端口 ServerSocket,通过HsqlSocketFactory创建ServerSocket类
(2) 创建一个线程组,同时让当前的ServerThread作为线程组的父线程。
(3) 打开数据库,获取数据相关参数。
(4) DataBaseManager.getDatabase方法获取数据库信息,先通过数据库(根据路径生成的一个key值)缓存中获取数据库,如果存在则返回,否则直接通过Database类创建新的数据库实例。
(5) DataBase的创建过程中设置数据库状态为关闭、设置数据库类型、绝对路径、相对路径、创建日志对象用于存储操作日志。
(6) 调用database的open方法打开数据库:
?
??
void reopen() { boolean isNew = false; setState(DATABASE_OPENING); try { lobManager = new LobManager(this); nameManager = new HsqlNameManager(this); granteeManager = new GranteeManager(this); userManager = new UserManager(this); schemaManager = new SchemaManager(this); persistentStoreCollection = new PersistentStoreCollectionDatabase(this); isReferentialIntegrity = true; sessionManager = new SessionManager(this); collation = collation.newDatabaseInstance(); dbInfo = DatabaseInformation.newDatabaseInformation(this); txManager = new TransactionManager2PL(this); lobManager.createSchema(); sessionManager.getSysLobSession().setSchema( SqlInvariants.LOBS_SCHEMA); schemaManager.setSchemaChangeTimestamp(); schemaManager.createSystemTables(); // completed metadata logger.open();//关联到数据持久化流程,此步也是打开数据库文件的步骤 isNew = logger.isNewDatabase; if (isNew) { String username = urlProperties.getProperty("user", "SA"); String password = urlProperties.getProperty("password", ""); userManager.createFirstUser(username, password); schemaManager.createPublicSchema(); logger.checkpoint(false); } lobManager.open(); dbInfo.setWithContent(true); checkpointRunner = new CheckpointRunner(); timeoutRunner = new TimeoutRunner(); } catch (Throwable e) { logger.close(Database.CLOSEMODE_IMMEDIATELY); logger.releaseLock(); setState(DATABASE_SHUTDOWN); clearStructures(); DatabaseManager.removeDatabase(this); if (!(e instanceof HsqlException)) { e = Error.error(ErrorCode.GENERAL_ERROR, e); } logger.logSevereEvent("could not reopen database", e); throw (HsqlException) e; } setState(DATABASE_ONLINE); }
?
1.2.1 ? ? 客户端请求接收并处理
此部分的入口是在创建完serversoket后执行的,也在run方法中。
try { /* * This loop is necessary for UNIX w/ Sun Java 1.3 because * in that case the socket.close() elsewhere will not * interrupt this accept(). */ while (socket != null) { try { handleConnection(socket.accept());// 接收并处理客户端发起的请求 } catch (java.io.InterruptedIOException iioe) {} } } catch (IOException ioe) { if (getState() == ServerConstants.SERVER_STATE_ONLINE) { setServerError(ioe); printError(this + ".run()/handleConnection(): "); printStackTrace(ioe); } } catch (Throwable t) { printWithThread(t.toString()); } finally { shutdown(false); // or maybe getServerError() != null? }
?
1.2.2 ? ? 客户端请求处理步骤
?
publicvoid handleConnection(Socket s) { Thread t; Runnable r; String ctn; printWithThread("handleConnection(" + s + ") entered"); if (!allowConnection(s)) { try { s.close(); } catch (Exception e) {} printWithThread("allowConnection(): connection refused"); printWithThread("handleConnection() exited"); return; } // Maybe set up socket options, SSL // Session tracing/callbacks, etc. if (socketFactory != null) { socketFactory.configureSocket(s); } if (serverProtocol == ServerConstants.SC_PROTOCOL_HSQL) { r = new ServerConnection(s, this); ctn = ((ServerConnection) r).getConnectionThreadName(); } else { r = new WebServerConnection(s, (WebServer) this); ctn = ((WebServerConnection) r).getConnectionThreadName(); } t = new Thread(serverConnectionThreadGroup, r, ctn); t.start(); printWithThread("handleConnection() exited"); }
?
(1) 初步判断如是否允许该socket建立连接
(2) 根据服务类型判断创建哪种类型的连接,比如是Server类创建ServerConnection如果是webserver则创建WebServerConnection,每一个连接是一个单独的线程、
(3) 将连接线程加入到线程组中。
1.3数据库创建
此部分是对1.2.2 database.open方法的详细说明
1.3.1 ? ? LobManager创建schema
(1) 加载自定义的初始化脚本/org/hsqldb/resources/lob-schema.sql
1.3.2 ? ? SchemaManager创建SystemTable
1.3.3 ? ? Logger打开日志并且设置为新建数据库日志
1.3.4 ? ? UsernManager创建第一个用户
1.3.5 ? ? Schemanager创建publicSchema
Schema用于存储hsqldb的所有对象信息
? ?
// SCHEMA management publicvoid createPublicSchema() { writeLock.lock(); try { HsqlName name = database.nameManager.newHsqlName(null, SqlInvariants.PUBLIC_SCHEMA, SchemaObject.SCHEMA); Schema schema = new Schema(name, database.getGranteeManager().getDBARole()); defaultSchemaHsqlName = schema.getName(); schemaMap.put(schema.getName().name, schema); } finally { writeLock.unlock(); } }
?
1.3.6 ?Schema类包含的特性
? ?
public Schema(HsqlName name, Grantee owner) { this.name = name; triggerLookup = new SchemaObjectSet(SchemaObject.TRIGGER); indexLookup = new SchemaObjectSet(SchemaObject.INDEX); constraintLookup = new SchemaObjectSet(SchemaObject.CONSTRAINT); tableLookup = new SchemaObjectSet(SchemaObject.TABLE); sequenceLookup = new SchemaObjectSet(SchemaObject.SEQUENCE); typeLookup = new SchemaObjectSet(SchemaObject.TYPE); charsetLookup = new SchemaObjectSet(SchemaObject.CHARSET); collationLookup = new SchemaObjectSet(SchemaObject.COLLATION); procedureLookup = new SchemaObjectSet(SchemaObject.PROCEDURE); functionLookup = new SchemaObjectSet(SchemaObject.FUNCTION); specificRoutineLookup = new SchemaObjectSet(SchemaObject.SPECIFIC_ROUTINE); assertionLookup = new SchemaObjectSet(SchemaObject.ASSERTION); tableList = (HashMappedList) tableLookup.map; sequenceList = (HashMappedList) sequenceLookup.map; name.owner = owner;}
?
1.3.7 ? ? 创建checkPoint生成后台线程
checkpointRunner = new CheckpointRunner();
?
1.3.8 ?创建timeOut生成后台线程
?
? ?
timeoutRunner = new TimeoutRunner();
?