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  }