Пример #1
0
// toLayers converts a path leading to one or multiple layers to Layer structs,
// selecting the specified fields
func toLayers(path *path.Path, selectedFields []string) ([]*Layer, error) {
	var layers []*Layer

	saveFields(path, selectedFields, []string{FieldLayerSuccessors, FieldLayerPackages, FieldLayerInstalledPackages, FieldLayerRemovedPackages})
	it, _ := path.BuildIterator().Optimize()
	defer it.Close()
	for cayley.RawNext(it) {
		tags := make(map[string]graph.Value)
		it.TagResults(tags)

		layer := Layer{Node: store.NameOf(it.Result())}
		for _, selectedField := range selectedFields {
			switch selectedField {
			case FieldLayerID:
				layer.ID = store.NameOf(tags[FieldLayerID])
			case FieldLayerParent:
				layer.ParentNode = store.NameOf(tags[FieldLayerParent])
			case FieldLayerSuccessors:
				var err error
				layer.SuccessorsNodes, err = toValues(cayley.StartPath(store, layer.Node).In(FieldLayerParent))
				if err != nil {
					log.Errorf("could not get successors of layer %s: %s.", layer.Node, err.Error())
					return nil, err
				}
			case FieldLayerOS:
				layer.OS = store.NameOf(tags[FieldLayerOS])
			case FieldLayerPackages:
				var err error
				it, _ := cayley.StartPath(store, layer.Node).OutWithTags([]string{"predicate"}, FieldLayerInstalledPackages, FieldLayerRemovedPackages).BuildIterator().Optimize()
				defer it.Close()
				for cayley.RawNext(it) {
					tags := make(map[string]graph.Value)
					it.TagResults(tags)

					predicate := store.NameOf(tags["predicate"])
					if predicate == FieldLayerInstalledPackages {
						layer.InstalledPackagesNodes = append(layer.InstalledPackagesNodes, store.NameOf(it.Result()))
					} else if predicate == FieldLayerRemovedPackages {
						layer.RemovedPackagesNodes = append(layer.RemovedPackagesNodes, store.NameOf(it.Result()))
					}
				}
				if it.Err() != nil {
					log.Errorf("could not get installed/removed packages of layer %s: %s.", layer.Node, it.Err())
					return nil, err
				}
			case FieldLayerEngineVersion:
				layer.EngineVersion, _ = strconv.Atoi(store.NameOf(tags[FieldLayerEngineVersion]))
			default:
				panic("unknown selectedField")
			}
		}
		layers = append(layers, &layer)
	}
	if it.Err() != nil {
		log.Errorf("failed query in toLayers: %s", it.Err())
		return []*Layer{}, ErrBackendException
	}

	return layers, nil
}
Пример #2
0
func (suite *GraphTestSuite) TestSave(t *C) {
	mTime := time.Now()
	ni := graph.NodeInfo{
		Name:     "child",
		ParentId: graph.RootNodeId,
		Mode:     os.FileMode(0755),
		MTime:    mTime,
		Type:     "application/json",
	}

	node, err := suite.ng.NewNodeWithNodeInfo(ni)
	t.Check(err, IsNil)

	assertProperty := func(expected string, actual cayley.Iterator) {
		t.Check(cayley.RawNext(actual), Equals, true)
		t.Check(suite.ng.NameOf(actual.Result()), Equals, expected)
	}

	it := cayley.StartPath(suite.ng, node.Id).Out("isNamed").BuildIterator()
	assertProperty("child", it)

	it = cayley.StartPath(suite.ng, node.Id).Out("hasMTime").BuildIterator()
	assertProperty(mTime.Format(time.RFC3339Nano), it)

	it = cayley.StartPath(suite.ng, node.Id).Out("hasMode").BuildIterator()
	assertProperty(fmt.Sprint(0755), it)

	it = cayley.StartPath(suite.ng, node.Id).Out("hasType").BuildIterator()
	assertProperty("application/json", it)
}
Пример #3
0
func (s *localSignallingLayer) AddServiceHost(service string, version string, uri string) (common.ServiceHost, error) {
	var h, err = s.base.AddServiceHost(service, version, uri)
	if err == nil {
		var svcDef, finderr = s.base.GetServiceDefinition(service)
		if finderr == nil {
			// find all affected api versions
			var startingNodeID = utils.CreateServiceVersionKey(service, version)
			var path = cayley.StartPath(s.graph, startingNodeID).Out(utils.InApiRel)
			it := path.BuildIterator()
			for cayley.RawNext(it) {
				var apiNodeID = s.graph.NameOf(it.Result())
				var apiVersion = strings.TrimPrefix(apiNodeID, utils.CreateAPIVersionKey(""))
				var event = common.Event{}
				event.ActionCode = "ADD_ServiceHost"
				event.Data = map[string]string{
					"version": apiVersion,
					"prefix":  svcDef.Prefix,
					"uri":     uri}
				s.signalOutput <- event
			}
		}
	}

	return h, err
}
Пример #4
0
// pruneLocks removes every expired locks from the database
func pruneLocks() {
	now := time.Now()

	// Delete every expired locks
	tr := cayley.NewTransaction()
	it, _ := cayley.StartPath(store, "locked").In("locked").Save("locked_until", "locked_until").Save("locked_by", "locked_by").BuildIterator().Optimize()
	defer it.Close()
	for cayley.RawNext(it) {
		tags := make(map[string]graph.Value)
		it.TagResults(tags)

		n := store.NameOf(it.Result())
		t := store.NameOf(tags["locked_until"])
		o := store.NameOf(tags["locked_by"])
		tt, _ := strconv.ParseInt(t, 10, 64)

		if now.Unix() > tt {
			log.Debugf("Lock %s owned by %s has expired.", n, o)
			tr.RemoveQuad(cayley.Quad(n, "locked", "locked", ""))
			tr.RemoveQuad(cayley.Quad(n, "locked_until", t, ""))
			tr.RemoveQuad(cayley.Quad(n, "locked_by", o, ""))
		}
	}
	store.ApplyTransaction(tr)
}
Пример #5
0
Файл: lock.go Проект: dwdm/clair
// Unlock unlocks a lock specified by its name if I own it
func Unlock(name, owner string) {
	unlocked := 0
	it, _ := cayley.StartPath(store, name).Has(fieldLockLocked, fieldLockLockedValue).Has(fieldLockLockedBy, owner).Save(fieldLockLockedUntil, fieldLockLockedUntil).BuildIterator().Optimize()
	defer it.Close()
	for cayley.RawNext(it) {
		tags := make(map[string]graph.Value)
		it.TagResults(tags)

		t := cayley.NewTransaction()
		t.RemoveQuad(cayley.Triple(name, fieldLockLocked, fieldLockLockedValue))
		t.RemoveQuad(cayley.Triple(name, fieldLockLockedUntil, store.NameOf(tags[fieldLockLockedUntil])))
		t.RemoveQuad(cayley.Triple(name, fieldLockLockedBy, owner))
		err := store.ApplyTransaction(t)
		if err != nil {
			log.Errorf("failed transaction (Unlock): %s", err)
		}

		unlocked++
	}
	if it.Err() != nil {
		log.Errorf("failed query in Unlock: %s", it.Err())
	}
	if unlocked > 1 {
		// We should never see this, it would mean that our database doesn't ensure quad uniqueness
		// and that the entire lock system is jeopardized.
		log.Errorf("found inconsistency in Unlock: matched %d times a locked named: %s", unlocked, name)
	}
}
Пример #6
0
/*
* Searches for articles in the database
* @param tags string[] The tags entered by the user.Currently only entity search has been implemented.
Algorithm in Readme
*/
func SearchForArticles(tags []string, store *cayley.Handle) PairList {
	links := make(map[string]int)

	for _, tag := range tags {

		entities := extractArticleData.GetEntityInfo(tag, "")

		if len(entities) == 0 {
			continue
		}

		entitityInfo := entities[0] // Get the First Entity //TODO:- Change to Best Label Match

		for _, category := range entitityInfo.Categories {

			path := cayley.StartPath(store, category).
				In("has_category").
				In("has_entity")

			it := path.BuildIterator()
			it, _ = it.Optimize()

			for cayley.RawNext(it) {
				link := store.NameOf(it.Result())
				links[link] += 10
			}
		}
	}
	return sortMapByValue(links)
}
Пример #7
0
Файл: lock.go Проект: dwdm/clair
// pruneLocks removes every expired locks from the database
func pruneLocks() {
	now := time.Now()

	// Delete every expired locks
	it, _ := cayley.StartPath(store, "locked").In("locked").Save(fieldLockLockedUntil, fieldLockLockedUntil).Save(fieldLockLockedBy, fieldLockLockedBy).BuildIterator().Optimize()
	defer it.Close()
	for cayley.RawNext(it) {
		tags := make(map[string]graph.Value)
		it.TagResults(tags)

		n := store.NameOf(it.Result())
		t := store.NameOf(tags[fieldLockLockedUntil])
		o := store.NameOf(tags[fieldLockLockedBy])
		tt, _ := strconv.ParseInt(t, 10, 64)

		if now.Unix() > tt {
			log.Debugf("lock %s owned by %s has expired.", n, o)

			tr := cayley.NewTransaction()
			tr.RemoveQuad(cayley.Triple(n, fieldLockLocked, fieldLockLockedValue))
			tr.RemoveQuad(cayley.Triple(n, fieldLockLockedUntil, t))
			tr.RemoveQuad(cayley.Triple(n, fieldLockLockedBy, o))
			err := store.ApplyTransaction(tr)
			if err != nil {
				log.Errorf("failed transaction (pruneLocks): %s", err)
				continue
			}
			log.Debugf("lock %s has been successfully pruned.", n)
		}
	}
	if it.Err() != nil {
		log.Errorf("failed query in Unlock: %s", it.Err())
	}
}
Пример #8
0
func (s *SocketServer) NotifyStop(t int64) {
	stopAt := strconv.FormatInt(t, 10)
	p := cayley.StartPath(s.storage, stopAt).In("free at")
	it := p.BuildIterator()
	for cayley.RawNext(it) {
		s.BroadcastTo(RoomName, "stop", s.storage.NameOf(it.Result()))
	}
}
Пример #9
0
func (nd *Node) graphValue(key string) (value string) {
	it := cayley.StartPath(nd.graph, nd.Id).Out(key).BuildIterator()
	if cayley.RawNext(it) {
		value = nd.graph.NameOf(it.Result())
	}

	return
}
Пример #10
0
func (s *SocketServer) NotifyEnable(t int64) {
	stopedAt := strconv.FormatInt(t-models.Wait5Minutes, 10)
	p := cayley.StartPath(s.storage, stopedAt).In("free at")
	it := p.BuildIterator()
	for cayley.RawNext(it) {
		//TODO send to only one user
		s.BroadcastTo(RoomName, "enable", s.storage.NameOf(it.Result()))
	}
}
Пример #11
0
func (a *ACL) GetProfilePerm(sourceprofileid, targetprofile string) []string {
	p := cayley.StartPath(a.profilestore, sourceprofileid).Out(targetprofile)
	it := p.BuildIterator()
	r := []string{}
	for cayley.RawNext(it) {
		r = append(r, a.profilestore.NameOf(it.Result()))
	}
	return r
}
Пример #12
0
func (ng *NodeGraph) NodeWithName(parentId, name string) *Node {
	namePath := cayley.StartPath(ng, name).In(nameLink)
	parentpath := cayley.StartPath(ng, parentId).In(parentLink)

	it := namePath.And(parentpath).BuildIterator()
	if cayley.RawNext(it) {
		return ng.NodeWithId(ng.NameOf(it.Result()))
	}

	return nil
}
Пример #13
0
func (nd *Node) BlockWithOffset(offset int64) string {
	if nd.IsDir() {
		return ""
	}

	it := cayley.StartPath(nd.graph, nd.Id).Out(fmt.Sprint("offset-", offset)).BuildIterator()
	if cayley.RawNext(it) {
		return nd.graph.NameOf(it.Result())
	} else {
		return ""
	}
}
Пример #14
0
func (s *Storage) GetUsersFreeAt(t int64) []*User {
	freeAt := strconv.FormatInt(t, 10)

	users := []*User{}
	p := cayley.StartPath(s, freeAt).In("free at")
	it := p.BuildIterator()
	for cayley.RawNext(it) {
		users = append(users, NewUser(s.NameOf(it.Result())))
	}

	return users
}
Пример #15
0
func (s *Storage) SaveUser(u *User) {
	s.AddQuad(cayley.Quad(u.Name, "is", "user", ""))

	p := cayley.StartPath(u.getStorage(), u.Name).Out("free at")

	iterationTime := u.IterationTime()
	it := p.BuildIterator()
	for cayley.RawNext(it) {
		s.RemoveQuad(cayley.Quad(u.Name, "free at", s.NameOf(it.Result()), ""))
	}

	s.AddQuad(cayley.Quad(u.Name, "free at", strconv.FormatInt(iterationTime, 10), ""))
}
Пример #16
0
func (suite *GraphTestSuite) TestWriteData_removesExistingFingerprintForOffset(t *C) {
	child, _ := makeNode("child", suite.ng.RootNode.Id, time.Now(), suite.ng)
	dat := testutils.RandDat(1024)

	t.Check(child.WriteData(dat, 0), IsNil)

	dat = testutils.RandDat(1024)
	fingerprint := graph.Hash(dat)
	t.Check(child.WriteData(dat, 0), IsNil)

	it := cayley.StartPath(suite.ng, child.Id).Out("offset-0").BuildIterator()
	t.Check(cayley.RawNext(it), Equals, true)
	t.Check(suite.ng.NameOf(it.Result()), Equals, fingerprint)
}
Пример #17
0
func (u *User) IterationTime() int64 {
	if u.iterationTime == 0 {
		p := cayley.StartPath(u.getStorage(), u.Name).Out("free at")

		it := p.BuildIterator()
		if cayley.RawNext(it) {
			u.iterationTime, _ = strconv.ParseInt(u.getStorage().NameOf(it.Result()), 10, 64)
		} else {
			u.iterationTime = time.Now().Unix() - Wait5Minutes
		}
	}

	return u.iterationTime
}
Пример #18
0
// CountNotificationsToSend returns the number of pending notifications
// Note that it also count the locked notifications.
func CountNotificationsToSend() (int, error) {
	c := 0

	it, _ := cayley.StartPath(store, "notification").In(FieldIs).Has("isSent", strconv.FormatBool(false)).BuildIterator().Optimize()
	defer it.Close()
	for cayley.RawNext(it) {
		c = c + 1
	}
	if it.Err() != nil {
		log.Errorf("failed query in CountNotificationsToSend: %s", it.Err())
		return 0, ErrBackendException
	}

	return c, nil
}
Пример #19
0
func (p *mgoPersistenceProvider) loadVersionsByAPI(apiVersion string, graph *cayley.Handle, session *mgo.Session, target common.IServiceRegistry) error {
	var startingNodeID = utils.CreateAPIVersionKey(apiVersion)
	var path = cayley.StartPath(graph, startingNodeID).Out(utils.ContainsVersionRel)
	it := path.BuildIterator()
	for cayley.RawNext(it) {
		var version serviceVersion
		err := session.DB("test").C("serviceVersions").Find(bson.M{"_id": graph.NameOf(it.Result())}).One(&version)
		if err != nil {
			return err
		}
		target.LinkServiceToAPI(version.Service, version.Version, apiVersion)
	}

	return nil
}
Пример #20
0
func (p *mgoPersistenceProvider) loadVersionsByService(serviceIdentifier string, graph *cayley.Handle, session *mgo.Session, target common.IServiceRegistry) error {
	var startingNodeID = utils.CreateServiceDefinitionKey(serviceIdentifier)
	var path = cayley.StartPath(graph, startingNodeID).Out(utils.ContainsVersionRel)
	it := path.BuildIterator()
	for cayley.RawNext(it) {
		var version serviceVersion
		var serviceVersionNode = graph.NameOf(it.Result())
		err := session.DB("test").C("serviceVersions").Find(bson.M{"_id": serviceVersionNode}).One(&version)
		if err != nil {
			return fmt.Errorf("Cannot find %s in collection 'serviceVersions': %s", serviceVersionNode, err.Error())
		}
		target.AddServiceVersion(serviceIdentifier, version.Version)
	}

	return nil
}
Пример #21
0
// LockInfo returns the owner of a lock specified by its name and its
// expiration time
func LockInfo(name string) (string, time.Time, error) {
	it, _ := cayley.StartPath(store, name).Has("locked", "locked").Save("locked_until", "locked_until").Save("locked_by", "locked_by").BuildIterator().Optimize()
	defer it.Close()
	for cayley.RawNext(it) {
		tags := make(map[string]graph.Value)
		it.TagResults(tags)

		tt, _ := strconv.ParseInt(store.NameOf(tags["locked_until"]), 10, 64)
		return store.NameOf(tags["locked_by"]), time.Unix(tt, 0), nil
	}
	if it.Err() != nil {
		log.Errorf("failed query in LockInfo: %s", it.Err())
		return "", time.Time{}, ErrBackendException
	}

	return "", time.Time{}, cerrors.ErrNotFound
}
Пример #22
0
// toValues returns multiple values from a path
// If the path does not lead to any value, an empty array is returned
// If a database error occurs, an empty array and an error are returned
func toValues(p *path.Path) ([]string, error) {
	var values []string

	it, _ := p.BuildIterator().Optimize()
	defer it.Close()
	for cayley.RawNext(it) {
		if it.Result() != nil {
			values = append(values, store.NameOf(it.Result()))
		}
	}
	if it.Err() != nil {
		log.Errorf("failed query in toValues: %s", it.Err())
		return []string{}, ErrBackendException
	}

	return values, nil
}
Пример #23
0
func (nd *Node) Children() []*Node {
	if !nd.IsDir() {
		return make([]*Node, 0)
	}

	it := cayley.StartPath(nd.graph, nd.Id).In(parentLink).BuildIterator()
	children := make([]*Node, 0, 10)
	for cayley.RawNext(it) {
		child := nd.graph.NodeWithId(nd.graph.NameOf(it.Result()))
		child.parentId = nd.Id
		children = append(children, child)
	}

	Sort(children, Alphabetical)

	return children
}
Пример #24
0
// Unlock unlocks a lock specified by its name if I own it
func Unlock(name, owner string) {
	pruneLocks()

	t := cayley.NewTransaction()
	it, _ := cayley.StartPath(store, name).Has("locked", "locked").Has("locked_by", owner).Save("locked_until", "locked_until").BuildIterator().Optimize()
	defer it.Close()

	for cayley.RawNext(it) {
		tags := make(map[string]graph.Value)
		it.TagResults(tags)

		t.RemoveQuad(cayley.Quad(name, "locked", "locked", ""))
		t.RemoveQuad(cayley.Quad(name, "locked_until", store.NameOf(tags["locked_until"]), ""))
		t.RemoveQuad(cayley.Quad(name, "locked_by", owner, ""))
	}

	store.ApplyTransaction(t)
}
Пример #25
0
// toPackages converts a path leading to one or multiple packages to Package structs, selecting the specified fields
func toPackages(path *path.Path, selectedFields []string) ([]*Package, error) {
	var packages []*Package
	var err error

	saveFields(path, selectedFields, []string{FieldPackagePreviousVersion})
	it, _ := path.BuildIterator().Optimize()
	defer it.Close()
	for cayley.RawNext(it) {
		tags := make(map[string]graph.Value)
		it.TagResults(tags)

		pkg := Package{Node: store.NameOf(it.Result())}
		for _, selectedField := range selectedFields {
			switch selectedField {
			case FieldPackageOS:
				pkg.OS = store.NameOf(tags[FieldPackageOS])
			case FieldPackageName:
				pkg.Name = store.NameOf(tags[FieldPackageName])
			case FieldPackageVersion:
				pkg.Version, err = types.NewVersion(store.NameOf(tags[FieldPackageVersion]))
				if err != nil {
					log.Warningf("could not parse version of package %s: %s", pkg.Node, err.Error())
				}
			case FieldPackageNextVersion:
				pkg.NextVersionNode = store.NameOf(tags[FieldPackageNextVersion])
			case FieldPackagePreviousVersion:
				pkg.PreviousVersionNode, err = toValue(cayley.StartPath(store, pkg.Node).In(FieldPackageNextVersion))
				if err != nil {
					log.Warningf("could not get previousVersion on package %s: %s.", pkg.Node, err.Error())
					return []*Package{}, ErrInconsistent
				}
			default:
				panic("unknown selectedField")
			}
		}
		packages = append(packages, &pkg)
	}
	if it.Err() != nil {
		log.Errorf("failed query in toPackages: %s", it.Err())
		return []*Package{}, ErrBackendException
	}

	return packages, nil
}
Пример #26
0
// toVulnerabilities converts a path leading to one or multiple vulnerabilities to Vulnerability structs, selecting the specified fields
func toVulnerabilities(path *path.Path, selectedFields []string) ([]*Vulnerability, error) {
	var vulnerabilities []*Vulnerability

	saveFields(path, selectedFields, []string{FieldVulnerabilityFixedIn, FieldVulnerabilityCausedByPackage})
	it, _ := path.BuildIterator().Optimize()
	defer it.Close()
	for cayley.RawNext(it) {
		tags := make(map[string]graph.Value)
		it.TagResults(tags)

		vulnerability := Vulnerability{Node: store.NameOf(it.Result())}
		for _, selectedField := range selectedFields {
			switch selectedField {
			case FieldVulnerabilityID:
				vulnerability.ID = store.NameOf(tags[FieldVulnerabilityID])
			case FieldVulnerabilityLink:
				vulnerability.Link = store.NameOf(tags[FieldVulnerabilityLink])
			case FieldVulnerabilityPriority:
				vulnerability.Priority = types.Priority(store.NameOf(tags[FieldVulnerabilityPriority]))
			case FieldVulnerabilityDescription:
				vulnerability.Description = store.NameOf(tags[FieldVulnerabilityDescription])
			case FieldVulnerabilityFixedIn:
				var err error
				vulnerability.FixedInNodes, err = toValues(cayley.StartPath(store, vulnerability.Node).Out(FieldVulnerabilityFixedIn))
				if err != nil {
					log.Errorf("could not get fixedIn on vulnerability %s: %s.", vulnerability.Node, err.Error())
					return []*Vulnerability{}, err
				}
			case FieldVulnerabilityCausedByPackage:
				vulnerability.CausedByPackage = store.NameOf(tags[FieldVulnerabilityCausedByPackage])
			default:
				panic("unknown selectedField")
			}
		}
		vulnerabilities = append(vulnerabilities, &vulnerability)
	}
	if it.Err() != nil {
		log.Errorf("failed query in toVulnerabilities: %s", it.Err())
		return []*Vulnerability{}, ErrBackendException
	}

	return vulnerabilities, nil
}
Пример #27
0
func open() {
	path := "./db"
	// Initialize the database
	graph.InitQuadStore("bolt", path, nil)

	// Open and use the database
	store, err := cayley.NewGraph("bolt", path, nil)
	if err != nil {
		log.Fatalln(err)
	}

	p := cayley.StartPath(store, "").Out("type").Is("Person")

	it := p.BuildIterator()
	for cayley.RawNext(it) {
		log.Println(store.NameOf(it.Result()))
	}

}
Пример #28
0
// FindOneNotificationToSend finds and returns a notification that is not sent
// yet and not locked. Returns nil if there is none.
func FindOneNotificationToSend(wrapper NotificationWrapper) (string, Notification, error) {
	it, _ := cayley.StartPath(store, "notification").In(FieldIs).Has("isSent", strconv.FormatBool(false)).Except(getLockedNodes()).Save("type", "type").Save("data", "data").BuildIterator().Optimize()
	defer it.Close()
	for cayley.RawNext(it) {
		tags := make(map[string]graph.Value)
		it.TagResults(tags)

		notification, err := wrapper.Unwrap(&NotificationWrap{Type: store.NameOf(tags["type"]), Data: store.NameOf(tags["data"])})
		if err != nil {
			return "", nil, err
		}

		return store.NameOf(it.Result()), notification, nil
	}
	if it.Err() != nil {
		log.Errorf("failed query in FindOneNotificationToSend: %s", it.Err())
		return "", nil, ErrBackendException
	}

	return "", nil, nil
}
Пример #29
0
func (s *Storage) GetUsers(exclude ...*User) []*User {
	users := []*User{}
	p := cayley.StartPath(s, "user").In("is")
	it := p.BuildIterator()
	for cayley.RawNext(it) {
		name := s.NameOf(it.Result())
		excluded := false
		if len(exclude) > 0 {
			for _, u := range exclude {
				if name == u.Name {
					excluded = true
					break
				}
			}
		}
		if !excluded {
			users = append(users, NewUser(name))
		}
	}

	return users
}
Пример #30
0
// toValue returns a single value from a path
// If the path does not lead to a value, an empty string is returned
// If the path leads to multiple values or if a database error occurs, an empty string and an error are returned
func toValue(p *path.Path) (string, error) {
	var value string

	it, _ := p.BuildIterator().Optimize()
	defer it.Close()
	for cayley.RawNext(it) {
		if value != "" {
			log.Error("failed query in toValue: used on an iterator containing multiple values")
			return "", ErrInconsistent
		}

		if it.Result() != nil {
			value = store.NameOf(it.Result())
		}
	}
	if it.Err() != nil {
		log.Errorf("failed query in toValue: %s", it.Err())
		return "", ErrBackendException
	}

	return value, nil
}