A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
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}