<commit_before>package mstate

import (
	"errors"
	"fmt"
	"labix.org/v2/mgo/bson"
)

// unitDoc represents the internal state of a unit in MongoDB.
type unitDoc struct {
	Name      string `bson:"_id"`
	Service   string
	Principal string
	MachineId *int
	Life      Life
}

// ServiceName returns the service name.
func (u *unitDoc) ServiceName() string {
	return u.Service
}

// String returns the unit as string.
func (u *unitDoc) String() string {
	return u.Name
}

// Unit represents the state of a service unit.
type Unit struct {
	st *State
	unitDoc
}

func newUnit(s *State, udoc *unitDoc) *Unit {
	return &Unit{
		st:      s,
		unitDoc: *udoc,
	}
}

// Name returns the unit name.
func (u *Unit) Name() string {
	return u.unitDoc.Name
}

// IsPrincipal returns whether the unit is deployed in its own container,
// and can therefore have subordinate services deployed alongside it.
func (u *Unit) IsPrincipal() bool {
	return u.unitDoc.Name == u.unitDoc.Principal
}

// AssignedMachineId returns the id of the assigned machine.
func (u *Unit) AssignedMachineId() (id int, err error) {
	defer errorContextf(&err, "can't get machine id of unit %q", u)
	if u.IsPrincipal() {
		if u.unitDoc.MachineId == nil {
			return 0, errors.New("unit not assigned to machine")
		}
		return *u.unitDoc.MachineId, nil
	}
	pudoc := unitDoc{}
	sel := bson.D{{"_id", u.unitDoc.Principal}, {"life", Alive}}
	err = u.st.units.Find(sel).One(&pudoc)
	if err != nil {
		return 0, err
	}
	if pudoc.MachineId == nil {
		return 0, errors.New("unit not assigned to machine")
	}
	return *pudoc.MachineId, nil
}

// AssignToMachine assigns this unit to a given machine.
func (u *Unit) AssignToMachine(m *Machine) (err error) {
	change := bson.D{{"$set", bson.D{{"machineid", m.Id()}}}}
	sel := bson.D{{"_id", u.unitDoc.Principal}, {"machineid", nil}}
	err = u.st.units.Update(sel, change)
	if err != nil {
		return fmt.Errorf("can't assign unit %q to machine %s: %v", u, m, err)
	}
	return nil
}
<commit_msg>mstate: merge lp:~aramh/juju-core/mstate-units-subordinate<commit_after>package mstate

import (
	"errors"
	"fmt"
	"labix.org/v2/mgo/bson"
)

// unitDoc represents the internal state of a unit in MongoDB.
type unitDoc struct {
	Name      string `bson:"_id"`
	Service   string
	Principal string
	MachineId *int
	Life      Life
}

// Unit represents the state of a service unit.
type Unit struct {
	st  *State
	doc unitDoc
}

func newUnit(s *State, udoc *unitDoc) *Unit {
	return &Unit{
		st:  s,
		doc: *udoc,
	}
}

// ServiceName returns the service name.
func (u *Unit) ServiceName() string {
	return u.doc.Service
}

// String returns the unit as string.
func (u *Unit) String() string {
	return u.doc.Name
}

// Name returns the unit name.
func (u *Unit) Name() string {
	return u.doc.Name
}

// IsPrincipal returns whether the unit is deployed in its own container,
// and can therefore have subordinate services deployed alongside it.
func (u *Unit) IsPrincipal() bool {
	return u.doc.Name == u.doc.Principal
}

// AssignedMachineId returns the id of the assigned machine.
func (u *Unit) AssignedMachineId() (id int, err error) {
	defer errorContextf(&err, "can't get machine id of unit %q", u)
	if u.IsPrincipal() {
		if u.doc.MachineId == nil {
			return 0, errors.New("unit not assigned to machine")
		}
		return *u.doc.MachineId, nil
	}
	pudoc := unitDoc{}
	sel := bson.D{{"_id", u.unitDoc.Principal}, {"life", Alive}}
	err = u.st.units.Find(sel).One(&pudoc)
	if err != nil {
		return 0, err
	}
	if pudoc.MachineId == nil {
		return 0, errors.New("unit not assigned to machine")
	}
	return *pudoc.MachineId, nil
}

// AssignToMachine assigns this unit to a given machine.
func (u *Unit) AssignToMachine(m *Machine) (err error) {
	change := bson.D{{"$set", bson.D{{"machineid", m.Id()}}}}
	sel := bson.D{{"_id", u.doc.Principal}, {"machineid", nil}}
	err = u.st.units.Update(sel, change)
	if err != nil {
		return fmt.Errorf("can't assign unit %q to machine %s: %v", u, m, err)
	}
	return nil
}

{'fraction_non_alphanumeric': 0.13898645258404416, 'fraction_numerical': 0.002007024586051179, 'mean_word_length': 3.6145833333333335, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6667728', 'n_tokens_mistral': 1477, 'n_tokens_neox': 1414, 'n_words': 471}