github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/libnetwork/endpoint_cnt.go (about) 1 package libnetwork 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "sync" 7 8 "github.com/docker/libnetwork/datastore" 9 ) 10 11 type endpointCnt struct { 12 n *network 13 Count uint64 14 dbIndex uint64 15 dbExists bool 16 sync.Mutex 17 } 18 19 const epCntKeyPrefix = "endpoint_count" 20 21 func (ec *endpointCnt) Key() []string { 22 ec.Lock() 23 defer ec.Unlock() 24 25 return []string{epCntKeyPrefix, ec.n.id} 26 } 27 28 func (ec *endpointCnt) KeyPrefix() []string { 29 ec.Lock() 30 defer ec.Unlock() 31 32 return []string{epCntKeyPrefix, ec.n.id} 33 } 34 35 func (ec *endpointCnt) Value() []byte { 36 ec.Lock() 37 defer ec.Unlock() 38 39 b, err := json.Marshal(ec) 40 if err != nil { 41 return nil 42 } 43 return b 44 } 45 46 func (ec *endpointCnt) SetValue(value []byte) error { 47 ec.Lock() 48 defer ec.Unlock() 49 50 return json.Unmarshal(value, &ec) 51 } 52 53 func (ec *endpointCnt) Index() uint64 { 54 ec.Lock() 55 defer ec.Unlock() 56 return ec.dbIndex 57 } 58 59 func (ec *endpointCnt) SetIndex(index uint64) { 60 ec.Lock() 61 ec.dbIndex = index 62 ec.dbExists = true 63 ec.Unlock() 64 } 65 66 func (ec *endpointCnt) Exists() bool { 67 ec.Lock() 68 defer ec.Unlock() 69 return ec.dbExists 70 } 71 72 func (ec *endpointCnt) Skip() bool { 73 ec.Lock() 74 defer ec.Unlock() 75 return !ec.n.persist 76 } 77 78 func (ec *endpointCnt) New() datastore.KVObject { 79 ec.Lock() 80 defer ec.Unlock() 81 82 return &endpointCnt{ 83 n: ec.n, 84 } 85 } 86 87 func (ec *endpointCnt) CopyTo(o datastore.KVObject) error { 88 ec.Lock() 89 defer ec.Unlock() 90 91 dstEc := o.(*endpointCnt) 92 dstEc.n = ec.n 93 dstEc.Count = ec.Count 94 dstEc.dbExists = ec.dbExists 95 dstEc.dbIndex = ec.dbIndex 96 97 return nil 98 } 99 100 func (ec *endpointCnt) DataScope() string { 101 return ec.n.DataScope() 102 } 103 104 func (ec *endpointCnt) EndpointCnt() uint64 { 105 ec.Lock() 106 defer ec.Unlock() 107 108 return ec.Count 109 } 110 111 func (ec *endpointCnt) updateStore() error { 112 store := ec.n.getController().getStore(ec.DataScope()) 113 if store == nil { 114 return fmt.Errorf("store not found for scope %s on endpoint count update", ec.DataScope()) 115 } 116 // make a copy of count and n to avoid being overwritten by store.GetObject 117 count := ec.EndpointCnt() 118 n := ec.n 119 for { 120 if err := ec.n.getController().updateToStore(ec); err == nil || err != datastore.ErrKeyModified { 121 return err 122 } 123 if err := store.GetObject(datastore.Key(ec.Key()...), ec); err != nil { 124 return fmt.Errorf("could not update the kvobject to latest on endpoint count update: %v", err) 125 } 126 ec.Lock() 127 ec.Count = count 128 ec.n = n 129 ec.Unlock() 130 } 131 } 132 133 func (ec *endpointCnt) setCnt(cnt uint64) error { 134 ec.Lock() 135 ec.Count = cnt 136 ec.Unlock() 137 return ec.updateStore() 138 } 139 140 func (ec *endpointCnt) atomicIncDecEpCnt(inc bool) error { 141 store := ec.n.getController().getStore(ec.DataScope()) 142 if store == nil { 143 return fmt.Errorf("store not found for scope %s", ec.DataScope()) 144 } 145 146 tmp := &endpointCnt{n: ec.n} 147 if err := store.GetObject(datastore.Key(ec.Key()...), tmp); err != nil { 148 return err 149 } 150 retry: 151 ec.Lock() 152 if inc { 153 ec.Count++ 154 } else { 155 if ec.Count > 0 { 156 ec.Count-- 157 } 158 } 159 ec.Unlock() 160 161 if err := ec.n.getController().updateToStore(ec); err != nil { 162 if err == datastore.ErrKeyModified { 163 if err := store.GetObject(datastore.Key(ec.Key()...), ec); err != nil { 164 return fmt.Errorf("could not update the kvobject to latest when trying to atomic add endpoint count: %v", err) 165 } 166 167 goto retry 168 } 169 170 return err 171 } 172 173 return nil 174 } 175 176 func (ec *endpointCnt) IncEndpointCnt() error { 177 return ec.atomicIncDecEpCnt(true) 178 } 179 180 func (ec *endpointCnt) DecEndpointCnt() error { 181 return ec.atomicIncDecEpCnt(false) 182 }