Documentation
¶
Index ¶
- Constants
- func Debug(value string)
- func EntryToBytes(level int, entryID uint64, uv *UniqueValue) []byte
- func HashToBytes(entryID uint64, raw [32]byte) []byte
- func Info(value string)
- type AssociationSet
- func (s *AssociationSet) Delete(key UniqueAssociation)
- func (s *AssociationSet) ForEach(fn func(key UniqueAssociation, pos int64))
- func (s *AssociationSet) Get(key UniqueAssociation) (int64, bool)
- func (s *AssociationSet) HasRelation(rel uint64) bool
- func (s *AssociationSet) Put(key UniqueAssociation, value int64)
- func (s *AssociationSet) Size() int
- type BlobPolicy
- type Collection
- func (ic *Collection) Add(key string, value1 string, value2 string)
- func (ic *Collection) CoTags(q TagQuery, tagRelation string) ([]string, bool)
- func (ic *Collection) Delete(key string, value1 string, value2 string) (string, bool)
- func (ic *Collection) ExpandKeys(keys []string, filter string) []Row
- func (ic *Collection) ForEachTriple(do func(StringTriple))
- func (ic *Collection) Get(key string, value1 string) (TripleSet, bool)
- func (ic *Collection) GetAssociations(value string) (*AssociationSet, bool)
- func (ic *Collection) GetPage(s *AssociationSet, value1Filter string, o SortOptions) (result TripleSet, sorted []StringTriple, totalCount int)
- func (ic *Collection) GetReverseAssociations(value string) (*AssociationSet, bool)
- func (ic *Collection) GetTotalEntries() uint64
- func (ic *Collection) GetTripleSet(s *AssociationSet, value1Filter string, o SortOptions) (result TripleSet, totalCount int)
- func (ic *Collection) QueryTags(q TagQuery) (result TripleSet, sorted []StringTriple, total int, found bool)
- func (ic *Collection) SetBlobPolicy(p *BlobPolicy)
- func (ic *Collection) SetReverseRelations(relations []string)
- func (ic *Collection) SetValues(key string, value1 string, values []string)
- func (ic *Collection) SimpleUpdate(key string, value1 string, newValue2 string, addOnFail bool) (string, bool)
- func (ic *Collection) Sort(tree *AssociationSet, value1Filter string, o SortOptions) (sorted []StringTriple, totalCount int)
- func (ic *Collection) Sync()
- func (ic *Collection) Update(key string, value1 string, value2 string, newValue2 string) (string, bool)
- func (ic *Collection) UpdateAdd(key string, value1 string, value2 string, newValue2 string) (string, bool)
- type CollectionKey
- type FileIndexer
- type FileMod
- type RawDataEntry
- type ReadRequest
- type Row
- type SortOptions
- type StringTriple
- type TagQuery
- type TieTree
- func (db *TieTree) Close()
- func (db *TieTree) DropCollection(key CollectionKey) error
- func (db *TieTree) GetCollection(key CollectionKey) *Collection
- func (tree *TieTree) SetBlobPolicy(p *BlobPolicy)
- func (tree *TieTree) SetDefaultReverseRelations(relations []string)
- func (tree *TieTree) SetReverseRelationsOverrides(overrides map[CollectionKey][]string)
- type Triple
- type TripleSet
- type UniqueAssociation
- type UniqueValue
- type Unit
- type Value1
- type Value2
Constants ¶
const ( ENTRY_SIZE = SIZE_DATATYPE + SIZE_LEVEL + SIZE_ID + SIZE_PARENTID + SIZE_VALUE SIZE_DATATYPE = 2 SIZE_LEVEL = 8 SIZE_ID = 8 SIZE_PARENTID = SIZE_ID SIZE_VALUE = 24 // 6 * 8 - 3 * 8 FILE_ADD = 0 FILE_DELETE = 1 // These values get written to the db files TYPE_DELETE = 10 TYPE_ENTRY = 11 TYPE_ASSOCIATION = 12 TYPE_HASH = 13 // HASH_LEVEL is a sentinel level marking an entry ID that lives in the // whole-value hash store rather than in any trie level. A value routed // through BlobPolicy is stored as one 32-byte record and its Triple level // fields carry HASH_LEVEL, so getValue resolves it from hashEntries instead // of walking ParentId links. HASH_LEVEL = -1 )
Variables ¶
This section is empty.
Functions ¶
func Debug ¶
func Debug(value string)
Debug and Info are thin wrappers kept for existing call sites; they forward to the process slog logger (which tie-triplestore/tie-filehost point at a log file plus pretty stderr). Diagnostics stay off stdout — stdout is data.
func EntryToBytes ¶
func EntryToBytes(level int, entryID uint64, uv *UniqueValue) []byte
func HashToBytes ¶
HashToBytes serializes a whole-value hash entry into the same 50-byte frame as the other record types: datatype(2) | level(8) | entryID(8) | raw hash(32). The 32-byte hash occupies the contiguous parentId+value region of the frame, so ENTRY_SIZE is unchanged. The level field is always HASH_LEVEL.
Types ¶
type AssociationSet ¶
type AssociationSet struct {
// contains filtered or unexported fields
}
AssociationSet is the inner association store: a mapping from UniqueAssociation to an int64 position (a disk offset in disk mode, or an arena index in memory mode). It replaces the former red-black tree: the query paths never use key ordering (Sort re-sorts by resolved strings, intersect/exclude use point lookups), so there is no need to keep entries ordered.
Three representations, chosen by size:
- a single inline entry (no allocation) — the common forward-index case where a content-address key holds exactly one association
- a flat slice — the small case (2..shardThreshold distinct keys), the most memory-compact form for the bimodal middle population
- a sharded map — only once a set exceeds shardThreshold, for the reverse index's shared-value hot sets that many load workers hammer concurrently
It is internal to tiedb: association set algebra reaches callers only through Collection.QueryTags, so no map-of-generic type ever crosses into api/.
func (*AssociationSet) Delete ¶
func (s *AssociationSet) Delete(key UniqueAssociation)
func (*AssociationSet) ForEach ¶
func (s *AssociationSet) ForEach(fn func(key UniqueAssociation, pos int64))
ForEach visits every (key, position). Order is unspecified (the query paths re-sort by resolved strings, so tree ordering was never used).
func (*AssociationSet) Get ¶
func (s *AssociationSet) Get(key UniqueAssociation) (int64, bool)
func (*AssociationSet) HasRelation ¶
func (s *AssociationSet) HasRelation(rel uint64) bool
HasRelation reports whether any entry is stored under relation id rel. The set is keyed on the full {AssociateTo, Relation} pair with no per-relation index, so this scans — but it early-exits on the first match, and the sets it is meant for (one subject's forward associations = its handful of metadata triples) are tiny, so a hit or miss is effectively O(1) in practice.
func (*AssociationSet) Put ¶
func (s *AssociationSet) Put(key UniqueAssociation, value int64)
func (*AssociationSet) Size ¶
func (s *AssociationSet) Size() int
type BlobPolicy ¶
type BlobPolicy struct {
Encode func(value string) (raw []byte, ok bool)
Decode func(raw []byte) string
}
BlobPolicy, when non-nil on a Collection, routes matching values to a whole-value hash entry instead of the 24-byte-chunk trie. Encode maps a value string to its raw bytes, returning ok=false for values that should use the trie; Decode is the inverse, reconstructing the string from stored bytes. Both must be deterministic on the value alone so a value's identity is stable across Adds (the same hash is the Key of many triples).
type Collection ¶
type Collection struct {
// contains filtered or unexported fields
}
func (*Collection) CoTags ¶
func (ic *Collection) CoTags(q TagQuery, tagRelation string) ([]string, bool)
CoTags runs the same set algebra as QueryTags (same Include/Exclude/Scope/Reverse) and returns every unique tagRelation value2 carried by the matching entries. This is a "faceted refinement" query: given the current tag filter, what further tags exist on the matching set? Use tagRelation = "tag" for the standard case.
Returns (nil, false) when the seed term (Include[0]) has no reverse associations. Returns (nil, true) when the AND of include terms yields an empty set (unmet AND). The returned slice is unsorted and deduplicated; sort it in the caller if needed.
func (*Collection) ExpandKeys ¶
func (ic *Collection) ExpandKeys(keys []string, filter string) []Row
ExpandKeys returns one Row per key holding that key's forward attributes (relation -> values), reusing the same GetAssociations + Sort path a query uses. Keys with no associations are skipped. Order follows the input keys. This is the multi-key batch fetch that lets a client attach metadata to many matches (or list many entries) in one round trip instead of one Get per key.
func (*Collection) ForEachTriple ¶
func (ic *Collection) ForEachTriple(do func(StringTriple))
ForEachTriple calls do for every forward triple in the collection. It walks each level's associations tree (keyed by entry ID) and runs each key's association subtree through the same Sort path used by Get, so the emitted triples match query results exactly. Intended for full-collection export.
func (*Collection) GetAssociations ¶
func (ic *Collection) GetAssociations(value string) (*AssociationSet, bool)
func (*Collection) GetPage ¶
func (ic *Collection) GetPage(s *AssociationSet, value1Filter string, o SortOptions) (result TripleSet, sorted []StringTriple, totalCount int)
GetPage runs one Sort and returns both views of the page: the unordered TripleSet map (for the existing OneKey/OneValue2 helpers and back-compat) and the ordered, paginated slice (for clients that need a stable sequence), together with the pre-pagination total. Building both from a single Sort avoids sorting twice.
func (*Collection) GetReverseAssociations ¶
func (ic *Collection) GetReverseAssociations(value string) (*AssociationSet, bool)
func (*Collection) GetTotalEntries ¶
func (ic *Collection) GetTotalEntries() uint64
func (*Collection) GetTripleSet ¶
func (ic *Collection) GetTripleSet(s *AssociationSet, value1Filter string, o SortOptions) (result TripleSet, totalCount int)
func (*Collection) QueryTags ¶
func (ic *Collection) QueryTags(q TagQuery) (result TripleSet, sorted []StringTriple, total int, found bool)
QueryTags resolves the include/exclude set algebra internally and returns a paginated result: the unordered TripleSet, the ordered+paged slice, and the pre-pagination total, plus whether the seed existed. The intermediate association trees never leave tiedb.
func (*Collection) SetBlobPolicy ¶
func (ic *Collection) SetBlobPolicy(p *BlobPolicy)
SetBlobPolicy installs a whole-value blob policy on this collection and allocates the backing hash store. Pass nil to keep the trie-only behavior. See [BlobPolicy]. Call before values are inserted.
func (*Collection) SetReverseRelations ¶
func (ic *Collection) SetReverseRelations(relations []string)
SetReverseRelations restricts which relations (value1) this collection indexes in reverse. Pass nil to index every relation (the default). Call before adding triples; it does not rebuild reverse indexes for triples already inserted.
func (*Collection) SetValues ¶
func (ic *Collection) SetValues(key string, value1 string, values []string)
SetValues makes (key, value1) hold exactly the given values: it removes every existing value2 for the relation and adds each of values. This is the multi-valued generalization of SimpleUpdate — the server-side "replace this relation" primitive, so clients no longer Get-then-Delete-each-then-Add. Passing an empty values slice clears the relation.
func (*Collection) SimpleUpdate ¶
func (ic *Collection) SimpleUpdate(key string, value1 string, newValue2 string, addOnFail bool) (string, bool)
SimpleUpdate makes a scalar (single-valued) field equal to newValue2: it removes every existing value2 for (key, value1) and adds newValue2. When the field does not yet exist it adds newValue2 only if addOnFail is set. Use this for fields that are meant to hold exactly one value.
func (*Collection) Sort ¶
func (ic *Collection) Sort(tree *AssociationSet, value1Filter string, o SortOptions) (sorted []StringTriple, totalCount int)
func (*Collection) Sync ¶
func (ic *Collection) Sync()
func (*Collection) UpdateAdd ¶
func (ic *Collection) UpdateAdd(key string, value1 string, value2 string, newValue2 string) (string, bool)
UpdateAdd replaces value2 with newValue2, adding newValue2 even when the original (key, value1, value2) did not exist. It always succeeds; the message notes when a fallback add was used instead of an update.
type CollectionKey ¶
type FileIndexer ¶
type FileIndexer interface {
// contains filtered or unexported methods
}
type RawDataEntry ¶
type RawDataEntry struct {
Position int64
Data [ENTRY_SIZE]byte
}
type ReadRequest ¶
type Row ¶
Row is the flat, language-neutral result unit that crosses the wire. It groups one key's triples by relation: Attributes maps a relation (value1) to all its values (value2). A client reads row.Attributes["tag"] directly — no nested-map navigation or callbacks. TripleSet stays internal to the engine.
func RowsFromSorted ¶
func RowsFromSorted(sorted []StringTriple) []Row
RowsFromSorted folds an ordered []StringTriple into []Row, preserving the first-seen key order (the slice is already sorted/paginated by Sort). Triples for the same key coalesce into one Row; values under a relation keep their order of appearance.
type SortOptions ¶
type SortOptions struct {
Offset int
Limit int
SortBy string // Value1 to sort by
// SortByValue orders matched keys by the VALUE each key holds under this
// relation (a forward lookup per key), rather than by the matched triple.
// Empty means no value-based ordering. Example: "gendb-imported-at" to sort
// tables chronologically. Multi-valued relations sort by their smallest value.
SortByValue string
// Descending reverses the final ordering (applies to any sort mode).
Descending bool
}
type StringTriple ¶
type TagQuery ¶
type TagQuery struct {
Include []string // AND across all; Include[0] is the seed set
Exclude []string // NOT any of these
Scope string // restrict to associates of this value, ignoring relation
MissingRelation string // keep only matches with NO triple under this relation
Reverse bool // seed via reverse associations (tag query) vs forward
Filter string // filter-in on value1 (relation)
Sort SortOptions // pagination (Offset/Limit/SortBy)
}
TagQuery selects entries by association membership: a match must be associated with the seed (Include[0]) and with every other Include value, and with none of the Exclude values. It expresses "things tagged with all of these but none of those" directly, so callers no longer compose raw set operations. Include and Exclude terms are matched by reverse association; Reverse also selects the seed via reverse associations (the tag-query case) rather than forward.
Scope, when set, restricts matches to the associates of that value under a different relation than the Include/Exclude terms — e.g. scope a "tag" query to a "tie-type" so only audio files are returned. Because Scope's relation differs from the query terms' relation, it cannot be an Include term (intersect keys on the full {associate, relation} pair); it is applied by matching on associate identity alone. An empty Scope means no scoping.
type TieTree ¶
type TieTree struct {
// contains filtered or unexported fields
}
TieTree is the top-level database handle: a typed, concurrency-safe map from CollectionKey to *Collection, plus the settings applied to collections it creates. The per-level entry and association indexes are separate lockedTree instances held on each Collection.
func (*TieTree) Close ¶
func (db *TieTree) Close()
Close flushes and closes every live collection's disk writer, blocking until each has drained its pending writes, synced, and closed its file handle. It is the clean-shutdown counterpart to the periodic sync in dBWriter: call it from a signal handler so a terminating server durably persists its tail of writes instead of relying on the kernel to flush the page cache. A no-op in memory-only mode (collections have no writer goroutine then).
func (*TieTree) DropCollection ¶
func (db *TieTree) DropCollection(key CollectionKey) error
DropCollection deletes a collection's entire on-disk state and forgets its in-memory index. The live writer (if any) is closed first so its fd is released before the .tie file is removed, then the collection is dropped from the map; a later GetCollection reloads it lazily from the now-absent file, yielding an empty collection. This is the destructive counterpart to the additive Add/Restore path — the whole collection is overwritten, not merged. A no-op in memory-only mode returns nil after dropping the in-memory entry.
func (*TieTree) GetCollection ¶
func (db *TieTree) GetCollection(key CollectionKey) *Collection
func (*TieTree) SetBlobPolicy ¶
func (tree *TieTree) SetBlobPolicy(p *BlobPolicy)
SetBlobPolicy sets a whole-value blob policy applied to newly created collections: matching values (e.g. content-address hashes) are stored as a single hash entry instead of being chunked into the trie. Pass nil for the default trie-only behavior. Call before collections are created; existing collections are unaffected.
func (*TieTree) SetDefaultReverseRelations ¶
SetDefaultReverseRelations restricts which relations (value1) newly created collections index in reverse. Pass nil to index every relation (the default). Call before collections are created; existing collections are unaffected.
func (*TieTree) SetReverseRelationsOverrides ¶
func (tree *TieTree) SetReverseRelationsOverrides(overrides map[CollectionKey][]string)
SetReverseRelationsOverrides pins the reverse-relation set for specific collections, overriding the default set by SetDefaultReverseRelations. Each keyed collection indexes exactly its listed relations in reverse; collections with no entry use the default. Call before collections are created; existing collections are unaffected. The reverse index is rebuilt from forward triples at load time, so a changed override takes effect after one restart.
type TripleSet ¶
func (TripleSet) ForEachKey ¶
func (TripleSet) ForEachValue1 ¶
func (TripleSet) ForEachValue2 ¶
type UniqueAssociation ¶
type UniqueValue ¶
type UniqueValue struct {
ParentId uint64
Value [SIZE_VALUE]byte
}