github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/state/db_mem.go (about) 1 package state 2 3 import ( 4 "sync" 5 6 "github.com/hashicorp/go-hclog" 7 "github.com/hashicorp/nomad/client/allocrunner/taskrunner/state" 8 dmstate "github.com/hashicorp/nomad/client/devicemanager/state" 9 "github.com/hashicorp/nomad/client/dynamicplugins" 10 driverstate "github.com/hashicorp/nomad/client/pluginmanager/drivermanager/state" 11 "github.com/hashicorp/nomad/client/serviceregistration/checks" 12 "github.com/hashicorp/nomad/nomad/structs" 13 "golang.org/x/exp/maps" 14 ) 15 16 // MemDB implements a StateDB that stores data in memory and should only be 17 // used for testing. All methods are safe for concurrent use. 18 type MemDB struct { 19 // alloc_id -> value 20 allocs map[string]*structs.Allocation 21 22 // alloc_id -> value 23 deployStatus map[string]*structs.AllocDeploymentStatus 24 25 // alloc_id -> value 26 networkStatus map[string]*structs.AllocNetworkStatus 27 28 // alloc_id -> task_name -> value 29 localTaskState map[string]map[string]*state.LocalState 30 taskState map[string]map[string]*structs.TaskState 31 32 // alloc_id -> check_id -> result 33 checks checks.ClientResults 34 35 // devicemanager -> plugin-state 36 devManagerPs *dmstate.PluginState 37 38 // drivermanager -> plugin-state 39 driverManagerPs *driverstate.PluginState 40 41 // dynamicmanager -> registry-state 42 dynamicManagerPs *dynamicplugins.RegistryState 43 44 logger hclog.Logger 45 46 mu sync.RWMutex 47 } 48 49 func NewMemDB(logger hclog.Logger) *MemDB { 50 logger = logger.Named("memdb") 51 return &MemDB{ 52 allocs: make(map[string]*structs.Allocation), 53 deployStatus: make(map[string]*structs.AllocDeploymentStatus), 54 networkStatus: make(map[string]*structs.AllocNetworkStatus), 55 localTaskState: make(map[string]map[string]*state.LocalState), 56 taskState: make(map[string]map[string]*structs.TaskState), 57 checks: make(checks.ClientResults), 58 logger: logger, 59 } 60 } 61 62 func (m *MemDB) Name() string { 63 return "memdb" 64 } 65 66 func (m *MemDB) Upgrade() error { 67 return nil 68 } 69 70 func (m *MemDB) GetAllAllocations() ([]*structs.Allocation, map[string]error, error) { 71 m.mu.RLock() 72 defer m.mu.RUnlock() 73 74 allocs := make([]*structs.Allocation, 0, len(m.allocs)) 75 for _, v := range m.allocs { 76 allocs = append(allocs, v) 77 } 78 79 return allocs, map[string]error{}, nil 80 } 81 82 func (m *MemDB) PutAllocation(alloc *structs.Allocation, _ ...WriteOption) error { 83 m.mu.Lock() 84 defer m.mu.Unlock() 85 m.allocs[alloc.ID] = alloc 86 return nil 87 } 88 89 func (m *MemDB) GetDeploymentStatus(allocID string) (*structs.AllocDeploymentStatus, error) { 90 m.mu.Lock() 91 defer m.mu.Unlock() 92 return m.deployStatus[allocID], nil 93 } 94 95 func (m *MemDB) PutDeploymentStatus(allocID string, ds *structs.AllocDeploymentStatus) error { 96 m.mu.Lock() 97 m.deployStatus[allocID] = ds 98 defer m.mu.Unlock() 99 return nil 100 } 101 102 func (m *MemDB) GetNetworkStatus(allocID string) (*structs.AllocNetworkStatus, error) { 103 m.mu.Lock() 104 defer m.mu.Unlock() 105 return m.networkStatus[allocID], nil 106 } 107 108 func (m *MemDB) PutNetworkStatus(allocID string, ns *structs.AllocNetworkStatus, _ ...WriteOption) error { 109 m.mu.Lock() 110 m.networkStatus[allocID] = ns 111 defer m.mu.Unlock() 112 return nil 113 } 114 115 func (m *MemDB) GetTaskRunnerState(allocID string, taskName string) (*state.LocalState, *structs.TaskState, error) { 116 m.mu.RLock() 117 defer m.mu.RUnlock() 118 119 var ls *state.LocalState 120 var ts *structs.TaskState 121 122 // Local Task State 123 allocLocalTS := m.localTaskState[allocID] 124 if len(allocLocalTS) != 0 { 125 ls = allocLocalTS[taskName] 126 } 127 128 // Task State 129 allocTS := m.taskState[allocID] 130 if len(allocTS) != 0 { 131 ts = allocTS[taskName] 132 } 133 134 return ls, ts, nil 135 } 136 137 func (m *MemDB) PutTaskRunnerLocalState(allocID string, taskName string, val *state.LocalState) error { 138 m.mu.Lock() 139 defer m.mu.Unlock() 140 141 if alts, ok := m.localTaskState[allocID]; ok { 142 alts[taskName] = val.Copy() 143 return nil 144 } 145 146 m.localTaskState[allocID] = map[string]*state.LocalState{ 147 taskName: val.Copy(), 148 } 149 150 return nil 151 } 152 153 func (m *MemDB) PutTaskState(allocID string, taskName string, state *structs.TaskState) error { 154 m.mu.Lock() 155 defer m.mu.Unlock() 156 157 if ats, ok := m.taskState[allocID]; ok { 158 ats[taskName] = state.Copy() 159 return nil 160 } 161 162 m.taskState[allocID] = map[string]*structs.TaskState{ 163 taskName: state.Copy(), 164 } 165 166 return nil 167 } 168 169 func (m *MemDB) DeleteTaskBucket(allocID, taskName string) error { 170 m.mu.Lock() 171 defer m.mu.Unlock() 172 173 if ats, ok := m.taskState[allocID]; ok { 174 delete(ats, taskName) 175 } 176 177 if alts, ok := m.localTaskState[allocID]; ok { 178 delete(alts, taskName) 179 } 180 181 return nil 182 } 183 184 func (m *MemDB) DeleteAllocationBucket(allocID string, _ ...WriteOption) error { 185 m.mu.Lock() 186 defer m.mu.Unlock() 187 188 delete(m.allocs, allocID) 189 delete(m.taskState, allocID) 190 delete(m.localTaskState, allocID) 191 192 return nil 193 } 194 195 func (m *MemDB) PutDevicePluginState(ps *dmstate.PluginState) error { 196 m.mu.Lock() 197 defer m.mu.Unlock() 198 m.devManagerPs = ps 199 return nil 200 } 201 202 // GetDevicePluginState stores the device manager's plugin state or returns an 203 // error. 204 func (m *MemDB) GetDevicePluginState() (*dmstate.PluginState, error) { 205 m.mu.Lock() 206 defer m.mu.Unlock() 207 return m.devManagerPs, nil 208 } 209 210 func (m *MemDB) GetDriverPluginState() (*driverstate.PluginState, error) { 211 m.mu.Lock() 212 defer m.mu.Unlock() 213 return m.driverManagerPs, nil 214 } 215 216 func (m *MemDB) PutDriverPluginState(ps *driverstate.PluginState) error { 217 m.mu.Lock() 218 defer m.mu.Unlock() 219 m.driverManagerPs = ps 220 return nil 221 } 222 223 func (m *MemDB) GetDynamicPluginRegistryState() (*dynamicplugins.RegistryState, error) { 224 m.mu.Lock() 225 defer m.mu.Unlock() 226 return m.dynamicManagerPs, nil 227 } 228 229 func (m *MemDB) PutDynamicPluginRegistryState(ps *dynamicplugins.RegistryState) error { 230 m.mu.Lock() 231 defer m.mu.Unlock() 232 m.dynamicManagerPs = ps 233 return nil 234 } 235 236 func (m *MemDB) PutCheckResult(allocID string, qr *structs.CheckQueryResult) error { 237 m.mu.Lock() 238 defer m.mu.Unlock() 239 240 if _, exists := m.checks[allocID]; !exists { 241 m.checks[allocID] = make(checks.AllocationResults) 242 } 243 244 m.checks[allocID][qr.ID] = qr 245 return nil 246 } 247 248 func (m *MemDB) GetCheckResults() (checks.ClientResults, error) { 249 m.mu.Lock() 250 defer m.mu.Unlock() 251 return maps.Clone(m.checks), nil 252 } 253 254 func (m *MemDB) DeleteCheckResults(allocID string, checkIDs []structs.CheckID) error { 255 m.mu.Lock() 256 defer m.mu.Unlock() 257 for _, id := range checkIDs { 258 delete(m.checks[allocID], id) 259 } 260 return nil 261 } 262 263 func (m *MemDB) PurgeCheckResults(allocID string) error { 264 m.mu.Lock() 265 defer m.mu.Unlock() 266 delete(m.checks, allocID) 267 return nil 268 } 269 270 func (m *MemDB) Close() error { 271 m.mu.Lock() 272 defer m.mu.Unlock() 273 274 // Set everything to nil to blow up on further use 275 m.allocs = nil 276 m.taskState = nil 277 m.localTaskState = nil 278 279 return nil 280 }