A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 154 lines 3.3 kB view raw
1// SiYuan - Refactor your thinking 2// Copyright (c) 2020-present, b3log.org 3// 4// This program is free software: you can redistribute it and/or modify 5// it under the terms of the GNU Affero General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// This program is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU Affero General Public License for more details. 13// 14// You should have received a copy of the GNU Affero General Public License 15// along with this program. If not, see <https://www.gnu.org/licenses/>. 16 17package cache 18 19import ( 20 "io/fs" 21 "path/filepath" 22 "strings" 23 "sync" 24 "time" 25 26 "github.com/siyuan-note/filelock" 27 "github.com/siyuan-note/logging" 28 "github.com/siyuan-note/siyuan/kernel/util" 29) 30 31type AssetHash struct { 32 Hash string `json:"hash"` 33 Path string `json:"path"` 34} 35 36var ( 37 assetHashCache = map[string]*AssetHash{} 38 assetHashLock = sync.Mutex{} 39) 40 41func RemoveAssetHash(hash string) { 42 assetHashLock.Lock() 43 defer assetHashLock.Unlock() 44 45 delete(assetHashCache, hash) 46} 47 48func SetAssetHash(hash, path string) { 49 assetHashLock.Lock() 50 defer assetHashLock.Unlock() 51 52 assetHashCache[hash] = &AssetHash{ 53 Hash: hash, 54 Path: path, 55 } 56} 57 58func GetAssetHash(hash string) *AssetHash { 59 assetHashLock.Lock() 60 defer assetHashLock.Unlock() 61 62 for _, a := range assetHashCache { 63 if a.Hash == hash { 64 if filelock.IsExist(filepath.Join(util.DataDir, a.Path)) { 65 return a 66 } 67 68 delete(assetHashCache, hash) 69 return nil 70 } 71 } 72 return nil 73} 74 75type Asset struct { 76 HName string `json:"hName"` 77 Path string `json:"path"` 78 Updated int64 `json:"updated"` 79} 80 81var ( 82 assetsCache = map[string]*Asset{} 83 assetsLock = sync.Mutex{} 84) 85 86func GetAssets() (ret map[string]*Asset) { 87 assetsLock.Lock() 88 defer assetsLock.Unlock() 89 90 ret = map[string]*Asset{} 91 for k, v := range assetsCache { 92 ret[k] = v 93 } 94 return 95} 96 97func RemoveAsset(path string) { 98 assetsLock.Lock() 99 defer assetsLock.Unlock() 100 101 delete(assetsCache, path) 102} 103 104func ExistAsset(path string) (ret bool) { 105 assetsLock.Lock() 106 defer assetsLock.Unlock() 107 108 _, ret = assetsCache[path] 109 return 110} 111 112func LoadAssets() { 113 defer logging.Recover() 114 115 start := time.Now() 116 assetsLock.Lock() 117 defer assetsLock.Unlock() 118 119 assetsCache = map[string]*Asset{} 120 assets := util.GetDataAssetsAbsPath() 121 filelock.Walk(assets, func(path string, d fs.DirEntry, err error) error { 122 if nil != err || nil == d { 123 return err 124 } 125 if d.IsDir() { 126 if strings.HasPrefix(d.Name(), ".") { 127 return filepath.SkipDir 128 } 129 return nil 130 } 131 if strings.HasSuffix(d.Name(), ".sya") || strings.HasPrefix(d.Name(), ".") || filelock.IsHidden(path) { 132 return nil 133 } 134 135 info, err := d.Info() 136 if nil != err { 137 logging.LogErrorf("load assets failed: %s", err) 138 return nil 139 } 140 141 hName := util.RemoveID(d.Name()) 142 path = "assets" + filepath.ToSlash(strings.TrimPrefix(path, assets)) 143 assetsCache[path] = &Asset{ 144 HName: hName, 145 Path: path, 146 Updated: info.ModTime().Unix(), 147 } 148 return nil 149 }) 150 elapsed := time.Since(start) 151 if 2000 < elapsed.Milliseconds() { 152 logging.LogInfof("loaded assets [%.2fs]", elapsed.Seconds()) 153 } 154}