Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 package state | 1 package state |
2 | 2 |
3 import ( | 3 import ( |
4 "errors" | 4 "errors" |
5 "fmt" | 5 "fmt" |
6 "labix.org/v2/mgo" | 6 "labix.org/v2/mgo" |
7 "labix.org/v2/mgo/bson" | 7 "labix.org/v2/mgo/bson" |
8 "labix.org/v2/mgo/txn" | 8 "labix.org/v2/mgo/txn" |
9 "launchpad.net/juju-core/charm" | 9 "launchpad.net/juju-core/charm" |
10 "launchpad.net/juju-core/trivial" | 10 "launchpad.net/juju-core/trivial" |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
250 } | 250 } |
251 | 251 |
252 // ErrCannotEnterScope indicates that a relation unit failed to enter its scope | 252 // ErrCannotEnterScope indicates that a relation unit failed to enter its scope |
253 // due to either the unit or the relation not being Alive. | 253 // due to either the unit or the relation not being Alive. |
254 var ErrCannotEnterScope = errors.New("cannot enter scope: unit or relation is no t alive") | 254 var ErrCannotEnterScope = errors.New("cannot enter scope: unit or relation is no t alive") |
255 | 255 |
256 // EnterScope ensures that the unit has entered its scope in the relation and | 256 // EnterScope ensures that the unit has entered its scope in the relation and |
257 // that its relation settings contain its private address. When the unit has | 257 // that its relation settings contain its private address. When the unit has |
258 // already entered its relation scope, EnterScope will report success but make | 258 // already entered its relation scope, EnterScope will report success but make |
259 // no changes to state; otherwise, it is an error for either the relation or | 259 // no changes to state; otherwise, it is an error for either the relation or |
260 // the unit not to be Alive. Once a unit has entered a scope, in stays in scope | 260 // the unit not to be Alive. Once a unit has entered a scope, it stays in scope |
rog
2012/12/07 10:06:21
s/in stays/it stays/
fwereade
2012/12/07 15:06:11
Done.
| |
261 // without further intervention; the relation will not be able to become Dead | 261 // without further intervention; the relation will not be able to become Dead |
262 // until all units have departed its scopes. | 262 // until all units have departed its scopes. |
263 func (ru *RelationUnit) EnterScope() error { | 263 func (ru *RelationUnit) EnterScope() error { |
264 key, err := ru.key(ru.unit.Name()) | 264 key, err := ru.key(ru.unit.Name()) |
265 if err != nil { | 265 if err != nil { |
266 return err | 266 return err |
267 } | 267 } |
268 desc := fmt.Sprintf("unit %q in relation %q", ru.unit, ru.relation) | 268 desc := fmt.Sprintf("unit %q in relation %q", ru.unit, ru.relation) |
269 if count, err := ru.st.relationScopes.FindId(key).Count(); err != nil { | 269 if count, err := ru.st.relationScopes.FindId(key).Count(); err != nil { |
270 return fmt.Errorf("cannot examine scope for %s: %v", desc, err) | 270 return fmt.Errorf("cannot examine scope for %s: %v", desc, err) |
(...skipping 12 matching lines...) Expand all Loading... | |
283 Update: D{{"$inc", D{{"unitcount", 1}}}}, | 283 Update: D{{"$inc", D{{"unitcount", 1}}}}, |
284 }, { | 284 }, { |
285 C: ru.st.units.Name, | 285 C: ru.st.units.Name, |
286 Id: ru.unit.Name(), | 286 Id: ru.unit.Name(), |
287 Assert: isAlive, | 287 Assert: isAlive, |
288 }} | 288 }} |
289 if _, err := readSettings(ru.st, key); IsNotFound(err) { | 289 if _, err := readSettings(ru.st, key); IsNotFound(err) { |
290 // If settings do not already exist, create them. | 290 // If settings do not already exist, create them. |
291 address, err := ru.unit.PrivateAddress() | 291 address, err := ru.unit.PrivateAddress() |
292 if err != nil { | 292 if err != nil { |
293 return fmt.Errorf("cannot initialize state for %s: %v", desc, err) | 293 return fmt.Errorf("cannot initialize state for %s: %v", desc, err) |
rog
2012/12/07 10:06:21
how is getting the private address "initializing s
fwereade
2012/12/07 10:30:04
It's not. The error is stating that it's impossibl
rog
2012/12/07 10:40:53
ah yes, i'd read the txn.DocMissing as pertaining
| |
294 } | 294 } |
295 ops = append([]txn.Op{{ | 295 ops = append([]txn.Op{{ |
296 C: ru.st.settings.Name, | 296 C: ru.st.settings.Name, |
297 Id: key, | 297 Id: key, |
298 Assert: txn.DocMissing, | 298 Assert: txn.DocMissing, |
299 Insert: map[string]interface{}{"private-address": addres s}, | 299 Insert: map[string]interface{}{"private-address": addres s}, |
300 }}, ops...) | 300 }}, ops...) |
301 } else if err != nil { | 301 } else if err != nil { |
302 return fmt.Errorf("cannot check settings for %s: %v", desc, err) | 302 return fmt.Errorf("cannot check settings for %s: %v", desc, err) |
303 } | 303 } |
304 » if err := ru.st.runner.Run(ops, "", nil); err == txn.ErrAborted { | 304 » if err := ru.st.runner.Run(ops, "", nil); err != txn.ErrAborted { |
305 » » if count, err := ru.st.relationScopes.FindId(key).Count(); err ! = nil { | |
306 » » » return fmt.Errorf("cannot examine scope for %s: %v", des c, err) | |
307 » » } else if count != 0 { | |
308 » » » return nil | |
309 » » } | |
310 » » for _, l := range []lifeRefresher{ru.relation, ru.unit} { | |
rog
2012/12/07 10:06:21
perhaps a comment might be appropriate here, sayin
fwereade
2012/12/07 10:30:04
If any DocMissing failed, we must already be in sc
rog
2012/12/07 10:40:53
i think that something encapsulating the above inf
fwereade
2012/12/07 15:06:11
Indeed -- I wasn't trying to say "no comments!", I
| |
311 » » » if err := l.Refresh(); IsNotFound(err) { | |
312 » » » » return ErrCannotEnterScope | |
313 » » » } else if err != nil { | |
314 » » » » return err | |
315 » » » } | |
316 » » » if l.Life() != Alive { | |
317 » » » » return ErrCannotEnterScope | |
318 » » » } | |
jameinel
2012/12/04 09:06:08
This feels like something that would like to retur
fwereade
2012/12/04 11:31:45
Please expand... what is improved by emitting/hand
TheMue
2012/12/07 10:07:10
Here I have my troubles. If it is an expected and
fwereade
2012/12/07 10:30:04
I'm confused... why is this different from all the
rog
2012/12/07 10:40:53
i think returning specific errors is just fine. we
| |
319 » » } | |
320 » » return fmt.Errorf("cannot enter scope for %s: inconsistent state ", desc) | |
321 » } else if err != nil { | |
322 return err | 305 return err |
323 } | 306 } |
324 » return nil | 307 » if count, err := ru.st.relationScopes.FindId(key).Count(); err != nil { |
308 » » return fmt.Errorf("cannot examine scope for %s: %v", desc, err) | |
309 » } else if count != 0 { | |
310 » » // The scope document exists, so we're already in scope; the txn was | |
311 » » // aborted by one of the DocMissing checks. | |
312 » » return nil | |
313 » } | |
314 » // If there's no scope document, the abort should be a consequence of | |
315 » // one of the isAlive checks: find out which. | |
316 » for _, l := range []lifeRefresher{ru.relation, ru.unit} { | |
317 » » if err := l.Refresh(); IsNotFound(err) { | |
318 » » » return ErrCannotEnterScope | |
319 » » } else if err != nil { | |
320 » » » return err | |
321 » » } | |
322 » » if l.Life() != Alive { | |
323 » » » return ErrCannotEnterScope | |
324 » » } | |
325 » } | |
326 » // Apparently, all our assertions should have passed, but the txn was | |
327 » // aborted: something is badly wrong. | |
328 » return fmt.Errorf("cannot enter scope for %s: inconsistent state", desc) | |
325 } | 329 } |
326 | 330 |
327 type lifeRefresher interface { | 331 type lifeRefresher interface { |
328 Life() Life | 332 Life() Life |
329 Refresh() error | 333 Refresh() error |
330 } | 334 } |
331 | 335 |
332 // LeaveScope signals that the unit has left its scope in the relation. | 336 // LeaveScope signals that the unit has left its scope in the relation. |
333 // After the unit has left its relation scope, it is no longer a member | 337 // After the unit has left its relation scope, it is no longer a member |
334 // of the relation; if the relation is dying when its last member unit | 338 // of the relation; if the relation is dying when its last member unit |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
466 // relationScopeDoc represents a unit which is in a relation scope. | 470 // relationScopeDoc represents a unit which is in a relation scope. |
467 // The relation, container, role, and unit are all encoded in the key. | 471 // The relation, container, role, and unit are all encoded in the key. |
468 type relationScopeDoc struct { | 472 type relationScopeDoc struct { |
469 Key string `bson:"_id"` | 473 Key string `bson:"_id"` |
470 } | 474 } |
471 | 475 |
472 func (d *relationScopeDoc) unitName() string { | 476 func (d *relationScopeDoc) unitName() string { |
473 parts := strings.Split(d.Key, "#") | 477 parts := strings.Split(d.Key, "#") |
474 return parts[len(parts)-1] | 478 return parts[len(parts)-1] |
475 } | 479 } |
LEFT | RIGHT |