Browse Source

:art: 清理块树中重复冗余的数据

Liang Ding 2 years ago
parent
commit
c0240f20d6
4 changed files with 127 additions and 92 deletions
  1. 3 5
      kernel/model/index_fix.go
  2. 8 0
      kernel/sql/queue.go
  3. 0 87
      kernel/treenode/blocktree.go
  4. 116 0
      kernel/treenode/blocktree_fix.go

+ 3 - 5
kernel/model/index_fix.go

@@ -106,12 +106,10 @@ func autoFixIndex() {
 
 		size := len(paths)
 
-		// 清理块树中重复冗余的数据
-		redundantPaths := treenode.GetRedundantPaths(box.ID, paths)
-		for _, p := range redundantPaths {
-			treenode.RemoveBlockTreesByPath(box.ID, p)
-		}
+		// 清理块树中的冗余数据
+		treenode.ClearRedundantBlockTrees(box.ID, paths)
 
+		// 重新索引缺失的块树
 		missingPaths := treenode.GetNotExistPaths(box.ID, paths)
 		for i, p := range missingPaths {
 			id := path.Base(p)

+ 8 - 0
kernel/sql/queue.go

@@ -181,6 +181,10 @@ func execOp(op *dbQueueOperation, tx *sql.Tx, context map[string]interface{}) (e
 }
 
 func BatchRemoveAssetsQueue(hashes []string) {
+	if 1 > len(hashes) {
+		return
+	}
+
 	dbQueueLock.Lock()
 	defer dbQueueLock.Unlock()
 
@@ -319,6 +323,10 @@ func RemoveTreeQueue(box, rootID string) {
 }
 
 func BatchRemoveTreeQueue(rootIDs []string) {
+	if 1 > len(rootIDs) {
+		return
+	}
+
 	dbQueueLock.Lock()
 	defer dbQueueLock.Unlock()
 

+ 0 - 87
kernel/treenode/blocktree.go

@@ -55,22 +55,6 @@ type BlockTree struct {
 	Type     string // 类型
 }
 
-func GetRootUpdated() (ret map[string]string) {
-	ret = map[string]string{}
-	blockTrees.Range(func(key, value interface{}) bool {
-		slice := value.(*btSlice)
-		slice.m.Lock()
-		for _, b := range slice.data {
-			if b.RootID == b.ID {
-				ret[b.RootID] = b.Updated
-			}
-		}
-		slice.m.Unlock()
-		return true
-	})
-	return
-}
-
 func GetBlockTreeByPath(path string) (ret *BlockTree) {
 	blockTrees.Range(func(key, value interface{}) bool {
 		slice := value.(*btSlice)
@@ -113,62 +97,6 @@ func CountBlocks() (ret int) {
 	return
 }
 
-func GetRedundantPaths(boxID string, paths []string) (ret []string) {
-	pathsMap := map[string]bool{}
-	for _, path := range paths {
-		pathsMap[path] = true
-	}
-
-	btPathsMap := map[string]bool{}
-	blockTrees.Range(func(key, value interface{}) bool {
-		slice := value.(*btSlice)
-		slice.m.Lock()
-		for _, b := range slice.data {
-			if b.BoxID == boxID {
-				btPathsMap[b.Path] = true
-			}
-		}
-		slice.m.Unlock()
-		return true
-	})
-
-	for p, _ := range btPathsMap {
-		if !pathsMap[p] {
-			ret = append(ret, p)
-		}
-	}
-	ret = gulu.Str.RemoveDuplicatedElem(ret)
-	return
-}
-
-func GetNotExistPaths(boxID string, paths []string) (ret []string) {
-	pathsMap := map[string]bool{}
-	for _, path := range paths {
-		pathsMap[path] = true
-	}
-
-	btPathsMap := map[string]bool{}
-	blockTrees.Range(func(key, value interface{}) bool {
-		slice := value.(*btSlice)
-		slice.m.Lock()
-		for _, b := range slice.data {
-			if b.BoxID == boxID {
-				btPathsMap[b.Path] = true
-			}
-		}
-		slice.m.Unlock()
-		return true
-	})
-
-	for p, _ := range pathsMap {
-		if !btPathsMap[p] {
-			ret = append(ret, p)
-		}
-	}
-	ret = gulu.Str.RemoveDuplicatedElem(ret)
-	return
-}
-
 func GetBlockTreeRootByPath(boxID, path string) (ret *BlockTree) {
 	blockTrees.Range(func(key, value interface{}) bool {
 		slice := value.(*btSlice)
@@ -269,21 +197,6 @@ func RemoveBlockTreesByRootID(rootID string) {
 	}
 }
 
-func RemoveBlockTreesByPath(boxID, path string) {
-	blockTrees.Range(func(key, value interface{}) bool {
-		slice := value.(*btSlice)
-		slice.m.Lock()
-		for _, b := range slice.data {
-			if b.Path == path && b.BoxID == boxID {
-				delete(slice.data, b.ID)
-				slice.changed = time.Now()
-			}
-		}
-		slice.m.Unlock()
-		return true
-	})
-}
-
 func RemoveBlockTreesByPathPrefix(pathPrefix string) {
 	var ids []string
 	blockTrees.Range(func(key, value interface{}) bool {

+ 116 - 0
kernel/treenode/blocktree_fix.go

@@ -0,0 +1,116 @@
+// SiYuan - Build Your Eternal Digital Garden
+// Copyright (c) 2020-present, b3log.org
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+package treenode
+
+import (
+	"github.com/88250/gulu"
+	"time"
+)
+
+func ClearRedundantBlockTrees(boxID string, paths []string) {
+	redundantPaths := getRedundantPaths(boxID, paths)
+	for _, p := range redundantPaths {
+		removeBlockTreesByPath(boxID, p)
+	}
+}
+
+func getRedundantPaths(boxID string, paths []string) (ret []string) {
+	pathsMap := map[string]bool{}
+	for _, path := range paths {
+		pathsMap[path] = true
+	}
+
+	btPathsMap := map[string]bool{}
+	blockTrees.Range(func(key, value interface{}) bool {
+		slice := value.(*btSlice)
+		slice.m.Lock()
+		for _, b := range slice.data {
+			if b.BoxID == boxID {
+				btPathsMap[b.Path] = true
+			}
+		}
+		slice.m.Unlock()
+		return true
+	})
+
+	for p, _ := range btPathsMap {
+		if !pathsMap[p] {
+			ret = append(ret, p)
+		}
+	}
+	ret = gulu.Str.RemoveDuplicatedElem(ret)
+	return
+}
+
+func removeBlockTreesByPath(boxID, path string) {
+	blockTrees.Range(func(key, value interface{}) bool {
+		slice := value.(*btSlice)
+		slice.m.Lock()
+		for _, b := range slice.data {
+			if b.Path == path && b.BoxID == boxID {
+				delete(slice.data, b.ID)
+				slice.changed = time.Now()
+			}
+		}
+		slice.m.Unlock()
+		return true
+	})
+}
+
+func GetNotExistPaths(boxID string, paths []string) (ret []string) {
+	pathsMap := map[string]bool{}
+	for _, path := range paths {
+		pathsMap[path] = true
+	}
+
+	btPathsMap := map[string]bool{}
+	blockTrees.Range(func(key, value interface{}) bool {
+		slice := value.(*btSlice)
+		slice.m.Lock()
+		for _, b := range slice.data {
+			if b.BoxID == boxID {
+				btPathsMap[b.Path] = true
+			}
+		}
+		slice.m.Unlock()
+		return true
+	})
+
+	for p, _ := range pathsMap {
+		if !btPathsMap[p] {
+			ret = append(ret, p)
+		}
+	}
+	ret = gulu.Str.RemoveDuplicatedElem(ret)
+	return
+}
+
+func GetRootUpdated() (ret map[string]string) {
+	ret = map[string]string{}
+	blockTrees.Range(func(key, value interface{}) bool {
+		slice := value.(*btSlice)
+		slice.m.Lock()
+		for _, b := range slice.data {
+			if b.RootID == b.ID {
+				ret[b.RootID] = b.Updated
+			}
+		}
+		slice.m.Unlock()
+		return true
+	})
+	return
+}