github.com/tonistiigi/docker@v0.10.1-0.20240229224939-974013b0dc6a/libnetwork/endpoint_cnt.go (about) 1 package libnetwork 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "sync" 7 8 "github.com/docker/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) EndpointCnt() uint64 { 101 ec.Lock() 102 defer ec.Unlock() 103 104 return ec.Count 105 } 106 107 func (ec *endpointCnt) updateStore() error { 108 store := ec.n.getController().getStore() 109 if store == nil { 110 return fmt.Errorf("store not found on endpoint count update") 111 } 112 // make a copy of count and n to avoid being overwritten by store.GetObject 113 count := ec.EndpointCnt() 114 n := ec.n 115 for { 116 if err := ec.n.getController().updateToStore(ec); err == nil || err != datastore.ErrKeyModified { 117 return err 118 } 119 if err := store.GetObject(ec); err != nil { 120 return fmt.Errorf("could not update the kvobject to latest on endpoint count update: %v", err) 121 } 122 ec.Lock() 123 ec.Count = count 124 ec.n = n 125 ec.Unlock() 126 } 127 } 128 129 func (ec *endpointCnt) setCnt(cnt uint64) error { 130 ec.Lock() 131 ec.Count = cnt 132 ec.Unlock() 133 return ec.updateStore() 134 } 135 136 func (ec *endpointCnt) atomicIncDecEpCnt(inc bool) error { 137 store := ec.n.getController().getStore() 138 if store == nil { 139 return fmt.Errorf("store not found on endpoint count atomic inc/dec") 140 } 141 142 tmp := &endpointCnt{n: ec.n} 143 if err := store.GetObject(tmp); err != nil { 144 return err 145 } 146 retry: 147 ec.Lock() 148 if inc { 149 ec.Count++ 150 } else { 151 if ec.Count > 0 { 152 ec.Count-- 153 } 154 } 155 ec.Unlock() 156 157 if err := ec.n.getController().updateToStore(ec); err != nil { 158 if err == datastore.ErrKeyModified { 159 if err := store.GetObject(ec); err != nil { 160 return fmt.Errorf("could not update the kvobject to latest when trying to atomic add endpoint count: %v", err) 161 } 162 163 goto retry 164 } 165 166 return err 167 } 168 169 return nil 170 } 171 172 func (ec *endpointCnt) IncEndpointCnt() error { 173 return ec.atomicIncDecEpCnt(true) 174 } 175 176 func (ec *endpointCnt) DecEndpointCnt() error { 177 return ec.atomicIncDecEpCnt(false) 178 }