github.com/rawahars/moby@v24.0.4+incompatible/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) 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()
   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()
   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  }