Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / docker / libnetwork / endpoint_cnt.go
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 retry:
142         ec.Lock()
143         if inc {
144                 ec.Count++
145         } else {
146                 if ec.Count > 0 {
147                         ec.Count--
148                 }
149         }
150         ec.Unlock()
151
152         store := ec.n.getController().getStore(ec.DataScope())
153         if store == nil {
154                 return fmt.Errorf("store not found for scope %s", ec.DataScope())
155         }
156
157         if err := ec.n.getController().updateToStore(ec); err != nil {
158                 if err == datastore.ErrKeyModified {
159                         if err := store.GetObject(datastore.Key(ec.Key()...), 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 }