diff --git a/kernel/cache/asset.go b/kernel/cache/asset.go index fa623de9a..fc20c0891 100644 --- a/kernel/cache/asset.go +++ b/kernel/cache/asset.go @@ -34,25 +34,45 @@ type AssetHash struct { } var ( - assetHashCache = map[string]*AssetHash{} - assetHashLock = sync.Mutex{} + assetHashCache = map[string]*AssetHash{} + assetPathHashCache = map[string]*AssetHash{} + assetHashLock = sync.Mutex{} ) func RemoveAssetHash(hash string) { assetHashLock.Lock() defer assetHashLock.Unlock() - delete(assetHashCache, hash) + asset := assetHashCache[hash] + if nil != asset { + delete(assetHashCache, hash) + delete(assetPathHashCache, asset.Path) + } } func SetAssetHash(hash, path string) { assetHashLock.Lock() defer assetHashLock.Unlock() - assetHashCache[hash] = &AssetHash{ - Hash: hash, - Path: path, + assetHashCache[hash] = &AssetHash{Hash: hash, Path: path} + assetPathHashCache[path] = &AssetHash{Hash: hash, Path: path} +} + +func GetAssetHashByPath(path string) *AssetHash { + assetHashLock.Lock() + defer assetHashLock.Unlock() + + asset, exists := assetPathHashCache[path] + if exists { + if filelock.IsExist(filepath.Join(util.DataDir, asset.Path)) { + return asset + } + + delete(assetHashCache, asset.Hash) + delete(assetPathHashCache, path) + return nil } + return nil } func GetAssetHash(hash string) *AssetHash { @@ -66,6 +86,7 @@ func GetAssetHash(hash string) *AssetHash { } delete(assetHashCache, hash) + delete(assetPathHashCache, a.Path) return nil } } diff --git a/kernel/model/assets.go b/kernel/model/assets.go index 77de9640b..b17bf1374 100644 --- a/kernel/model/assets.go +++ b/kernel/model/assets.go @@ -93,6 +93,13 @@ func HandleAssetsRemoveEvent(assetAbsPath string) { removeIndexAssetContent(assetAbsPath) removeAssetThumbnail(assetAbsPath) + + hash, err := util.GetEtag(assetAbsPath) + if nil != err { + logging.LogErrorf("calc asset [%s] hash failed: %s", assetAbsPath, err) + } else { + cache.RemoveAssetHash(hash) + } } func HandleAssetsChangeEvent(assetAbsPath string) { @@ -106,6 +113,15 @@ func HandleAssetsChangeEvent(assetAbsPath string) { indexAssetContent(assetAbsPath) removeAssetThumbnail(assetAbsPath) + + hash, err := util.GetEtag(assetAbsPath) + if nil != err { + logging.LogErrorf("calc asset [%s] hash failed: %s", assetAbsPath, err) + } else { + p := strings.TrimPrefix(assetAbsPath, util.DataDir) + p = filepath.ToSlash(p) + cache.SetAssetHash(hash, p) + } } func removeAssetThumbnail(assetAbsPath string) { diff --git a/kernel/sql/asset.go b/kernel/sql/asset.go index 8819b756f..501b1a5ab 100644 --- a/kernel/sql/asset.go +++ b/kernel/sql/asset.go @@ -21,9 +21,11 @@ import ( "path/filepath" "strings" + "github.com/88250/gulu" "github.com/88250/lute/ast" "github.com/siyuan-note/filelock" "github.com/siyuan-note/logging" + "github.com/siyuan-note/siyuan/kernel/cache" "github.com/siyuan-note/siyuan/kernel/treenode" "github.com/siyuan-note/siyuan/kernel/util" ) @@ -69,16 +71,7 @@ func docTitleImgAsset(root *ast.Node, boxLocalPath, docDirLocalPath string) *Ass return nil } - var hash string - var err error - if lp := assetLocalPath(p, boxLocalPath, docDirLocalPath); "" != lp { - hash, err = util.GetEtag(lp) - if err != nil { - logging.LogErrorf("calc asset [%s] hash failed: %s", lp, err) - return nil - } - } - + hash := assetHashByLocalPath(p, boxLocalPath, docDirLocalPath) name, _ := util.LastID(p) asset := &Asset{ ID: ast.NewNodeID(), @@ -126,6 +119,22 @@ func scanAssetRows(rows *sql.Rows) (ret *Asset) { return } +func assetHashByLocalPath(linkDest, boxLocalPath, docDirLocalPath string) (ret string) { + if lp := assetLocalPath(linkDest, boxLocalPath, docDirLocalPath); "" != lp { + if !gulu.File.IsDir(lp) { + if assetHash := cache.GetAssetHashByPath(linkDest); nil != assetHash { + ret = assetHash.Hash + } else { + ret, _ = util.GetEtag(lp) + if "" != ret { + cache.SetAssetHash(ret, linkDest) + } + } + } + } + return +} + func assetLocalPath(linkDest, boxLocalPath, docDirLocalPath string) (ret string) { ret = filepath.Join(docDirLocalPath, linkDest) if filelock.IsExist(ret) { diff --git a/kernel/sql/database.go b/kernel/sql/database.go index e5620aac3..e55bb8f93 100644 --- a/kernel/sql/database.go +++ b/kernel/sql/database.go @@ -649,16 +649,7 @@ func buildSpanFromNode(n *ast.Node, tree *parse.Tree, rootID, boxID, p string) ( title = gulu.Str.FromBytes(titleNode.Tokens) } - var hash string - var hashErr error - if lp := assetLocalPath(dest, boxLocalPath, docDirLocalPath); "" != lp { - if !gulu.File.IsDir(lp) { - hash, hashErr = util.GetEtag(lp) - if nil != hashErr { - logging.LogErrorf("calc asset [%s] hash failed: %s", lp, hashErr) - } - } - } + hash := assetHashByLocalPath(dest, boxLocalPath, docDirLocalPath) name, _ := util.LastID(dest) asset := &Asset{ ID: ast.NewNodeID(), @@ -700,16 +691,7 @@ func buildSpanFromNode(n *ast.Node, tree *parse.Tree, rootID, boxID, p string) ( title = gulu.Str.FromBytes(titleNode.Tokens) } - var hash string - var hashErr error - if lp := assetLocalPath(dest, boxLocalPath, docDirLocalPath); "" != lp { - if !gulu.File.IsDir(lp) { - hash, hashErr = util.GetEtag(lp) - if nil != hashErr { - logging.LogErrorf("calc asset [%s] hash failed: %s", lp, hashErr) - } - } - } + hash := assetHashByLocalPath(dest, boxLocalPath, docDirLocalPath) name, _ := util.LastID(dest) asset := &Asset{ ID: ast.NewNodeID(), @@ -790,15 +772,7 @@ func buildSpanFromNode(n *ast.Node, tree *parse.Tree, rootID, boxID, p string) ( } dest := string(src) - var hash string - var hashErr error - if lp := assetLocalPath(dest, boxLocalPath, docDirLocalPath); "" != lp { - hash, hashErr = util.GetEtag(lp) - if nil != hashErr { - logging.LogErrorf("calc asset [%s] hash failed: %s", lp, hashErr) - } - } - + hash := assetHashByLocalPath(dest, boxLocalPath, docDirLocalPath) parentBlock := treenode.ParentBlock(n) if ast.NodeInlineHTML != n.Type { parentBlock = n