// Relation returns information about all given relation/unit pairs,
// including their id, key and the local endpoint.
436522
func (u *UniterAPI) Relation(args params.RelationUnits) (params.RelationResults, error) {
	result := params.RelationResults{
		Results: make([]params.RelationResult, len(args.RelationUnits)),
	}
	canAccess, err := u.accessUnit()
	if err != nil {
		return params.RelationResults{}, err
	}
	for i, rel := range args.RelationUnits {
		relParams, err := u.getOneRelation(canAccess, rel.Relation, rel.Unit)
		if err == nil {
			result.Results[i] = relParams
		}
		result.Results[i].Error = common.ServerError(err)
	}
	return result, nil
}
290641
func (r *Relation) removeLocalEndpointOps(ep Endpoint, departingUnitName string, op *ForcedOperation) ([]txn.Op, error) {
	var asserts bson.D
	hasRelation := bson.D{{"relationcount", bson.D{{"$gt", 0}}}}
	departingUnitApplicationMatchesEndpoint := func() bool {
		s, err := names.UnitApplication(departingUnitName)
		return err == nil && s == ep.ApplicationName
	}
	var cleanupOps []txn.Op
	if departingUnitName == "" {
		// We're constructing a destroy operation, either of the relation
		// or one of its applications, and can therefore be assured that both
		// applications are Alive.
		asserts = append(hasRelation, isAliveDoc...)
	} else if departingUnitApplicationMatchesEndpoint() {
		// This application must have at least one unit -- the one that's
		// departing the relation -- so it cannot be ready for removal.
		cannotDieYet := bson.D{{"unitcount", bson.D{{"$gt", 0}}}}
		asserts = append(hasRelation, cannotDieYet...)
	} else {
		// This application may require immediate removal.
		// Check if the application is Dying, and if so, queue up a potential
		// cleanup in case this was the last reference.
		applications, closer := r.st.db().GetCollection(applicationsC)
		defer closer()

		asserts = append(hasRelation)
		var appDoc applicationDoc
		if err := applications.FindId(ep.ApplicationName).One(&appDoc); err == nil {
			if appDoc.Life != Alive {
				cleanupOps = append(cleanupOps, newCleanupOp(
					cleanupApplication,
					ep.ApplicationName,
					false, // destroyStorage
					op.Force,
				))
			}
		} else if !op.Force {
			return nil, errors.Trace(err)
		}
	}
	return append([]txn.Op{{
		C:      applicationsC,
		Id:     r.st.docID(ep.ApplicationName),
		Assert: asserts,
		Update: bson.D{{"$inc", bson.D{{"relationcount", -1}}}},
	}}, cleanupOps...), nil
}
596003
func NetworksForRelation(
	binding string, unit *Unit, rel *Relation, defaultEgress []string,
) (boundSpace string, ingress []string, egress []string, _ error) {
	st := unit.st

	relEgress := NewRelationEgressNetworks(st)
	egressSubnets, err := relEgress.Networks(rel.Tag().Id())
	if err != nil && !errors.IsNotFound(err) {
		return "", nil, nil, errors.Trace(err)
	} else if err == nil {
		egress = egressSubnets.CIDRS()
	} else {
		egress = defaultEgress
	}

	boundSpace, err = unit.GetSpaceForBinding(binding)
	if err != nil && !errors.IsNotValid(err) {
		return "", nil, nil, errors.Trace(err)
	}
	// If the endpoint for this relation is not bound to a space, or
	// is bound to the default space, we need to look up the ingress
	// address info which is aware of cross model relations.
	if boundSpace == environs.DefaultSpaceName || err != nil {
		_, crossmodel, err := rel.RemoteApplication()
		if err != nil {
			return "", nil, nil, errors.Trace(err)
		}
		// TODO(caas) - we might need to use the service address
		if crossmodel && unit.ShouldBeAssigned() {
			var address network.Address
			retryArg := PreferredAddressRetryArgs()
			retryArg.Func = func() error {
				var err error
				address, err = unit.PublicAddress()
				return err
			}
			retryArg.IsFatalError = func(err error) bool {
				return !network.IsNoAddressError(err)
			}
			err := retry.Call(retryArg)
			if err != nil {
				// TODO(wallyworld) - it's ok to return a private address sometimes
				// TODO return an error when it's not possible to use the private address
				logger.Warningf(
					"no public address for unit %q in cross model relation %q, using private address",
					unit.Name(), rel)
				address, err = unit.PrivateAddress()
				if err != nil {
					return "", nil, nil, errors.Trace(err)
				}
			}
			ingress = []string{address.Value}
		}
	}
	if len(ingress) == 0 {
		if unit.ShouldBeAssigned() {
			// We don't yet have an ingress address, so pick one from the space to
			// which the endpoint is bound.
			machineID, err := unit.AssignedMachineId()
			if err != nil {
				return "", nil, nil, errors.Trace(err)
			}

			machine, err := st.Machine(machineID)
			if err != nil {
				return "", nil, nil, errors.Trace(err)
			}

			networkInfos := machine.GetNetworkInfoForSpaces(set.NewStrings(boundSpace))
			// The binding address information based on link layer devices.
			for _, nwInfo := range networkInfos[boundSpace].NetworkInfos {
				for _, addr := range nwInfo.Addresses {
					ingress = append(ingress, addr.Address)
				}

			}
		} else {
			// Be be consistent with IAAS behaviour above, we'll return all
			// addresses, including any container address.
			addr, err := unit.AllAddresses()
			if err != nil {
				logger.Warningf(
					"no service address for unit %q in relation %q",
					unit.Name(), rel)
			} else {
				network.SortAddresses(addr)
				for _, a := range addr {
					ingress = append(ingress, a.Value)
				}
			}
		}
	}

	// If no egress subnets defined, We default to the ingress address.
	if len(egress) == 0 && len(ingress) > 0 {
		egress, err = network.FormatAsCIDR([]string{ingress[0]})
		if err != nil {
			return "", nil, nil, errors.Trace(err)
		}
	}
	return boundSpace, ingress, egress, nil
}
980085
func Rels(resource interface{}) Relations {
	cachedResource, ok := resource.(CachedResource)
	if ok {
		if rels, cached := cachedResource.Rels(); cached {
			return rels
		}
	}

	rels := NewRels()
	FillRels(resource, rels)

	if ok {
		cachedResource.CacheRels(rels)
	}

	return rels
}
383096
func (m *model) Connection(deviceID protocol.DeviceID) (connections.Connection, bool) {
	m.pmut.RLock()
	cn, ok := m.conn[deviceID]
	m.pmut.RUnlock()
	if ok {
		m.deviceWasSeen(deviceID)
	}
	return cn, ok
}
1213871
func (relation *Relation) AddRelation(wordID int, relatedWordID int, sentenceID int) {
	if relatedWordID == -1 {
		return
	}

	if relation.updateRelation(relatedWordID, wordID, true, sentenceID) {
		return
	}

	if relation.extendRelation(wordID, relatedWordID, true, sentenceID) {
		return
	}

	relation.createRelation(wordID, relatedWordID, sentenceID)
}
483377
func (ep *endpoint) Key() []string {
	if ep.network == nil {
		return nil
	}

	return []string{datastore.EndpointKeyPrefix, ep.network.id, ep.id}
}
287346
func (r *Relation) AllRemoteUnits(appName string) ([]*RelationUnit, error) {
	// Verify that the unit belongs to a remote application.
	if _, err := r.st.RemoteApplication(appName); err != nil {
		return nil, errors.Trace(err)
	}

	relationScopes, closer := r.st.db().GetCollection(relationScopesC)
	defer closer()

	ep, err := r.Endpoint(appName)
	if err != nil {
		return nil, err
	}
	scope := r.globalScope()
	parts := []string{"^" + scope, string(ep.Role), appName + "/"}
	ruRegex := strings.Join(parts, "#")

	var docs []relationScopeDoc
	if err := relationScopes.Find(bson.D{{"key", bson.D{{"$regex", ruRegex}}}}).All(&docs); err != nil {
		return nil, errors.Trace(err)
	}
	result := make([]*RelationUnit, len(docs))
	for i, doc := range docs {
		result[i] = &RelationUnit{
			st:          r.st,
			relation:    r,
			unitName:    doc.unitName(),
			isPrincipal: true,
			isLocalUnit: false,
			endpoint:    ep,
			scope:       scope,
		}
	}
	return result, nil
}
252752
func (res *Resource) relationshipHandler(
	resourceType string,
	handler http.HandlerFunc,
) {

	// handle /.../:id/<resourceType>
	matcher := fmt.Sprintf("%s/%s", patID, resourceType)
	res.HandleFunc(
		pat.Get(matcher),
		handler,
	)
	res.addRoute(get, matcher)

	// handle /.../:id/relationships/<resourceType>
	relationshipMatcher := fmt.Sprintf("%s/relationships/%s", patID, resourceType)
	res.HandleFunc(
		pat.Get(relationshipMatcher),
		handler,
	)
	res.addRoute(get, relationshipMatcher)
}
1085028
func (u *UniterAPI) RelationsStatus(args params.Entities) (params.RelationUnitStatusResults, error) {
	result := params.RelationUnitStatusResults{
		Results: make([]params.RelationUnitStatusResult, len(args.Entities)),
	}
	if len(args.Entities) == 0 {
		return result, nil
	}
	canRead, err := u.accessUnit()
	if err != nil {
		return params.RelationUnitStatusResults{}, err
	}

	oneRelationUnitStatus := func(rel *state.Relation, unit *state.Unit) (params.RelationUnitStatus, error) {
		rus := params.RelationUnitStatus{
			RelationTag: rel.Tag().String(),
			Suspended:   rel.Suspended(),
		}
		ru, err := rel.Unit(unit)
		if err != nil {
			return params.RelationUnitStatus{}, errors.Trace(err)
		}
		inScope, err := ru.InScope()
		if err != nil {
			return params.RelationUnitStatus{}, errors.Trace(err)
		}
		rus.InScope = inScope
		return rus, nil
	}

	relationResults := func(unit *state.Unit) ([]params.RelationUnitStatus, error) {
		var ruStatus []params.RelationUnitStatus
		app, err := unit.Application()
		if err != nil {
			return nil, errors.Trace(err)
		}
		relations, err := app.Relations()
		for _, rel := range relations {
			rus, err := oneRelationUnitStatus(rel, unit)
			if err != nil {
				return nil, errors.Trace(err)
			}
			ruStatus = append(ruStatus, rus)
		}
		return ruStatus, nil
	}

	for i, entity := range args.Entities {
		tag, err := names.ParseUnitTag(entity.Tag)
		if err != nil {
			result.Results[i].Error = common.ServerError(common.ErrPerm)
			continue
		}
		err = common.ErrPerm
		if canRead(tag) {
			var unit *state.Unit
			unit, err = u.getUnit(tag)
			if err == nil {
				result.Results[i].RelationResults, err = relationResults(unit)
			}
		}
		result.Results[i].Error = common.ServerError(err)
	}
	return result, nil
}
955739
func removeRelations(data [][]string, appName string) [][]string {
	var result [][]string
	for _, relation := range data {
		// Keep the dud relation in the set, it will be caught by the bundle
		// verify code.
		if len(relation) == 2 {
			left, right := relation[0], relation[1]
			if left == appName || strings.HasPrefix(left, appName+":") ||
				right == appName || strings.HasPrefix(right, appName+":") {
				continue
			}
		}
		result = append(result, relation)
	}
	return result
}
270650
func resolveRelation(e string, results map[string]string) string {
	parts := strings.SplitN(e, ":", 2)
	application := resolve(parts[0], results)
	if len(parts) == 1 {
		return application
	}
	return fmt.Sprintf("%s:%s", application, parts[1])
}
436800
func (r *Response) HypermediaRels(rels hypermedia.Relations) {
	if r.rels == nil {
		r.rels = hypermedia.HyperHeaderRelations(r.Header, nil)
	}

	for key, value := range r.rels {
		rels[key] = value
	}
}
12822
func (u *Unit) relations(predicate relationPredicate) ([]*Relation, error) {
	candidates, err := applicationRelations(u.st, u.doc.Application)
	if err != nil {
		return nil, err
	}
	var filtered []*Relation
	for _, relation := range candidates {
		relationUnit, err := relation.Unit(u)
		if err != nil {
			return nil, err
		}
		if include, err := predicate(relationUnit); err != nil {
			return nil, err
		} else if include {
			filtered = append(filtered, relation)
		}
	}
	return filtered, nil
}
1182072
func (api *CrossModelRelationsAPI) RegisterRemoteRelations(
	relations params.RegisterRemoteRelationArgs,
) (params.RegisterRemoteRelationResults, error) {
	results := params.RegisterRemoteRelationResults{
		Results: make([]params.RegisterRemoteRelationResult, len(relations.Relations)),
	}
	for i, relation := range relations.Relations {
		id, err := api.registerRemoteRelation(relation)
		results.Results[i].Result = id
		results.Results[i].Error = common.ServerError(err)
	}
	return results, nil
}
335777
func NewRelationIdValue(ctx Context, result *int) (*relationIdValue, error) {
	v := &relationIdValue{result: result, ctx: ctx}
	id := -1
	if r, err := ctx.HookRelation(); err == nil {
		id = r.Id()
		v.value = r.FakeId()
	} else if !errors.IsNotFound(err) {
		return nil, errors.Trace(err)
	}
	*result = id
	return v, nil
}
329401
func (u *Unit) NetworkInfo(bindings []string, relationId *int) (map[string]params.NetworkInfoResult, error) {
	var results params.NetworkInfoResults
	args := params.NetworkInfoParams{
		Unit:       u.tag.String(),
		Bindings:   bindings,
		RelationId: relationId,
	}

	err := u.st.facade.FacadeCall("NetworkInfo", args, &results)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return results.Results, nil
}