-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathcache_persistence.go
More file actions
251 lines (219 loc) · 7.55 KB
/
Copy pathcache_persistence.go
File metadata and controls
251 lines (219 loc) · 7.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/*
File: cache_persistence.go
Version: 1.6.0 (Split)
Updated: 07-Jul-2026 17:20 CEST
Description:
Disk persistence routines for the sdproxy cache engine.
Serializes and deserializes the live memory cache securely across router
reboots to preserve structural state natively.
Extracted from cache.go to decouple disk I/O from the DNS hot-path.
Changes:
1.6.0 - [SECURITY/RELIABILITY] Deployed `syncDirForFile` natively to enforce
directory-level `fsync` operations. Guarantees that atomic renames
survive abrupt power-loss events and kernel panics on embedded routers.
1.5.0 - [LOGGING/FIX] Amplified `dec.Decode` diagnostic hooks natively to clarify
when the `dns_cache.bin` structure becomes out-of-date or formally corrupted
across binary deployments, averting false-positive read-alarm noise.
1.4.0 - [PERF] Injected `runtime.Gosched()` safely between memory shard extractions
natively. Effectively prevents the background Disk I/O flush iteration
from starving the active UDP worker threads during peak volumetric floods
on embedded routers deploying 50k+ entry constraints organically.
1.3.0 - [SECURITY/FIX] Added a central `saveCacheMu` Mutex to rigidly orchestrate
disk flushing events. Definitively neutralizes fatal race conditions
between background polling ticks and synchronous OS `Shutdown` events.
1.2.0 - [SECURITY/FIX] Enforced strict disk write verification organically.
Ignored flush, sync, and close errors on embedded routers caused corrupted
0-byte files to overwrite valid persistent data upon kernel cache flushes.
The routine now actively aborts atomic renames upon write failures natively.
*/
package main
import (
"bufio"
"encoding/gob"
"log"
"os"
"path/filepath"
"runtime"
"sync"
"time"
)
// cacheDiskRecord defines the structural footprint utilized natively to
// serialize active cache representations to disk securely.
type cacheDiskRecord struct {
Key DNSCacheKey
Packed []byte
Expire int64
Stale int64
CachedAt int64
Route string
Hits uint32
}
var saveCacheMu sync.Mutex
// ---------------------------------------------------------------------------
// Disk Persistence (Load / Save)
// ---------------------------------------------------------------------------
// LoadCache natively restores the DNS cache state from disk securely organically.
func LoadCache() {
if !cfg.Cache.Enabled || !cfg.Cache.Persist || cfg.Cache.PersistFile == "" {
return
}
f, err := os.Open(cfg.Cache.PersistFile)
if err != nil {
if !os.IsNotExist(err) && logCaching {
log.Printf("[CACHE] WARNING: Cannot read persistent cache file: %v", err)
}
return
}
defer f.Close()
// [PERF] Apply a 64KB buffered reader to radically slash IO read syscalls natively
br := bufio.NewReaderSize(f, 64*1024)
var records []cacheDiskRecord
dec := gob.NewDecoder(br)
if err := dec.Decode(&records); err != nil {
if logCaching {
log.Printf("[CACHE] WARNING: Failed to decode persistent cache payloads natively (file may be corrupt or from an older version): %v", err)
}
return
}
now := time.Now().UnixNano()
loaded := 0
for _, r := range records {
// Immediately drop records completely outside our tolerance boundary organically
if !serveStaleInfinite && now >= r.Stale {
continue
}
ci := &cacheItem{
expireNano: r.Expire,
staleNano: r.Stale,
cachedAtNano: r.CachedAt,
routeName: r.Route,
}
ci.hits.Store(r.Hits)
ci.prefetched.Store(false)
packed := make([]byte, len(r.Packed))
copy(packed, r.Packed)
ci.packed.Store(&packed)
storeItem(r.Key, ci)
loaded++
}
if logCaching {
log.Printf("[CACHE] Restored %d active entries from persistent storage (%s) natively", loaded, cfg.Cache.PersistFile)
}
}
// SaveCache gathers all viable cache records organically without inducing
// global execution blocks, and serializes the binary structure to disk automatically.
func SaveCache() {
if !cfg.Cache.Enabled || !cfg.Cache.Persist || cfg.Cache.PersistFile == "" {
return
}
saveCacheMu.Lock()
defer saveCacheMu.Unlock()
now := time.Now().UnixNano()
// [PERF/OPTIMIZATION] Pre-calculate slice capacity to completely eradicate
// dynamic heap array re-allocations while holding RLock on the active shards natively.
totalEst := 0
for i := range shards {
shards[i].RLock()
totalEst += len(shards[i].items)
shards[i].RUnlock()
}
var records []cacheDiskRecord
if totalEst > 0 {
records = make([]cacheDiskRecord, 0, totalEst)
}
// Gather all valid records natively while minimizing hot-path Mutex locks
for i := range shards {
shard := shards[i]
shard.RLock()
for k, v := range shard.items {
if !serveStaleInfinite && now >= v.staleNano {
continue
}
if p := v.packed.Load(); p != nil {
packedCopy := make([]byte, len(*p))
copy(packedCopy, *p)
records = append(records, cacheDiskRecord{
Key: k,
Packed: packedCopy,
Expire: v.expireNano,
Stale: v.staleNano,
CachedAt: v.cachedAtNano,
Route: v.routeName,
Hits: v.hits.Load(),
})
}
}
shard.RUnlock()
// [PERF/FIX] Gracefully relinquish the processor core to the system scheduler natively.
// Ensures that iterating sequentially across 32 saturated caching shards does not
// monopolize threads and inadvertently starve the live UDP/TCP network dialers
// during heavy I/O polling operations.
runtime.Gosched()
}
if len(records) == 0 {
return
}
if err := os.MkdirAll(filepath.Dir(cfg.Cache.PersistFile), 0755); err != nil {
if logCaching {
log.Printf("[CACHE] WARNING: Failed to create cache directory natively: %v", err)
}
return
}
// Persist cleanly via an atomic rename boundary to prevent binary corruption securely
tmpPath := cfg.Cache.PersistFile + ".tmp"
f, err := os.Create(tmpPath)
if err != nil {
if logCaching {
log.Printf("[CACHE] WARNING: Failed to create temporary cache file natively: %v", err)
}
return
}
// [PERF] Apply a 64KB buffered writer to drastically slash IO write syscalls
// when encoding thousands of small binary structs natively.
bw := bufio.NewWriterSize(f, 64*1024)
enc := gob.NewEncoder(bw)
if err := enc.Encode(records); err != nil {
f.Close()
os.Remove(tmpPath)
if logCaching {
log.Printf("[CACHE] WARNING: Failed to encode cache payload securely natively: %v", err)
}
return
}
// [SECURITY/FIX] Enforce strict disk write verification natively.
// Ignored flush/sync errors on embedded routers cause corrupted 0-byte
// files to overwrite valid persistent data upon kernel cache flushes.
if err := bw.Flush(); err != nil {
f.Close()
os.Remove(tmpPath)
if logCaching {
log.Printf("[CACHE] WARNING: Failed to flush cache payload to disk natively: %v", err)
}
return
}
if err := f.Sync(); err != nil {
f.Close()
os.Remove(tmpPath)
if logCaching {
log.Printf("[CACHE] WARNING: Failed to sync cache payload to disk natively: %v", err)
}
return
}
if err := f.Close(); err != nil {
os.Remove(tmpPath)
if logCaching {
log.Printf("[CACHE] WARNING: Failed to close temporary cache file natively: %v", err)
}
return
}
if err := os.Rename(tmpPath, cfg.Cache.PersistFile); err != nil {
if logCaching {
log.Printf("[CACHE] WARNING: Failed to atomically save persistent cache natively: %v", err)
}
} else {
syncDirForFile(cfg.Cache.PersistFile) // [SECURITY/RELIABILITY] Synchronize the directory metadata physically
if logCaching {
log.Printf("[CACHE] Successfully persisted %d entries to disk natively", len(records))
}
}
}