Left: | ||
Right: |
OLD | NEW |
---|---|
1 // Copyright 2012, 2013 Canonical Ltd. | 1 // Copyright 2012, 2013 Canonical Ltd. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package state | 4 package state |
5 | 5 |
6 import ( | 6 import ( |
7 "errors" | 7 "errors" |
8 | 8 |
9 "labix.org/v2/mgo/txn" | 9 "labix.org/v2/mgo/txn" |
10 | 10 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 C: st.minUnits.Name, | 115 C: st.minUnits.Name, |
116 Id: serviceName, | 116 Id: serviceName, |
117 Remove: true, | 117 Remove: true, |
118 } | 118 } |
119 } | 119 } |
120 | 120 |
121 // MinUnits returns the minimum units count for the service. | 121 // MinUnits returns the minimum units count for the service. |
122 func (s *Service) MinUnits() int { | 122 func (s *Service) MinUnits() int { |
123 return s.doc.MinUnits | 123 return s.doc.MinUnits |
124 } | 124 } |
125 | |
126 // EnsureMinUnits adds new units if the service's MinUnits value is greater | |
127 // than the number of alive units. | |
128 func (s *Service) EnsureMinUnits() (err error) { | |
129 defer utils.ErrorContextf(&err, | |
dimitern
2013/07/11 20:05:12
please, either put the whole statement on one line
frankban
2013/07/12 10:07:22
I'd be happier to do this after understanding the
dimitern
2013/07/15 11:28:24
Sorry, probably personal preference and also makes
| |
130 "cannot ensure minimum units for service %q", s) | |
131 service := &Service{st: s.st, doc: s.doc} | |
132 for { | |
133 // Ensure the service is alive. | |
134 if service.doc.Life != Alive { | |
dimitern
2013/07/11 20:05:12
this should be an transaction assert op, rather th
frankban
2013/07/12 10:07:22
The assertion is already included in the transacti
fwereade
2013/07/15 11:02:53
+1 to frankban. It's annoying that we have to defi
dimitern
2013/07/15 11:28:24
OK, good point objection withdrawn.
| |
135 return errors.New("service is no longer alive") | |
136 } | |
137 // Exit without errors if the MinUnits for the service is not se t. | |
138 if service.doc.MinUnits == 0 { | |
dimitern
2013/07/11 20:05:12
ditto
frankban
2013/07/12 10:07:22
See the comment above.
| |
139 return nil | |
140 } | |
141 // Retrieve the number of alive units for the service. | |
142 aliveUnits, err := aliveUnitsCount(service) | |
dimitern
2013/07/11 20:05:12
ditto
frankban
2013/07/12 10:07:22
See the comment above.
| |
143 if err != nil { | |
144 return err | |
145 } | |
146 // Calculate the number of required units to be added. | |
147 missing := service.doc.MinUnits - aliveUnits | |
dimitern
2013/07/11 20:05:12
ditto
frankban
2013/07/12 10:07:22
See the comment above.
| |
148 if missing <= 0 { | |
149 return nil | |
150 } | |
151 name, ops, err := ensureMinUnitsOps(service) | |
152 if err != nil { | |
153 return err | |
154 } | |
155 // Add missing unit. | |
156 switch err := s.st.runTransaction(ops); err { | |
157 case nil: | |
158 // Assign the new unit. | |
159 unit, err := service.Unit(name) | |
160 if err != nil { | |
161 return err | |
162 } | |
163 if err := service.st.AssignUnit(unit, AssignNew); err != nil { | |
164 return err | |
165 } | |
166 // No need to proceed and refresh the service if this wa s the | |
167 // last/only missing unit. | |
168 if missing == 1 { | |
169 return nil | |
170 } | |
171 case txn.ErrAborted: | |
172 default: | |
173 return err | |
dimitern
2013/07/11 20:05:12
I don't think this is right - the transaction can
frankban
2013/07/12 10:07:22
If I read this lines correctly, this is exactly wh
fwereade
2013/07/15 11:02:53
frankban's right, but I agree that a casual readin
dimitern
2013/07/15 11:28:24
Sorry, I read it incorrectly (that's why you shoul
| |
174 } | |
175 if err := service.Refresh(); err != nil { | |
176 return err | |
177 } | |
178 } | |
179 panic("unreachable") | |
180 } | |
181 | |
182 // aliveUnitsCount returns the number a alive units for the service. | |
183 func aliveUnitsCount(service *Service) (int, error) { | |
184 query := D{{"service", service.doc.Name}, {"life", Alive}} | |
dimitern
2013/07/11 20:05:12
this needs to be an assert op, take a look at serv
frankban
2013/07/12 10:07:22
Could you please be more specific? Why do I need a
fwereade
2013/07/15 11:02:53
I don't think you do, but I'm interested to hear d
dimitern
2013/07/15 11:28:24
See the above comment and just ignore me, sorry :/
| |
185 return service.st.units.Find(query).Count() | |
186 } | |
187 | |
188 // ensureMinUnitsOps returns the operations required to add a unit for the | |
189 // service in MongoDB and the name for the new unit. The resulting transaction | |
190 // will be aborted if the service document changes when running the operations. | |
191 func ensureMinUnitsOps(service *Service) (string, []txn.Op, error) { | |
192 asserts := D{{"txn-revno", service.doc.TxnRevno}} | |
193 return service.addUnitOps("", asserts) | |
194 } | |
OLD | NEW |