Skip to content

Commit

Permalink
执行DROP DATABASE后删除底层所有文件
Browse files Browse the repository at this point in the history
  • Loading branch information
codefollower committed Aug 20, 2018
1 parent 31f87e9 commit 73149ed
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 89 deletions.
Expand Up @@ -177,4 +177,11 @@ public void move(String[] targetEndpoints, RunMode runMode) {
}
}

@Override
public void drop() {
close();
String storageName = (String) config.get("storageName");
FileUtils.deleteRecursive(storageName, false);
}

}
Expand Up @@ -96,6 +96,10 @@ public void run() {

private static void adaptiveOptimization() {
for (AOMap<?, ?> map : aoMaps) {
if (map.getRawMap().isClosed()) {
aoMaps.remove(map);
continue;
}
if (map.getReadPercent() > 50)
map.switchToNoBufferedMap();
else if (map.getWritePercent() > 50)
Expand All @@ -105,6 +109,10 @@ else if (map.getWritePercent() > 50)

private static void merge() {
for (BufferedMap<?, ?> map : bufferedMaps) {
if (map.getRawMap().isClosed()) {
bufferedMaps.remove(map);
continue;
}
if (map.needMerge())
addTask(map);
}
Expand Down
5 changes: 5 additions & 0 deletions lealone-common/src/main/java/org/lealone/storage/Storage.java
Expand Up @@ -18,6 +18,7 @@
package org.lealone.storage;

import java.util.Map;
import java.util.Set;

import org.lealone.common.exceptions.DbException;
import org.lealone.db.RunMode;
Expand All @@ -42,8 +43,12 @@ <K, V> StorageMap<K, V> openMap(String name, String mapType, StorageDataType key

boolean isClosed();

Set<String> getMapNames();

public default void move(String[] targetEndpoints, RunMode runMode) {
throw DbException.getUnsupportedException("move");
}

public default void drop() {
}
}
Expand Up @@ -77,6 +77,7 @@ public boolean isClosed() {
return closed;
}

@Override
public Set<String> getMapNames() {
return new HashSet<String>(maps.keySet());
}
Expand Down
Expand Up @@ -31,4 +31,5 @@ public interface TransactionEngine extends PluggableEngine {

TransactionMap<?, ?> getTransactionMap(String name);

void removeTransactionMap(String name);
}
17 changes: 17 additions & 0 deletions lealone-db/src/main/java/org/lealone/db/Database.java
Expand Up @@ -1039,6 +1039,11 @@ public ServerSession getLastSession() {
* @param session the session
*/
public synchronized void removeSession(ServerSession session) {
if (deleteFilesOnDisconnect) {
userSessions.clear();
drop();
return;
}
if (session != null) {
if (exclusiveSession == session) {
exclusiveSession = null;
Expand Down Expand Up @@ -2441,4 +2446,16 @@ synchronized User createAdminUser(String userName, byte[] userPasswordHash) {
return user;
}

public void drop() {
if (getSessionCount() > 0) {
setDeleteFilesOnDisconnect(true);
return;
}
for (Storage storage : getStorages()) {
for (String mapName : storage.getMapNames()) {
transactionEngine.removeTransactionMap(mapName);
}
storage.drop();
}
}
}
Expand Up @@ -370,6 +370,11 @@ public RedoLogRecord createRedoLogRecord(MVCCTransaction t) {
value = r.newValue;
map = maps.get(mapName);

// 有可能在执行DROP DATABASE时删除了
if (map == null) {
continue;
}

ValueString.type.write(writeBuffer, mapName);
keyValueStart = writeBuffer.position();
writeBuffer.putInt(0);
Expand Down Expand Up @@ -416,4 +421,10 @@ public void addTransactionMap(TransactionMap<?, ?> map) {
public TransactionMap<?, ?> getTransactionMap(String name) {
return tmaps.get(name);
}

@Override
public void removeTransactionMap(String name) {
removeMap(name);
tmaps.remove(name);
}
}
146 changes: 72 additions & 74 deletions lealone-sql/src/main/java/org/lealone/sql/ddl/DropDatabase.java
Expand Up @@ -6,22 +6,12 @@
*/
package org.lealone.sql.ddl;

import java.util.ArrayList;

import org.lealone.api.ErrorCode;
import org.lealone.common.exceptions.DbException;
import org.lealone.common.util.New;
import org.lealone.db.Database;
import org.lealone.db.DbObject;
import org.lealone.db.DbObjectType;
import org.lealone.db.LealoneDatabase;
import org.lealone.db.ServerSession;
import org.lealone.db.auth.Role;
import org.lealone.db.auth.User;
import org.lealone.db.schema.Schema;
import org.lealone.db.schema.SchemaObject;
import org.lealone.db.table.Table;
import org.lealone.db.table.TableType;
import org.lealone.sql.SQLStatement;

/**
Expand Down Expand Up @@ -62,17 +52,21 @@ public int update() {
throw DbException.get(ErrorCode.CANNOT_DROP_LEALONE_DATABASE);
}
Database db;
synchronized (LealoneDatabase.getInstance().getLock(DbObjectType.DATABASE)) {
db = LealoneDatabase.getInstance().getDatabase(dbName);
LealoneDatabase lealoneDB = LealoneDatabase.getInstance();
synchronized (lealoneDB.getLock(DbObjectType.DATABASE)) {
db = lealoneDB.getDatabase(dbName);
if (db == null) {
if (!ifExists)
throw DbException.get(ErrorCode.DATABASE_NOT_FOUND_1, dbName);
} else {
LealoneDatabase.getInstance().removeDatabaseObject(session, db);
lealoneDB.removeDatabaseObject(session, db);
if (isTargetEndpoint(db)) {
dropAllObjects(db);
// dropAllObjects(db);
if (deleteFiles) {
session.getDatabase().setDeleteFilesOnDisconnect(true);
db.setDeleteFilesOnDisconnect(true);
}
if (db.getSessionCount() == 0) {
db.drop();
}
}
}
Expand All @@ -81,63 +75,67 @@ public int update() {
return 0;
}

private void dropAllObjects(Database db) {
db.lockMeta(session);
db.cleanPreparedStatements();
// TODO local temp tables are not removed
for (Schema schema : db.getAllSchemas()) {
if (schema.canDrop()) {
db.removeDatabaseObject(session, schema);
}
}
ArrayList<Table> tables = db.getAllTablesAndViews(false);
for (Table t : tables) {
if (t.getName() != null && TableType.VIEW == t.getTableType()) {
db.removeSchemaObject(session, t);
}
}
for (Table t : tables) {
if (t.getName() != null && TableType.STANDARD_TABLE == t.getTableType() && !t.isHidden()) {
db.removeSchemaObject(session, t);
}
}
session.findLocalTempTable(null);
ArrayList<SchemaObject> list = New.arrayList();
list.addAll(db.getAllSchemaObjects(DbObjectType.SEQUENCE));
// maybe constraints and triggers on system tables will be allowed in
// the future
list.addAll(db.getAllSchemaObjects(DbObjectType.CONSTRAINT));
list.addAll(db.getAllSchemaObjects(DbObjectType.TRIGGER));
list.addAll(db.getAllSchemaObjects(DbObjectType.CONSTANT));
list.addAll(db.getAllSchemaObjects(DbObjectType.FUNCTION_ALIAS));
for (SchemaObject obj : list) {
if (obj.isHidden()) {
continue;
}
db.removeSchemaObject(session, obj);
}
for (User user : db.getAllUsers()) {
if (user != session.getUser()) {
db.removeDatabaseObject(session, user);
}
}
for (Role role : db.getAllRoles()) {
String sql = role.getCreateSQL();
// the role PUBLIC must not be dropped
if (sql != null) {
db.removeDatabaseObject(session, role);
}
}
ArrayList<DbObject> dbObjects = New.arrayList();
dbObjects.addAll(db.getAllRights());
dbObjects.addAll(db.getAllAggregates());
dbObjects.addAll(db.getAllUserDataTypes());
for (DbObject obj : dbObjects) {
String sql = obj.getCreateSQL();
// the role PUBLIC must not be dropped
if (sql != null) {
db.removeDatabaseObject(session, obj);
}
}
}
// Lealone不同于H2数据库,在H2的一个数据库中可以访问另一个数据库的对象,而Lealone不允许,
// 所以在H2中需要一个对象一个对象地删除,这样其他数据库中的对象对他们的引用才能解除,
// 而Lealone只要在LealoneDatabase中删除对当前数据库的引用然后删除底层的文件即可。

// private void dropAllObjects(Database db) {
// db.lockMeta(session);
// db.cleanPreparedStatements();
// // TODO local temp tables are not removed
// for (Schema schema : db.getAllSchemas()) {
// if (schema.canDrop()) {
// db.removeDatabaseObject(session, schema);
// }
// }
// ArrayList<Table> tables = db.getAllTablesAndViews(false);
// for (Table t : tables) {
// if (t.getName() != null && TableType.VIEW == t.getTableType()) {
// db.removeSchemaObject(session, t);
// }
// }
// for (Table t : tables) {
// if (t.getName() != null && TableType.STANDARD_TABLE == t.getTableType() && !t.isHidden()) {
// db.removeSchemaObject(session, t);
// }
// }
// session.findLocalTempTable(null);
// ArrayList<SchemaObject> list = New.arrayList();
// list.addAll(db.getAllSchemaObjects(DbObjectType.SEQUENCE));
// // maybe constraints and triggers on system tables will be allowed in
// // the future
// list.addAll(db.getAllSchemaObjects(DbObjectType.CONSTRAINT));
// list.addAll(db.getAllSchemaObjects(DbObjectType.TRIGGER));
// list.addAll(db.getAllSchemaObjects(DbObjectType.CONSTANT));
// list.addAll(db.getAllSchemaObjects(DbObjectType.FUNCTION_ALIAS));
// for (SchemaObject obj : list) {
// if (obj.isHidden()) {
// continue;
// }
// db.removeSchemaObject(session, obj);
// }
// for (User user : db.getAllUsers()) {
// if (user != session.getUser()) {
// db.removeDatabaseObject(session, user);
// }
// }
// for (Role role : db.getAllRoles()) {
// String sql = role.getCreateSQL();
// // the role PUBLIC must not be dropped
// if (sql != null) {
// db.removeDatabaseObject(session, role);
// }
// }
// ArrayList<DbObject> dbObjects = New.arrayList();
// dbObjects.addAll(db.getAllRights());
// dbObjects.addAll(db.getAllAggregates());
// dbObjects.addAll(db.getAllUserDataTypes());
// for (DbObject obj : dbObjects) {
// String sql = obj.getCreateSQL();
// // the role PUBLIC must not be dropped
// if (sql != null) {
// db.removeDatabaseObject(session, obj);
// }
// }
// }
}
Expand Up @@ -17,7 +17,6 @@
*/
package org.lealone.sql.router;

import org.lealone.common.exceptions.DbException;
import org.lealone.db.Database;
import org.lealone.db.ServerSession;
import org.lealone.db.result.Result;
Expand Down Expand Up @@ -52,6 +51,6 @@ public String[] getHostIds(Database db, boolean alterDatabase) {

@Override
public int executeDatabaseStatement(Database db, ServerSession currentSession, StatementBase statement) {
throw DbException.throwInternalError("executeDatabaseStatement");
return 0;
}
}
Expand Up @@ -27,38 +27,55 @@ public DatabaseStatementTest() {
super(LealoneDatabase.NAME);
}

private void printException(Exception e) {
System.out.println(getRootCause(e).getMessage());
}

@Test
public void run() throws Exception {
executeUpdate("CREATE DATABASE IF NOT EXISTS DatabaseStatementTest");
new NoRightTest("DatabaseStatementTest").runTest();

try {
executeUpdate("DROP DATABASE IF EXISTS DatabaseStatementTest DELETE FILES");
} catch (Exception e) {
e.printStackTrace();
}

// 不能删除lealone数据库
try {
executeUpdate("DROP DATABASE lealone");
executeUpdate("DROP DATABASE " + LealoneDatabase.NAME);
fail();
} catch (Exception e) {
System.out.println(getRootCause(e).getMessage());
printException(e);
}

executeUpdate("CREATE DATABASE IF NOT EXISTS DatabaseStatementTest");

new NoRightTest("DatabaseStatementTest").runTest();

executeUpdate("DROP DATABASE IF EXISTS DatabaseStatementTest DELETE FILES");
}

private static class NoRightTest extends SqlTestBase {
private class NoRightTest extends SqlTestBase {

public NoRightTest(String dbName) {
super(dbName);
}

@Override
protected void test() throws Exception {
// 只有以管理员身份连到lealone数据库时才能执行CREATE/ALTER/DROP DATABASE语句
try {
executeUpdate("CREATE DATABASE IF NOT EXISTS db1");
fail();
} catch (Exception e) {
printException(e);
}

try {
executeUpdate("ALTER DATABASE DatabaseStatementTest RUN MODE REPLICATION");
fail();
} catch (Exception e) {
printException(e);
}

try {
executeUpdate("DROP DATABASE IF EXISTS DatabaseStatementTest");
fail();
} catch (Exception e) {
System.out.println(getRootCause(e).getMessage());
printException(e);
}
}
}
Expand Down

0 comments on commit 73149ed

Please sign in to comment.