@@ -3,8 +3,6 @@ package main
33import (
44 "errors"
55 "fmt"
6- "sync"
7- "sync/atomic"
86 "time"
97
108 "codeberg.org/miekg/dns"
@@ -29,115 +27,6 @@ type ReloadablePlugin interface {
2927 SetConfigWatcher (watcher * ConfigWatcher ) // Set the config watcher
3028}
3129
32- // ReloadSafeguard provides atomic operations to ensure configuration reloading is safe
33- type ReloadSafeguard struct {
34- isReloading int32 // Flag indicating if a reload is in progress (0=false, 1=true)
35- reloadMutex sync.Mutex // Mutex for reload operations
36- activeConfigMu sync.RWMutex // Read-write mutex for accessing active configuration
37- activeTimestamp time.Time // Timestamp when the active config was loaded
38- }
39-
40- // NewReloadSafeguard creates a new reload safeguard
41- func NewReloadSafeguard () * ReloadSafeguard {
42- return & ReloadSafeguard {
43- activeTimestamp : time .Now (),
44- }
45- }
46-
47- // StartReload attempts to start a reload operation
48- // Returns true if reload can proceed, false if another reload is in progress
49- func (rs * ReloadSafeguard ) StartReload () bool {
50- // Try to set isReloading atomically, only succeeds if it was previously false
51- if atomic .CompareAndSwapInt32 (& rs .isReloading , 0 , 1 ) {
52- rs .reloadMutex .Lock ()
53- return true
54- }
55- return false
56- }
57-
58- // FinishReload completes a reload operation, releasing locks
59- func (rs * ReloadSafeguard ) FinishReload () {
60- atomic .StoreInt32 (& rs .isReloading , 0 )
61- rs .reloadMutex .Unlock ()
62- }
63-
64- // AcquireConfigRead acquires a read lock on the active configuration
65- func (rs * ReloadSafeguard ) AcquireConfigRead () {
66- rs .activeConfigMu .RLock ()
67- }
68-
69- // ReleaseConfigRead releases a read lock on the active configuration
70- func (rs * ReloadSafeguard ) ReleaseConfigRead () {
71- rs .activeConfigMu .RUnlock ()
72- }
73-
74- // AcquireConfigWrite acquires a write lock on the active configuration
75- func (rs * ReloadSafeguard ) AcquireConfigWrite () {
76- rs .activeConfigMu .Lock ()
77- }
78-
79- // ReleaseConfigWrite releases a write lock on the active configuration
80- func (rs * ReloadSafeguard ) ReleaseConfigWrite () {
81- rs .activeConfigMu .Unlock ()
82- rs .activeTimestamp = time .Now ()
83- }
84-
85- // SafeReload handles the entire reload process with proper locking
86- // The provided function is executed while holding the write lock
87- func (rs * ReloadSafeguard ) SafeReload (reloadFunc func () error ) error {
88- if ! rs .StartReload () {
89- return errors .New ("another reload operation is already in progress" )
90- }
91- defer rs .FinishReload ()
92-
93- // Acquire write lock for configuration update
94- rs .AcquireConfigWrite ()
95- defer rs .ReleaseConfigWrite ()
96-
97- // Execute the provided reload function
98- return reloadFunc ()
99- }
100-
101- // RegisterPluginForReload adds a plugin to the config watcher for automatic reloading
102- func RegisterPluginForReload (plugin ReloadablePlugin , watcher * ConfigWatcher ) error {
103- configPath := plugin .GetConfigPath ()
104- if configPath == "" {
105- return errors .New ("empty configuration path for plugin: " + plugin .Name ())
106- }
107-
108- // Create a reload function closure that handles the complete reload process
109- reloadFunc := func () error {
110- dlog .Noticef ("Reloading configuration for plugin [%s]" , plugin .Name ())
111-
112- // Prepare stage: Load and validate new configuration without applying it
113- if err := plugin .PrepareReload (); err != nil {
114- dlog .Errorf ("Failed to prepare reload for plugin [%s]: %v" , plugin .Name (), err )
115- plugin .CancelReload () // Ensure cleanup of any temporary resources
116- return err
117- }
118-
119- // Apply stage: Switch to new configuration
120- if err := plugin .ApplyReload (); err != nil {
121- dlog .Errorf ("Failed to apply reload for plugin [%s]: %v" , plugin .Name (), err )
122- plugin .CancelReload () // Ensure cleanup of any temporary resources
123- return err
124- }
125-
126- dlog .Noticef ("Successfully reloaded plugin [%s]" , plugin .Name ())
127- return nil
128- }
129-
130- // Add the plugin's config file to the watcher
131- if err := watcher .AddFile (configPath , reloadFunc ); err != nil {
132- return err
133- }
134-
135- // Set the config watcher in the plugin
136- plugin .SetConfigWatcher (watcher )
137-
138- return nil
139- }
140-
14130// SafeReadTextFile is similar to ReadTextFile but with additional safeguards
14231// to prevent reading partially written files
14332func SafeReadTextFile (filePath string ) (string , error ) {
0 commit comments