// The lazy per-value equality index behind NodesWithProperty and friends:// (label, key) -> value -> node set, built on first access by scanning the// column, with builds running outside the lock (a racing duplicate is// discarded -- both are identical).package chickpeasimport ()type propIndexKey struct { label Label key PropertyKey}// anyLabel is the reserved sentinel scoping the label-free index built by// NodeWithProperty.const anyLabel = Label(^uint32(0))// valueFromAny resolves a convenience value (string, int, int32, int64,// float64, bool, or Value) to a Value. A string that was never interned// resolves to nothing -- no property can equal it.func ( *Snapshot) ( any) (Value, bool) {switch v := .(type) {caseValue:return , truecasestring:return .ValueFromString()caseint64:returnI64Value(), truecaseint:returnI64Value(int64()), truecaseint32:returnI64Value(int64()), truecasefloat64:returnF64Value(), truecasebool:returnBoolValue(), true }returnValue{}, false}// buildPropValueIndex groups a column's entries by value, restricted to// labelNodes when non-nil.func buildPropValueIndex( Column, *nodeset.Set) map[Value]*nodeset.Set { := map[Value][]uint32{}for , := range .Entries() {if == nil || .Contains() { [] = append([], ) } } := make(map[Value]*nodeset.Set, len())for , := range { := roaring.New() .AddMany() [] = nodeset.FromBitmap() }return}// withPropValueIndex runs query against the cached per-value index for// indexKey, building it once via build on a miss. The build runs OUTSIDE// the lock; build returning nil (unknown column/label) short-circuits.func ( *Snapshot) (propIndexKey,func() map[Value]*nodeset.Set,func(map[Value]*nodeset.Set) (*nodeset.Set, bool),) (*nodeset.Set, bool) { .propIndexMu.Lock() , := .propIndex[] .propIndexMu.Unlock()if {return () } := ()if == nil {returnnil, false } .propIndexMu.Lock()if , := .propIndex[]; { = } else { .propIndex[] = } .propIndexMu.Unlock()return ()}// NodesWithValue is the set of label-carrying nodes whose property key// equals v -- the typed core of NodesWithProperty. The index for (label,// key) is built lazily on first access and cached. The returned set is// shared -- callers must not mutate it (Clone first). ok is false when the// label/key is unknown or no node carries that value.func ( *Snapshot) (, string, Value) (*nodeset.Set, bool) { , := .Label()if ! {returnnil, false } , := .PropertyKey()if ! {returnnil, false }return .withPropValueIndex(propIndexKey{label: , key: },func() map[Value]*nodeset.Set { , := .labelIndex[]if ! {returnnil } , := .columns[]if ! {returnnil }returnbuildPropValueIndex(, ) },func( map[Value]*nodeset.Set) (*nodeset.Set, bool) { , := []return , }, )}// NodesWithProperty is NodesWithValue with a convenience value (string,// int, int32, int64, float64, bool, or Value).func ( *Snapshot) (, string, any) (*nodeset.Set, bool) { , := .valueFromAny()if ! {returnnil, false }return .NodesWithValue(, , )}// NodeWithProperty finds a single node by a property value across ALL// labels (unlike the label-scoped NodesWithProperty) -- for unique keys// such as a uri. Returns the smallest matching node id. The label-free// (key, value) index is built lazily and cached under a reserved sentinel.func ( *Snapshot) ( string, any) (NodeID, bool) { , := .PropertyKey()if ! {return0, false } , := .valueFromAny()if ! {return0, false } , := .withPropValueIndex(propIndexKey{label: anyLabel, key: },func() map[Value]*nodeset.Set { , := .columns[]if ! {returnnil }returnbuildPropValueIndex(, nil) },func( map[Value]*nodeset.Set) (*nodeset.Set, bool) { , := []return , }, )if ! {return0, false }return .Min()}// NodeWithLabelProperty finds a single label-carrying node whose property// key equals value -- the label-scoped sibling of NodeWithProperty, for// keys unique only within a label. Returns the smallest matching node id;// reuses the cached (label, key) index NodesWithProperty builds.func ( *Snapshot) (, string, any) (NodeID, bool) { , := .NodesWithProperty(, , )if ! {return0, false }return .Min()}
The pages are generated with Goldsv0.8.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.