github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/libnetwork/ipam/store.go (about)

     1  package ipam
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	"github.com/docker/docker/libnetwork/datastore"
     7  	"github.com/docker/docker/libnetwork/types"
     8  	"github.com/sirupsen/logrus"
     9  )
    10  
    11  // Key provides the Key to be used in KV Store
    12  func (aSpace *addrSpace) Key() []string {
    13  	aSpace.Lock()
    14  	defer aSpace.Unlock()
    15  	return []string{aSpace.id}
    16  }
    17  
    18  // KeyPrefix returns the immediate parent key that can be used for tree walk
    19  func (aSpace *addrSpace) KeyPrefix() []string {
    20  	aSpace.Lock()
    21  	defer aSpace.Unlock()
    22  	return []string{dsConfigKey}
    23  }
    24  
    25  // Value marshals the data to be stored in the KV store
    26  func (aSpace *addrSpace) Value() []byte {
    27  	b, err := json.Marshal(aSpace)
    28  	if err != nil {
    29  		logrus.Warnf("Failed to marshal ipam configured pools: %v", err)
    30  		return nil
    31  	}
    32  	return b
    33  }
    34  
    35  // SetValue unmarshalls the data from the KV store.
    36  func (aSpace *addrSpace) SetValue(value []byte) error {
    37  	rc := &addrSpace{subnets: make(map[SubnetKey]*PoolData)}
    38  	if err := json.Unmarshal(value, rc); err != nil {
    39  		return err
    40  	}
    41  	aSpace.subnets = rc.subnets
    42  	return nil
    43  }
    44  
    45  // Index returns the latest DB Index as seen by this object
    46  func (aSpace *addrSpace) Index() uint64 {
    47  	aSpace.Lock()
    48  	defer aSpace.Unlock()
    49  	return aSpace.dbIndex
    50  }
    51  
    52  // SetIndex method allows the datastore to store the latest DB Index into this object
    53  func (aSpace *addrSpace) SetIndex(index uint64) {
    54  	aSpace.Lock()
    55  	aSpace.dbIndex = index
    56  	aSpace.dbExists = true
    57  	aSpace.Unlock()
    58  }
    59  
    60  // Exists method is true if this object has been stored in the DB.
    61  func (aSpace *addrSpace) Exists() bool {
    62  	aSpace.Lock()
    63  	defer aSpace.Unlock()
    64  	return aSpace.dbExists
    65  }
    66  
    67  // Skip provides a way for a KV Object to avoid persisting it in the KV Store
    68  func (aSpace *addrSpace) Skip() bool {
    69  	return false
    70  }
    71  
    72  func (a *Allocator) getStore(as string) datastore.DataStore {
    73  	a.Lock()
    74  	defer a.Unlock()
    75  
    76  	if aSpace, ok := a.addrSpaces[as]; ok {
    77  		return aSpace.ds
    78  	}
    79  
    80  	return nil
    81  }
    82  
    83  func (a *Allocator) getAddressSpaceFromStore(as string) (*addrSpace, error) {
    84  	store := a.getStore(as)
    85  
    86  	// IPAM may not have a valid store. In such cases it is just in-memory state.
    87  	if store == nil {
    88  		return nil, nil
    89  	}
    90  
    91  	pc := &addrSpace{id: dsConfigKey + "/" + as, ds: store, alloc: a}
    92  	if err := store.GetObject(datastore.Key(pc.Key()...), pc); err != nil {
    93  		if err == datastore.ErrKeyNotFound {
    94  			return nil, nil
    95  		}
    96  
    97  		return nil, types.InternalErrorf("could not get pools config from store: %v", err)
    98  	}
    99  
   100  	return pc, nil
   101  }
   102  
   103  func (a *Allocator) writeToStore(aSpace *addrSpace) error {
   104  	store := aSpace.store()
   105  
   106  	// IPAM may not have a valid store. In such cases it is just in-memory state.
   107  	if store == nil {
   108  		return nil
   109  	}
   110  
   111  	err := store.PutObjectAtomic(aSpace)
   112  	if err == datastore.ErrKeyModified {
   113  		return types.RetryErrorf("failed to perform atomic write (%v). retry might fix the error", err)
   114  	}
   115  
   116  	return err
   117  }
   118  
   119  // DataScope method returns the storage scope of the datastore
   120  func (aSpace *addrSpace) DataScope() string {
   121  	aSpace.Lock()
   122  	defer aSpace.Unlock()
   123  
   124  	return aSpace.scope
   125  }