Skip to content

Commit

Permalink
LealoneDatabase在启动过程中执行CREATE DATABASE时,不对数据库初始化
Browse files Browse the repository at this point in the history
  • Loading branch information
codefollower committed Mar 6, 2017
1 parent 10f2baf commit 8186a58
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 71 deletions.
Expand Up @@ -65,9 +65,9 @@ public interface DatabaseEventListener extends EventListener {
* in the database URL, but may be later if the listener is set at
* runtime with the SET SQL statement.
*
* @param url - the database URL
* @param dbName - the database name
*/
void init(String url);
void init(String dbName);

/**
* This method is called after the database has been opened.
Expand Down
35 changes: 10 additions & 25 deletions lealone-db/src/main/java/org/lealone/db/Database.java
Expand Up @@ -165,26 +165,25 @@ public Object getAuthLock() {

private final int id;
private final String name;
private final Map<String, String> parameters;
private final DbSettings dbSettings;
private final boolean persistent;

// 每个数据库只有一个SQL引擎和一个事务引擎
private final SQLEngine sqlEngine;
private final TransactionEngine transactionEngine;

private String fullName;
private String storageName; // 不使用原始的名称,而是用id替换数据库名
private String databaseURL;

private Map<String, String> replicationProperties;
private ReplicationPropertiesChangeListener replicationPropertiesChangeListener;

private RunMode runMode;
private final Map<String, String> parameters;

public Database(int id, String name, Map<String, String> parameters) {
this.id = id;
this.name = name;
this.storageName = getStorageName();
this.parameters = parameters;
if (parameters != null)
dbSettings = DbSettings.getInstance(parameters);
Expand Down Expand Up @@ -242,10 +241,6 @@ public String getShortName() {
return getName();
}

public String getFullName() {
return fullName;
}

public DbSettings getSettings() {
return dbSettings;
}
Expand Down Expand Up @@ -316,7 +311,7 @@ public synchronized Database copy() {
db.storageName = storageName;
db.storageBuilder = storageBuilder;
db.storages.putAll(storages);
db.init(fullName, databaseURL);
db.init();
LealoneDatabase.getInstance().getDatabasesMap().put(name, db);
for (ServerSession s : userSessions) {
db.userSessions.add(s);
Expand All @@ -329,19 +324,11 @@ public boolean isInitialized() {
return initialized;
}

public void init(ConnectionInfo ci) {
init(ci.getDatabaseName(), ci.getURL());
}

public synchronized void init(String fullName, String databaseURL) {
public synchronized void init() {
if (initialized)
return;
initialized = true;

this.fullName = fullName;
this.databaseURL = databaseURL;
storageName = getStorageName();

String listener = dbSettings.eventListener;
if (listener != null) {
listener = StringUtils.trim(listener, true, true, "'");
Expand Down Expand Up @@ -1704,11 +1691,7 @@ public void setEventListenerClass(String className) {
} else {
try {
eventListener = (DatabaseEventListener) Utils.loadUserClass(className).newInstance();
String url = databaseURL;
if (dbSettings.cipher != null) {
url += ";CIPHER=" + dbSettings.cipher;
}
eventListener.init(url);
eventListener.init(name);
} catch (Throwable e) {
throw DbException.get(ErrorCode.ERROR_SETTING_DATABASE_EVENT_LISTENER_2, e, className, e.toString());
}
Expand Down Expand Up @@ -2166,9 +2149,7 @@ public Storage getStorage(String storageEngineName) {
private String getStorageName() {
if (storageName != null)
return storageName;
String baseDir = SysProperties.getBaseDirSilently();
if (baseDir == null)
baseDir = FileUtils.getParent(FileUtils.toRealPath(fullName));
String baseDir = SysProperties.getBaseDir();
if (baseDir != null && !baseDir.endsWith(File.separator))
baseDir = baseDir + File.separator;

Expand Down Expand Up @@ -2434,6 +2415,10 @@ public synchronized int getVersion(int id) {

private static final String ROOT_USER = "ROOT";

public void createRootUserIfNotExists() {
getSystemSession().prepareStatementLocal("CREATE USER IF NOT EXISTS root PASSWORD '' ADMIN").executeUpdate();
}

boolean isRootUser(String userName) {
return ROOT_USER.equalsIgnoreCase(userName);
}
Expand Down
Expand Up @@ -123,7 +123,7 @@ private ServerSession createSession(String dbName, ConnectionInfo ci, boolean if
}
} else {
if (!database.isInitialized())
database.init(ci);
database.init();
}

synchronized (database) {
Expand Down
20 changes: 8 additions & 12 deletions lealone-db/src/main/java/org/lealone/db/LealoneDatabase.java
Expand Up @@ -20,7 +20,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import org.lealone.api.ErrorCode;
Expand Down Expand Up @@ -52,28 +51,25 @@ private LealoneDatabase() {

INSTANCE = this; // init执行过程中会触发getInstance(),此时INSTANCE为null,会导致NPE

String url = Constants.URL_PREFIX + Constants.URL_EMBED + NAME;
ConnectionInfo ci = new ConnectionInfo(url, (Properties) null);
ci.setBaseDir(SysProperties.getBaseDir());
init(ci);
createRootUser(this);
init();
createRootUserIfNotExists();
}

// 安全注释见: DatabaseEngine.ServerSessionFactory.createSession(String, ConnectionInfo, boolean)
Database createDatabase(String dbName, ConnectionInfo ci) {
String sql = getCreateSQL(quoteIdentifier(dbName), ci);
getSystemSession().prepareStatementLocal(sql).executeUpdate();
// 执行完CREATE DATABASE后会加到databases字段中
// CreateDatabase.update -> Database.addDatabaseObject -> Database.getMap -> this.getDatabasesMap
Database db = databases.get(dbName);
db.init(ci);
createRootUser(db);
if (SysProperties.CHECK) {
if (db == null) {
DbException.throwInternalError("not found: " + dbName);
}
}
return db;
}

public static void createRootUser(Database db) {
db.getSystemSession().prepareStatementLocal("CREATE USER IF NOT EXISTS root PASSWORD '' ADMIN").executeUpdate();
}

void closeDatabase(String dbName) {
databases.remove(dbName);
}
Expand Down
2 changes: 2 additions & 0 deletions lealone-db/src/main/java/org/lealone/db/ServerSession.java
Expand Up @@ -588,6 +588,8 @@ private void endTransaction() {
setAutoCommit(true);

currentStatements.clear();
containsDDL = false;
containsDatabaseStatement = false;
}

private void checkCommitRollback() {
Expand Down
40 changes: 15 additions & 25 deletions lealone-sql/src/main/java/org/lealone/sql/ddl/CreateDatabase.java
Expand Up @@ -17,19 +17,16 @@
*/
package org.lealone.sql.ddl;

import java.io.File;
import java.util.Map;

import org.lealone.api.ErrorCode;
import org.lealone.common.exceptions.DbException;
import org.lealone.common.util.StringUtils;
import org.lealone.db.Constants;
import org.lealone.db.Database;
import org.lealone.db.DbObjectType;
import org.lealone.db.LealoneDatabase;
import org.lealone.db.RunMode;
import org.lealone.db.ServerSession;
import org.lealone.db.SysProperties;
import org.lealone.sql.SQLStatement;
import org.lealone.sql.router.RouterHolder;

Expand Down Expand Up @@ -65,40 +62,33 @@ public int getType() {
@Override
public int update() {
session.getUser().checkAdmin();
LealoneDatabase db = LealoneDatabase.getInstance();
synchronized (db.getLock(DbObjectType.DATABASE)) {
if (db.findDatabase(dbName) != null || LealoneDatabase.NAME.equalsIgnoreCase(dbName)) {
LealoneDatabase lealoneDB = LealoneDatabase.getInstance();
synchronized (lealoneDB.getLock(DbObjectType.DATABASE)) {
if (lealoneDB.findDatabase(dbName) != null || LealoneDatabase.NAME.equalsIgnoreCase(dbName)) {
if (ifNotExists) {
return 0;
}
throw DbException.get(ErrorCode.DATABASE_ALREADY_EXISTS_1, dbName);
}
int id = getObjectId(db);
Database newDb = new Database(id, dbName, parameters);
newDb.setReplicationProperties(replicationProperties);
newDb.setRunMode(runMode);
int id = getObjectId(lealoneDB);
Database newDB = new Database(id, dbName, parameters);
newDB.setReplicationProperties(replicationProperties);
newDB.setRunMode(runMode);
if (parameters != null && !parameters.containsKey("hostIds")) {
int[] hostIds = RouterHolder.getRouter().getHostIds(newDb);
int[] hostIds = RouterHolder.getRouter().getHostIds(newDB);
if (hostIds != null && hostIds.length > 0)
newDb.getParameters().put("hostIds", StringUtils.arrayCombine(hostIds, ','));
newDB.getParameters().put("hostIds", StringUtils.arrayCombine(hostIds, ','));
}
db.addDatabaseObject(session, newDb);
lealoneDB.addDatabaseObject(session, newDB);

String fullName;
String baseDir = SysProperties.getBaseDirSilently();
if (baseDir == null) {
fullName = dbName;
} else {
if (baseDir != null && !baseDir.endsWith(File.separator)) {
baseDir = baseDir + File.separator;
}
fullName = baseDir + dbName;
// LealoneDatabase在启动过程中执行CREATE DATABASE时,不对数据库初始化
if (!lealoneDB.isStarting()) {
newDB.init();
newDB.createRootUserIfNotExists();
}
String url = Constants.CONN_URL_INTERNAL + ":" + dbName;
newDb.init(fullName, url);
LealoneDatabase.createRootUser(newDb);
}
return 0;

}

@Override
Expand Down
4 changes: 2 additions & 2 deletions lealone-test/src/test/java/org/lealone/test/TestBase.java
Expand Up @@ -199,8 +199,8 @@ public synchronized String getURL(String dbName) {
url.append(TEST_DIR).append('/');
} else {
if (isReplicaSetMode)
url.append(Constants.URL_RS).append("//").append("127.0.0.1").append(',').append("127.0.0.2").append(',')
.append("127.0.0.3").append('/');
url.append(Constants.URL_RS).append("//").append("127.0.0.1").append(',').append("127.0.0.2")
.append(',').append("127.0.0.3").append('/');
else {
if (ssl)
url.append(Constants.URL_SSL);
Expand Down
Expand Up @@ -28,10 +28,12 @@ public ShardingTest() {
@Test
public void run() throws Exception {
// DATABASE和TENANT是同义词,多租户时用TENANT更明确
stmt.executeUpdate("CREATE DATABASE IF NOT EXISTS ShardingTestDB RUN MODE client_server");
stmt.executeUpdate("ALTER DATABASE ShardingTestDB RUN MODE sharding");
stmt.executeUpdate("CREATE TENANT IF NOT EXISTS ShardingTestDB RUN MODE client_server");
stmt.executeUpdate("ALTER TENANT ShardingTestDB RUN MODE sharding");
// stmt.executeUpdate("CREATE DATABASE IF NOT EXISTS ShardingTestDB RUN MODE client_server");
// stmt.executeUpdate("ALTER DATABASE ShardingTestDB RUN MODE sharding");
// stmt.executeUpdate("CREATE TENANT IF NOT EXISTS ShardingTestDB RUN MODE client_server");
// stmt.executeUpdate("ALTER TENANT ShardingTestDB RUN MODE sharding");

stmt.executeUpdate("CREATE DATABASE IF NOT EXISTS ShardingTestDB RUN MODE sharding");

stmt.executeUpdate("drop table IF EXISTS ShardingTest");
stmt.executeUpdate("create table IF NOT EXISTS ShardingTest(f1 int SELECTIVITY 10, f2 int, f3 int)");
Expand Down

0 comments on commit 8186a58

Please sign in to comment.