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 }