This is an automated email from the ASF dual-hosted git repository.
qiaojialin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 8f3edd7 [IOTDB-672] Fix delete storage group bug during restart
(#1310)
8f3edd7 is described below
commit 8f3edd731d7fbe5f091efa1dfb4ccafd6ac82784
Author: Haonan <[email protected]>
AuthorDate: Thu Jun 4 16:24:54 2020 +0800
[IOTDB-672] Fix delete storage group bug during restart (#1310)
* fix delete all timeseries in storage group and recover bug
---
docs/SystemDesign/SchemaManager/SchemaManager.md | 4 +-
.../zh/SystemDesign/SchemaManager/SchemaManager.md | 4 +-
.../org/apache/iotdb/db/metadata/MManager.java | 48 +++++++++-------------
.../apache/iotdb/db/qp/executor/PlanExecutor.java | 11 ++---
4 files changed, 27 insertions(+), 40 deletions(-)
diff --git a/docs/SystemDesign/SchemaManager/SchemaManager.md
b/docs/SystemDesign/SchemaManager/SchemaManager.md
index cec2c86..c8b6616 100644
--- a/docs/SystemDesign/SchemaManager/SchemaManager.md
+++ b/docs/SystemDesign/SchemaManager/SchemaManager.md
@@ -55,11 +55,11 @@ In the process of initializing, MManager will replay the
mlog to load the metada
* if succeed
* delete the LeafMNode
* read tlog using offset in the LeafMNode, update tag
inverted index
- * if the storage group becomes empty after deleting,
return the name of it
+ * if the storage group becomes empty after deleting,
record its name
* if failed
* return the full path of failed timeseries
- * iterate the returned empty storage group list, and delete them
* if not restart
+ * delete the recorded empty storage group
* persist log into mlog
* currently, we won't delete the tag/attribute info of that
timeseries in tlog
diff --git a/docs/zh/SystemDesign/SchemaManager/SchemaManager.md
b/docs/zh/SystemDesign/SchemaManager/SchemaManager.md
index 8a4cba2..afda6c1 100644
--- a/docs/zh/SystemDesign/SchemaManager/SchemaManager.md
+++ b/docs/zh/SystemDesign/SchemaManager/SchemaManager.md
@@ -54,11 +54,11 @@ IoTDB 的元数据统一由 MManger 管理,包括以下几个部分:
* 若获取成功
* 删除MTree中对应的LeafMNode
* 根据LeafMNode中的offset,读取标签文件,更新 tagIndex 索引
- * 若发现某一个存储组为空,则返回为空的存储组名
+ * 若发现某一个存储组为空,则记录下该空的存储组名
* 若获取失败
* 返回此未删除成功的时间序列
- * 遍历上一步返回的为空的存储组,依次删除
* 如果非重启(需要记录日志)
+ * 删除记录下的空的存储组
* 将所删除的时间序列信息记录到 mlog 中
* 目前并不会删除 tlog 中关于此时间序列的标签/属性信息。
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
index 8bfd480..c754c76 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
@@ -72,7 +72,7 @@ public class MManager {
private MTree mtree;
private MLogWriter logWriter;
private TagLogFile tagLogFile;
- private boolean writeToLog;
+ private boolean isRecovering;
// device -> DeviceMNode
private RandomDeleteCache<String, MNode> mNodeCache;
@@ -108,7 +108,7 @@ public class MManager {
logFilePath = schemaDir + File.separator + MetadataConstant.METADATA_LOG;
// do not write log when recover
- writeToLog = false;
+ isRecovering = true;
int cacheSize = config.getmManagerCacheSize();
mNodeCache =
@@ -156,7 +156,7 @@ public class MManager {
}
logWriter = new MLogWriter(config.getSchemaDir(),
MetadataConstant.METADATA_LOG);
- writeToLog = true;
+ isRecovering = false;
} catch (IOException | MetadataException e) {
mtree = new MTree();
logger.error("Cannot read MTree from file, using an empty new one", e);
@@ -243,12 +243,9 @@ public class MManager {
createTimeseries(plan, offset);
break;
case MetadataOperationType.DELETE_TIMESERIES:
- Pair<Set<String>, String> pair = deleteTimeseries(args[1]);
- for (String deleteStorageGroup : pair.left) {
-
StorageEngine.getInstance().deleteAllDataFilesInOneStorageGroup(deleteStorageGroup);
- }
- if (!pair.right.isEmpty()) {
- throw new DeleteFailedException(pair.right);
+ String failedTimeseries = deleteTimeseries(args[1]);
+ if (!failedTimeseries.isEmpty()) {
+ throw new DeleteFailedException(failedTimeseries);
}
break;
case MetadataOperationType.SET_STORAGE_GROUP:
@@ -319,7 +316,7 @@ public class MManager {
}
// write log
- if (writeToLog) {
+ if (!isRecovering) {
// either tags or attributes is not empty
if ((plan.getTags() != null && !plan.getTags().isEmpty())
|| (plan.getAttributes() != null &&
!plan.getAttributes().isEmpty())) {
@@ -357,11 +354,9 @@ public class MManager {
* Delete all timeseries under the given path, may cross different storage
group
*
* @param prefixPath path to be deleted, could be root or a prefix path or a
full path
- * @return 1. The Set contains StorageGroups that contain no more timeseries
after this deletion
- * files of such StorageGroups should be deleted to reclaim disk space. 2.
The String is the
- * deletion failed Timeseries
+ * @return The String is the deletion failed Timeseries
*/
- public Pair<Set<String>, String> deleteTimeseries(String prefixPath) throws
MetadataException {
+ public String deleteTimeseries(String prefixPath) throws MetadataException {
lock.writeLock().lock();
if (isStorageGroup(prefixPath)) {
@@ -378,8 +373,6 @@ public class MManager {
mNodeCache.clear();
}
try {
- Set<String> emptyStorageGroups = new HashSet<>();
-
List<String> allTimeseries = mtree.getAllTimeseriesName(prefixPath);
// Monitor storage group seriesPath is not allowed to be deleted
allTimeseries.removeIf(p ->
p.startsWith(MonitorConstants.STAT_STORAGE_GROUP_PREFIX));
@@ -387,15 +380,18 @@ public class MManager {
Set<String> failedNames = new HashSet<>();
for (String p : allTimeseries) {
try {
- String emptyStorageGroup =
deleteOneTimeseriesAndUpdateStatisticsAndLog(p);
- if (emptyStorageGroup != null) {
- emptyStorageGroups.add(emptyStorageGroup);
+ String emptyStorageGroup = deleteOneTimeseriesAndUpdateStatistics(p);
+ if (!isRecovering) {
+ if (emptyStorageGroup != null) {
+
StorageEngine.getInstance().deleteAllDataFilesInOneStorageGroup(emptyStorageGroup);
+ }
+ logWriter.deleteTimeseries(p);
}
} catch (DeleteFailedException e) {
failedNames.add(e.getName());
}
}
- return new Pair<>(emptyStorageGroups, String.join(",", failedNames));
+ return String.join(",", failedNames);
} catch (IOException e) {
throw new MetadataException(e.getMessage());
} finally {
@@ -432,7 +428,7 @@ public class MManager {
* @param path full path from root to leaf node
* @return after delete if the storage group is empty, return its name,
otherwise return null
*/
- private String deleteOneTimeseriesAndUpdateStatisticsAndLog(String path)
+ private String deleteOneTimeseriesAndUpdateStatistics(String path)
throws MetadataException, IOException {
lock.writeLock().lock();
try {
@@ -457,10 +453,6 @@ public class MManager {
.ifPresent(val -> maxSeriesNumberAmongStorageGroup = val);
}
}
-
- if (writeToLog) {
- logWriter.deleteTimeseries(path);
- }
return storageGroupName;
} finally {
lock.writeLock().unlock();
@@ -482,7 +474,7 @@ public class MManager {
ActiveTimeSeriesCounter.getInstance().init(storageGroup);
seriesNumberInStorageGroups.put(storageGroup, 0);
}
- if (writeToLog) {
+ if (!isRecovering) {
logWriter.setStorageGroup(storageGroup);
}
} catch (IOException e) {
@@ -523,7 +515,7 @@ public class MManager {
}
}
// if success
- if (writeToLog) {
+ if (!isRecovering) {
logWriter.deleteStorageGroup(storageGroup);
}
}
@@ -978,7 +970,7 @@ public class MManager {
lock.writeLock().lock();
try {
getStorageGroupNode(storageGroup).setDataTTL(dataTTL);
- if (writeToLog) {
+ if (!isRecovering) {
logWriter.setTTL(storageGroup, dataTTL);
}
} finally {
diff --git
a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
index 5d6a268..48697ee 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
@@ -1143,18 +1143,13 @@ public class PlanExecutor implements IPlanExecutor {
List<Path> deletePathList = deleteTimeSeriesPlan.getPaths();
try {
deleteDataOfTimeSeries(deletePathList);
- Set<String> emptyStorageGroups = new HashSet<>();
List<String> failedNames = new LinkedList<>();
for (Path path : deletePathList) {
- Pair<Set<String>, String> pair =
mManager.deleteTimeseries(path.toString());
- emptyStorageGroups.addAll(pair.left);
- if (!pair.right.isEmpty()) {
- failedNames.add(pair.right);
+ String failedTimeseries = mManager.deleteTimeseries(path.toString());
+ if (!failedTimeseries.isEmpty()) {
+ failedNames.add(failedTimeseries);
}
}
- for (String deleteStorageGroup : emptyStorageGroups) {
-
StorageEngine.getInstance().deleteAllDataFilesInOneStorageGroup(deleteStorageGroup);
- }
if (!failedNames.isEmpty()) {
throw new DeleteFailedException(String.join(",", failedNames));
}