diff --git a/kernel/cache/tree.go b/kernel/cache/tree.go new file mode 100644 index 000000000..836d2149a --- /dev/null +++ b/kernel/cache/tree.go @@ -0,0 +1,54 @@ +// SiYuan - Refactor your thinking +// 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 . + +package cache + +import ( + "github.com/dgraph-io/ristretto" +) + +type treeCacheEntry struct { + raw []byte +} + +var ( + treeCache, _ = ristretto.NewCache(&ristretto.Config{ + NumCounters: 8, + MaxCost: 1024 * 1024 * 200, + BufferItems: 64, + }) +) + +func GetTreeData(rootID string) (raw []byte, ok bool) { + v, _ := treeCache.Get(rootID) + if nil == v { + return nil, false + } + e := v.(*treeCacheEntry) + return e.raw, true +} + +func SetTreeData(rootID string, raw []byte) { + if raw == nil { + return + } + entry := &treeCacheEntry{raw: raw} + treeCache.Set(rootID, entry, int64(len(raw))) +} + +func RemoveTreeData(rootID string) { + treeCache.Del(rootID) +} diff --git a/kernel/filesys/tree.go b/kernel/filesys/tree.go index bbd4c293a..6713453c1 100644 --- a/kernel/filesys/tree.go +++ b/kernel/filesys/tree.go @@ -115,14 +115,23 @@ func batchLoadTrees(boxIDs, paths []string, luteEngine *lute.Lute) (ret []*parse } func LoadTree(boxID, p string, luteEngine *lute.Lute) (ret *parse.Tree, err error) { + rootID := util.GetTreeID(p) + if raw, ok := cache.GetTreeData(rootID); ok { + ret, err = LoadTreeByData(raw, boxID, p, luteEngine) + return + } + filePath := filepath.Join(util.DataDir, boxID, p) data, err := filelock.ReadFile(filePath) - if err != nil { + if nil != err { logging.LogErrorf("load tree [%s] failed: %s", p, err) return } ret, err = LoadTreeByData(data, boxID, p, luteEngine) + if nil != err { + cache.SetTreeData(rootID, data) + } return } @@ -146,7 +155,7 @@ func LoadTreeByData(data []byte, boxID, p string, luteEngine *lute.Lute) (ret *p // 构造 HPath hPathBuilder := bytes.Buffer{} hPathBuilder.WriteString("/") - for i, _ := range parts { + for i := range parts { var parentAbsPath string if 0 < i { parentAbsPath = strings.Join(parts[:i+1], "/") @@ -232,6 +241,7 @@ func WriteTree(tree *parse.Tree) (size uint64, err error) { util.PushErrMsg(msg, 7000) } + cache.SetTreeData(tree.ID, data) afterWriteTree(tree) return } diff --git a/kernel/model/file.go b/kernel/model/file.go index 2bb3fddd1..9bdfd1ad5 100644 --- a/kernel/model/file.go +++ b/kernel/model/file.go @@ -1647,6 +1647,7 @@ func removeDoc0(tree *parse.Tree, childrenDir string) { treenode.RemoveBlockTreesByPathPrefix(childrenDir) sql.RemoveTreePathQueue(tree.Box, childrenDir) cache.RemoveDocIAL(tree.Path) + cache.RemoveTreeData(tree.ID) return }