123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- package libnetwork
- import (
- "encoding/json"
- "fmt"
- "sync"
- "github.com/docker/docker/libnetwork/datastore"
- )
- type endpointCnt struct {
- n *Network
- Count uint64
- dbIndex uint64
- dbExists bool
- sync.Mutex
- }
- const epCntKeyPrefix = "endpoint_count"
- func (ec *endpointCnt) Key() []string {
- ec.Lock()
- defer ec.Unlock()
- return []string{epCntKeyPrefix, ec.n.id}
- }
- func (ec *endpointCnt) KeyPrefix() []string {
- ec.Lock()
- defer ec.Unlock()
- return []string{epCntKeyPrefix, ec.n.id}
- }
- func (ec *endpointCnt) Value() []byte {
- ec.Lock()
- defer ec.Unlock()
- b, err := json.Marshal(ec)
- if err != nil {
- return nil
- }
- return b
- }
- func (ec *endpointCnt) SetValue(value []byte) error {
- ec.Lock()
- defer ec.Unlock()
- return json.Unmarshal(value, &ec)
- }
- func (ec *endpointCnt) Index() uint64 {
- ec.Lock()
- defer ec.Unlock()
- return ec.dbIndex
- }
- func (ec *endpointCnt) SetIndex(index uint64) {
- ec.Lock()
- ec.dbIndex = index
- ec.dbExists = true
- ec.Unlock()
- }
- func (ec *endpointCnt) Exists() bool {
- ec.Lock()
- defer ec.Unlock()
- return ec.dbExists
- }
- func (ec *endpointCnt) Skip() bool {
- ec.Lock()
- defer ec.Unlock()
- return !ec.n.persist
- }
- func (ec *endpointCnt) New() datastore.KVObject {
- ec.Lock()
- defer ec.Unlock()
- return &endpointCnt{
- n: ec.n,
- }
- }
- func (ec *endpointCnt) CopyTo(o datastore.KVObject) error {
- ec.Lock()
- defer ec.Unlock()
- dstEc := o.(*endpointCnt)
- dstEc.n = ec.n
- dstEc.Count = ec.Count
- dstEc.dbExists = ec.dbExists
- dstEc.dbIndex = ec.dbIndex
- return nil
- }
- func (ec *endpointCnt) EndpointCnt() uint64 {
- ec.Lock()
- defer ec.Unlock()
- return ec.Count
- }
- func (ec *endpointCnt) updateStore() error {
- store := ec.n.getController().getStore()
- if store == nil {
- return fmt.Errorf("store not found on endpoint count update")
- }
- // make a copy of count and n to avoid being overwritten by store.GetObject
- count := ec.EndpointCnt()
- n := ec.n
- for {
- if err := ec.n.getController().updateToStore(ec); err == nil || err != datastore.ErrKeyModified {
- return err
- }
- if err := store.GetObject(datastore.Key(ec.Key()...), ec); err != nil {
- return fmt.Errorf("could not update the kvobject to latest on endpoint count update: %v", err)
- }
- ec.Lock()
- ec.Count = count
- ec.n = n
- ec.Unlock()
- }
- }
- func (ec *endpointCnt) setCnt(cnt uint64) error {
- ec.Lock()
- ec.Count = cnt
- ec.Unlock()
- return ec.updateStore()
- }
- func (ec *endpointCnt) atomicIncDecEpCnt(inc bool) error {
- store := ec.n.getController().getStore()
- if store == nil {
- return fmt.Errorf("store not found on endpoint count atomic inc/dec")
- }
- tmp := &endpointCnt{n: ec.n}
- if err := store.GetObject(datastore.Key(ec.Key()...), tmp); err != nil {
- return err
- }
- retry:
- ec.Lock()
- if inc {
- ec.Count++
- } else {
- if ec.Count > 0 {
- ec.Count--
- }
- }
- ec.Unlock()
- if err := ec.n.getController().updateToStore(ec); err != nil {
- if err == datastore.ErrKeyModified {
- if err := store.GetObject(datastore.Key(ec.Key()...), ec); err != nil {
- return fmt.Errorf("could not update the kvobject to latest when trying to atomic add endpoint count: %v", err)
- }
- goto retry
- }
- return err
- }
- return nil
- }
- func (ec *endpointCnt) IncEndpointCnt() error {
- return ec.atomicIncDecEpCnt(true)
- }
- func (ec *endpointCnt) DecEndpointCnt() error {
- return ec.atomicIncDecEpCnt(false)
- }
|