Просмотр исходного кода

:art: 改进内核任务调度机制提升稳定性 https://github.com/siyuan-note/siyuan/issues/7113

Liang Ding 2 лет назад
Родитель
Сommit
5aff312a7b
3 измененных файлов с 64 добавлено и 54 удалено
  1. 62 38
      kernel/model/index_fix.go
  2. 0 14
      kernel/sql/block.go
  3. 2 2
      kernel/sql/block_query.go

+ 62 - 38
kernel/model/index_fix.go

@@ -25,6 +25,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/88250/gulu"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/html"
 	"github.com/88250/lute/parse"
@@ -48,6 +49,42 @@ var autoFixLock = sync.Mutex{}
 func autoFixIndex() {
 	defer logging.Recover()
 
+	autoFixLock.Lock()
+	defer autoFixLock.Unlock()
+
+	// 去除重复的数据库块记录
+	duplicatedRootIDs := sql.GetDuplicatedRootIDs("blocks")
+	if 1 > len(duplicatedRootIDs) {
+		duplicatedRootIDs = sql.GetDuplicatedRootIDs("blocks_fts")
+		if 1 > len(duplicatedRootIDs) && !Conf.Search.CaseSensitive {
+			duplicatedRootIDs = sql.GetDuplicatedRootIDs("blocks_fts_case_insensitive")
+		}
+	}
+
+	roots := sql.GetBlocks(duplicatedRootIDs)
+	rootMap := map[string]*sql.Block{}
+	for _, root := range roots {
+		rootMap[root.ID] = root
+	}
+	for _, rootID := range duplicatedRootIDs {
+		root := rootMap[rootID]
+		if nil == root {
+			continue
+		}
+
+		//logging.LogWarnf("exist more than one tree [%s], reindex it", rootID)
+		sql.RemoveTreeQueue(root.Box, rootID)
+
+		if util.IsExiting {
+			break
+		}
+	}
+	if 0 < len(duplicatedRootIDs) {
+		logging.LogWarnf("exist more than one tree duplicated [%d], reindex it", len(duplicatedRootIDs))
+	}
+
+	sql.WaitForWritingDatabase()
+
 	// 根据文件系统补全块树
 	boxes := Conf.GetOpenedBoxes()
 	for _, box := range boxes {
@@ -88,6 +125,8 @@ func autoFixIndex() {
 		}
 	}
 
+	sql.WaitForWritingDatabase()
+
 	// 清理已关闭的笔记本块树
 	boxes = Conf.GetClosedBoxes()
 	for _, box := range boxes {
@@ -96,49 +135,17 @@ func autoFixIndex() {
 
 	// 对比块树和数据库并订正数据库
 	rootUpdatedMap := treenode.GetRootUpdated()
-	dbRootUpdatedMap, err := sql.GetRootUpdated("blocks")
+	dbRootUpdatedMap, err := sql.GetRootUpdated()
 	if nil == err {
-		reindexTreeByUpdated(rootUpdatedMap, dbRootUpdatedMap, "blocks")
-	}
-	dbFtsRootUpdatedMap, err := sql.GetRootUpdated("blocks_fts")
-	if nil == err {
-		reindexTreeByUpdated(rootUpdatedMap, dbFtsRootUpdatedMap, "blocks_fts")
-	}
-	if !Conf.Search.CaseSensitive {
-		dbFtsRootUpdatedMap, err = sql.GetRootUpdated("blocks_fts_case_insensitive")
-		if nil == err {
-			reindexTreeByUpdated(rootUpdatedMap, dbFtsRootUpdatedMap, "blocks_fts_case_insensitive")
-		}
-	}
-
-	// 去除重复的数据库块记录
-	duplicatedRootIDs := sql.GetDuplicatedRootIDs("blocks")
-	if 1 > len(duplicatedRootIDs) {
-		duplicatedRootIDs = sql.GetDuplicatedRootIDs("blocks_fts")
-		if 1 > len(duplicatedRootIDs) && !Conf.Search.CaseSensitive {
-			duplicatedRootIDs = sql.GetDuplicatedRootIDs("blocks_fts_case_insensitive")
-		}
+		reindexTreeByUpdated(rootUpdatedMap, dbRootUpdatedMap)
 	}
-	size := len(duplicatedRootIDs)
-	for i, rootID := range duplicatedRootIDs {
-		root := sql.GetBlock(rootID)
-		if nil == root {
-			continue
-		}
-
-		logging.LogWarnf("exist more than one tree [%s], reindex it", rootID)
-		sql.RemoveTreeQueue(root.Box, rootID)
-		reindexTree(rootID, i, size)
 
-		if util.IsExiting {
-			break
-		}
-	}
+	sql.WaitForWritingDatabase()
 
 	util.PushStatusBar(Conf.Language(185))
 }
 
-func reindexTreeByUpdated(rootUpdatedMap, dbRootUpdatedMap map[string]string, blocksTable string) {
+func reindexTreeByUpdated(rootUpdatedMap, dbRootUpdatedMap map[string]string) {
 	i := -1
 	size := len(rootUpdatedMap)
 	for rootID, updated := range rootUpdatedMap {
@@ -174,12 +181,29 @@ func reindexTreeByUpdated(rootUpdatedMap, dbRootUpdatedMap map[string]string, bl
 		}
 	}
 
+	var rootIDs []string
 	for rootID, _ := range dbRootUpdatedMap {
 		if _, ok := rootUpdatedMap[rootID]; !ok {
-			logging.LogWarnf("tree [%s] is not in block tree, remove it from [%s]", rootID, blocksTable)
-			sql.DeleteTree(blocksTable, rootID)
+			rootIDs = append(rootIDs, rootID)
+		}
+
+		if util.IsExiting {
+			break
+		}
+	}
+	rootIDs = gulu.Str.RemoveDuplicatedElem(rootIDs)
+	roots := map[string]*sql.Block{}
+	blocks := sql.GetBlocks(rootIDs)
+	for _, block := range blocks {
+		roots[block.RootID] = block
+	}
+	for id, root := range roots {
+		if nil == root {
+			continue
 		}
 
+		logging.LogWarnf("tree [%s] is not in block tree, remove it from [%s]", id, root.Box)
+		sql.RemoveTreeQueue(root.Box, root.ID)
 		if util.IsExiting {
 			break
 		}

+ 0 - 14
kernel/sql/block.go

@@ -92,17 +92,3 @@ func UpdateBlockContent(block *Block) {
 	tx.Commit()
 	putBlockCache(block)
 }
-
-func DeleteTree(table, rootID string) {
-	tx, err := beginTx()
-	if nil != err {
-		return
-	}
-
-	stmt := "DELETE FROM `" + table + "` WHERE root_id = ?"
-	if err = execStmtTx(tx, stmt, rootID); nil != err {
-		tx.Rollback()
-		return
-	}
-	tx.Commit()
-}

+ 2 - 2
kernel/sql/block_query.go

@@ -597,8 +597,8 @@ func GetBlock(id string) (ret *Block) {
 	return
 }
 
-func GetRootUpdated(blocksTable string) (ret map[string]string, err error) {
-	rows, err := query("SELECT root_id, updated FROM `" + blocksTable + "` WHERE type = 'd'")
+func GetRootUpdated() (ret map[string]string, err error) {
+	rows, err := query("SELECT root_id, updated FROM `blocks` WHERE type = 'd'")
 	if nil != err {
 		logging.LogErrorf("sql query failed: %s", err)
 		return