Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(275)

Unified Diff: worker/apiuniter/relation/relation.go

Issue 13401050: worker;cmd/jujud: Replace uniter with apiuniter (Closed)
Patch Set: worker;cmd/jujud: Replace uniter with apiuniter Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « worker/apiuniter/relation/hookqueue_test.go ('k') | worker/apiuniter/relation/relation_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: worker/apiuniter/relation/relation.go
=== removed file 'worker/apiuniter/relation/relation.go'
--- worker/apiuniter/relation/relation.go 2013-09-10 12:21:02 +0000
+++ worker/apiuniter/relation/relation.go 1970-01-01 00:00:00 +0000
@@ -1,232 +0,0 @@
-// Copyright 2012, 2013 Canonical Ltd.
-// Licensed under the AGPLv3, see LICENCE file for details.
-
-// relation implements persistent local storage of a unit's relation state, and
-// translation of relation changes into hooks that need to be run.
-package relation
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "strconv"
- "strings"
-
- "launchpad.net/juju-core/charm/hooks"
- "launchpad.net/juju-core/utils"
- "launchpad.net/juju-core/worker/apiuniter/hook"
-)
-
-// State describes the state of a relation.
-type State struct {
- // RelationId identifies the relation.
- RelationId int
-
- // Members is a map from unit name to the last change version
- // for which a hook.Info was delivered on the output channel.
- Members map[string]int64
-
- // ChangedPending indicates that a "relation-changed" hook for the given
- // unit name must be the first hook.Info to be sent to the output channel.
- ChangedPending string
-}
-
-// copy returns an independent copy of the state.
-func (s *State) copy() *State {
- copy := &State{
- RelationId: s.RelationId,
- ChangedPending: s.ChangedPending,
- }
- if s.Members != nil {
- copy.Members = map[string]int64{}
- for m, v := range s.Members {
- copy.Members[m] = v
- }
- }
- return copy
-}
-
-// Validate returns an error if the supplied hook.Info does not represent
-// a valid change to the relation state. Hooks must always be validated
-// against the current state before they are run, to ensure that the system
-// meets its guarantees about hook execution order.
-func (s *State) Validate(hi hook.Info) (err error) {
- defer utils.ErrorContextf(&err, "inappropriate %q for %q", hi.Kind, hi.RemoteUnit)
- if hi.RelationId != s.RelationId {
- return fmt.Errorf("expected relation %d, got relation %d", s.RelationId, hi.RelationId)
- }
- if s.Members == nil {
- return fmt.Errorf(`relation is broken and cannot be changed further`)
- }
- unit, kind := hi.RemoteUnit, hi.Kind
- if kind == hooks.RelationBroken {
- if len(s.Members) == 0 {
- return nil
- }
- return fmt.Errorf(`cannot run "relation-broken" while units still present`)
- }
- if s.ChangedPending != "" {
- if unit != s.ChangedPending || kind != hooks.RelationChanged {
- return fmt.Errorf(`expected "relation-changed" for %q`, s.ChangedPending)
- }
- } else if _, joined := s.Members[unit]; joined && kind == hooks.RelationJoined {
- return fmt.Errorf("unit already joined")
- } else if !joined && kind != hooks.RelationJoined {
- return fmt.Errorf("unit has not joined")
- }
- return nil
-}
-
-// StateDir is a filesystem-backed representation of the state of a
-// relation. Concurrent modifications to the underlying state directory
-// will have undefined consequences.
-type StateDir struct {
- // path identifies the directory holding persistent state.
- path string
-
- // state is the cached state of the directory, which is guaranteed
- // to be synchronized with the true state so long as no concurrent
- // changes are made to the directory.
- state State
-}
-
-// State returns the current state of the relation.
-func (d *StateDir) State() *State {
- return d.state.copy()
-}
-
-// ReadStateDir loads a StateDir from the subdirectory of dirPath named
-// for the supplied RelationId. If the directory does not exist, no error
-// is returned,
-func ReadStateDir(dirPath string, relationId int) (d *StateDir, err error) {
- d = &StateDir{
- filepath.Join(dirPath, strconv.Itoa(relationId)),
- State{relationId, map[string]int64{}, ""},
- }
- defer utils.ErrorContextf(&err, "cannot load relation state from %q", d.path)
- if _, err := os.Stat(d.path); os.IsNotExist(err) {
- return d, nil
- } else if err != nil {
- return nil, err
- }
- fis, err := ioutil.ReadDir(d.path)
- if err != nil {
- return nil, err
- }
- for _, fi := range fis {
- // Entries with names ending in "-" followed by an integer must be
- // files containing valid unit data; all other names are ignored.
- name := fi.Name()
- i := strings.LastIndex(name, "-")
- if i == -1 {
- continue
- }
- svcName := name[:i]
- unitId := name[i+1:]
- if _, err := strconv.Atoi(unitId); err != nil {
- continue
- }
- unitName := svcName + "/" + unitId
- var info diskInfo
- if err = utils.ReadYaml(filepath.Join(d.path, name), &info); err != nil {
- return nil, fmt.Errorf("invalid unit file %q: %v", name, err)
- }
- if info.ChangeVersion == nil {
- return nil, fmt.Errorf(`invalid unit file %q: "changed-version" not set`, name)
- }
- d.state.Members[unitName] = *info.ChangeVersion
- if info.ChangedPending {
- if d.state.ChangedPending != "" {
- return nil, fmt.Errorf("%q and %q both have pending changed hooks", d.state.ChangedPending, unitName)
- }
- d.state.ChangedPending = unitName
- }
- }
- return d, nil
-}
-
-// ReadAllStateDirs loads and returns every StateDir persisted directly inside
-// the supplied dirPath. If dirPath does not exist, no error is returned.
-func ReadAllStateDirs(dirPath string) (dirs map[int]*StateDir, err error) {
- defer utils.ErrorContextf(&err, "cannot load relations state from %q", dirPath)
- if _, err := os.Stat(dirPath); os.IsNotExist(err) {
- return nil, nil
- } else if err != nil {
- return nil, err
- }
- fis, err := ioutil.ReadDir(dirPath)
- if err != nil {
- return nil, err
- }
- dirs = map[int]*StateDir{}
- for _, fi := range fis {
- // Entries with integer names must be directories containing StateDir
- // data; all other names will be ignored.
- relationId, err := strconv.Atoi(fi.Name())
- if err != nil {
- // This doesn't look like a relation.
- continue
- }
- dir, err := ReadStateDir(dirPath, relationId)
- if err != nil {
- return nil, err
- }
- dirs[relationId] = dir
- }
- return dirs, nil
-}
-
-// Ensure creates the directory if it does not already exist.
-func (d *StateDir) Ensure() error {
- return os.MkdirAll(d.path, 0755)
-}
-
-// Write atomically writes to disk the relation state change in hi.
-// It must be called after the respective hook was executed successfully.
-// Write doesn't validate hi but guarantees that successive writes of
-// the same hi are idempotent.
-func (d *StateDir) Write(hi hook.Info) (err error) {
- defer utils.ErrorContextf(&err, "failed to write %q hook info for %q on state directory", hi.Kind, hi.RemoteUnit)
- if hi.Kind == hooks.RelationBroken {
- return d.Remove()
- }
- name := strings.Replace(hi.RemoteUnit, "/", "-", 1)
- path := filepath.Join(d.path, name)
- if hi.Kind == hooks.RelationDeparted {
- if err = os.Remove(path); err != nil && !os.IsNotExist(err) {
- return err
- }
- // If atomic delete succeeded, update own state.
- delete(d.state.Members, hi.RemoteUnit)
- return nil
- }
- di := diskInfo{&hi.ChangeVersion, hi.Kind == hooks.RelationJoined}
- if err := utils.WriteYaml(path, &di); err != nil {
- return err
- }
- // If write was successful, update own state.
- d.state.Members[hi.RemoteUnit] = hi.ChangeVersion
- if hi.Kind == hooks.RelationJoined {
- d.state.ChangedPending = hi.RemoteUnit
- } else {
- d.state.ChangedPending = ""
- }
- return nil
-}
-
-// Remove removes the directory if it exists and is empty.
-func (d *StateDir) Remove() error {
- if err := os.Remove(d.path); err != nil && !os.IsNotExist(err) {
- return err
- }
- // If atomic delete succeeded, update own state.
- d.state.Members = nil
- return nil
-}
-
-// diskInfo defines the relation unit data serialization.
-type diskInfo struct {
- ChangeVersion *int64 `yaml:"change-version"`
- ChangedPending bool `yaml:"changed-pending,omitempty"`
-}
« no previous file with comments | « worker/apiuniter/relation/hookqueue_test.go ('k') | worker/apiuniter/relation/relation_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b