schema

package
v0.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 7, 2024 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddEventListener

func AddEventListener[T any](node NTNode, propName PropKey, callback T) error

AddEventListener add `callback` to the event `propKey` of `node`

func PropertySet

func PropertySet[T any](ptr *T, propName PropKey, value any) error

PropertySet is an internal function which sets the property `propName` (stored at `ptr`) to `value`

Types

type BaseNode

type BaseNode struct {
	// Self is the pointer pointing to Self.
	// Note: This is needed since golang does not have true OO.
	// For example, if NodeA inherits BaseNode and calls a BaseNode function,
	// then the BaseNode function has to access NodeA via this Self pointer.
	Self NTNode

	// Chd holds all children.
	// Since a schema tree typically only has <10 branches, an array should not hurt performance.
	// Change when there found evidences showing this is the bottleneck.
	Chd []NTNode

	// Log is the logger
	Log *log.Entry
	// contains filtered or unexported fields
}

BaseNode is the base class of NTSchema nodes. TODO: Inheritance from BaseNode is really a bad model of this thing but I cannot come up with a better one in limited time. If possible, a mixin programming model may be better. TODO: (updated) a better choice may be separate the tree node (that handles Child, Parent, etc.) and the polymorphic functional part (than handles Get, Set, Events, etc.) For WASM use in the future, we may need a list of properties. Also, add ENV for Init.

func (*BaseNode) Apply

func (n *BaseNode) Apply(matching enc.Matching) enc.Name

Apply a (variable) matching and obtain the corresponding NDN name For example, apply {"id":[]byte{"aa"}} to a node at /ndn/<id> will get /ndn/aa

func (*BaseNode) At

func (n *BaseNode) At(path enc.NamePattern) NTNode

At gets a node/subtree at a given pattern path. The path does not include the attached prefix.

func (*BaseNode) AttachedPrefix

func (n *BaseNode) AttachedPrefix() enc.Name

AttachedPrefix of the root node. Must be nil for all other nodes and before Attach.

func (*BaseNode) Child

func (n *BaseNode) Child(edge enc.ComponentPattern) NTNode

Child of given edge

func (*BaseNode) Children

func (n *BaseNode) Children() []NTNode

Children return the publicly visible children nodes of the node.

func (*BaseNode) ConstructName

func (n *BaseNode) ConstructName(matching enc.Matching, ret enc.Name) error

ConstructName is the aux function used by Apply

func (*BaseNode) Depth

func (n *BaseNode) Depth() uint

Depth of the node in the tree. It includes the attached prefix, so the root node may have a positive depth For example, if the root is attached at prefix /ndn, then the child of path /<id> from the root will have a depth=2.

func (*BaseNode) Engine

func (n *BaseNode) Engine() ndn.Engine

func (*BaseNode) Get

func (n *BaseNode) Get(propName PropKey) any

Get a property or callback event

func (*BaseNode) Init

func (n *BaseNode) Init(parent NTNode, edge enc.ComponentPattern)

Init the node

func (*BaseNode) Match

func (n *BaseNode) Match(name enc.Name) (NTNode, enc.Matching)

Match an NDN name to a (variable) matching For example, /ndn/aa may match to a node at /ndn/<id> with matching <id> = "aa"

func (*BaseNode) NodeTrait

func (n *BaseNode) NodeTrait() NTNode

NodeTrait is the type trait of NTNode

func (*BaseNode) OnAttach

func (n *BaseNode) OnAttach(path enc.NamePattern, engine ndn.Engine) error

OnAttach is called when the node is attached to an engine BaseNode will call the event set by policy

func (*BaseNode) OnDetach

func (n *BaseNode) OnDetach()

OnDetach is called when the node is detached from an engine BaseNode will call the event set by policy

func (*BaseNode) OnInterest

func (n *BaseNode) OnInterest(
	interest ndn.Interest, rawInterest enc.Wire, sigCovered enc.Wire,
	reply ndn.ReplyFunc, deadline time.Time, matching enc.Matching,
)

OnInterest is the function called when an Interest comes. A base node shouldn't receive any Interest, so drops it.

func (*BaseNode) Parent

func (n *BaseNode) Parent() NTNode

Parent of this node

func (*BaseNode) PutNode

func (n *BaseNode) PutNode(path enc.NamePattern, node NTNode) error

PutNode sets a node/subtree at a given pattern path. The path does not include the attached prefix.

func (*BaseNode) Set

func (n *BaseNode) Set(propName PropKey, value any) error

Set a property. Use Get() to update callback events.

func (*BaseNode) SetAttachedPrefix

func (n *BaseNode) SetAttachedPrefix(prefix enc.Name) error

SetAttachedPrefix sets the attached prefix of the root node.

func (*BaseNode) UpEdge

func (n *BaseNode) UpEdge() enc.ComponentPattern

UpEdge is the edge value from its parent to itself

type Context

type Context map[CtxKey]any

Context contains extra info that may be useful to an event, but not worthy to be an argument. It can also be used to pass information between chained event callbacks.

type CtxKey

type CtxKey uint64

CtxKey is the type of keys of the context.

const (
	// The following keys are used to grab extra information of the incoming packet. [TYPE]
	CkDeadline        CtxKey = 1  // Deadline is now + InterestLifetime. [time.Time]
	CkRawPacket       CtxKey = 2  // The raw Interest or Data wire. [enc.Wire]
	CkSigCovered      CtxKey = 3  // The wire covered by the signature. [enc.Wire]
	CkName            CtxKey = 4  // The name of the packet. [enc.Name]
	CkInterest        CtxKey = 5  // The Interest packet. [ndn.Interest]
	CkData            CtxKey = 6  // The Data packet. [ndn.Data]
	CkContent         CtxKey = 7  // The content of the data packet or AppParam of Interest. [enc.Wire]
	CkNackReason      CtxKey = 8  // The NackReason. Only valid when the InterestResult is NACK. [uint64]
	CkLastValidResult CtxKey = 10 // The result returned by the prev validator in the callback chain. [ValidRes]
	CkEngine          CtxKey = 20 // The engine the current node is attached to. [ndn.Engine]

	// The following keys are used to overwrite nodes' properties once
	// Not valid for incoming Interest or Data packets.
	CkCanBePrefix    CtxKey = 101 // [bool]
	CkMustBeFresh    CtxKey = 102 // [bool]
	CkForwardingHint CtxKey = 103 // [[]enc.Name]
	CkNonce          CtxKey = 104 // [time.Duration]
	CkLifetime       CtxKey = 105 // [uint64]
	CkHopLimit       CtxKey = 106 // [uint]
	CkSupressInt     CtxKey = 107 // If true, only local storage is searched. No Interest will be expressed. [bool]
	CkContentType    CtxKey = 201 // [ndn.ContentType]
	CkFreshness      CtxKey = 202 // [time.Duration]
	CkFinalBlockID   CtxKey = 203 // [enc.Component]

	// The validity period of a data in the storage produced by this node,
	// i.e. how long the local storage will serve it.
	// Should be larger than FreshnessPeriod. Not affected data fetched remotely.
	CkValidDuration CtxKey = 205 // [time.Duration]
)

type Event

type Event[T comparable] struct {
	// contains filtered or unexported fields
}

Event is a chain of callback functions for an event. The execution order is supposed to be the addition order. Note: to implement `comparable`, you need to use pointer type, like *func()

func NewEvent

func NewEvent[T comparable]() *Event[T]

NewEvent creates an event. Note that T should be *func.

func (*Event[T]) Add

func (e *Event[T]) Add(callback T)

Add a callback. Note that callback should be a *func.

func (*Event[T]) Remove

func (e *Event[T]) Remove(callback T)

Remove a callback Seems not useful at all. Do we remove it?

func (*Event[T]) Val

func (e *Event[T]) Val() []T

Val returns the value of the event. Used by nodes only.

type ExpressPoint

type ExpressPoint struct {
	BaseNode
	// contains filtered or unexported fields
}

ExpressPoint is an expressing point where an Interest is supposed to be expressed. For example, for an RDR protocol w/ metadata name being /prefix/<filename>/32=metadata/<v=version>, The node at "/prefix/<filename>/32=metadata" is an ExpressPoint, as the consumer will express an Interest of this name with CanBePrefix. The node at "/prefix/<filename>/32=metadata/<v=version>" is a LeafNode.

func (*ExpressPoint) Get

func (n *ExpressPoint) Get(propName PropKey) any

Get a property or callback event

func (*ExpressPoint) Init

func (n *ExpressPoint) Init(parent NTNode, edge enc.ComponentPattern)

func (*ExpressPoint) Need

func (n *ExpressPoint) Need(
	matching enc.Matching, name enc.Name, appParam enc.Wire, context Context,
) chan NeedResult

Need is the function to obtain the corresponding Data. May express an Interest if the Data is not stored. Name is constructed from matching if nil. If given, name must agree with matching. TODO: 1. Need we make it non-blocking and return future/channel? 2. Need we use a different type than ndn.InterestResult? 3. Need we use []byte instead of enc.Wire, given that the performance is not a big consideration here?

func (*ExpressPoint) OnInterest

func (n *ExpressPoint) OnInterest(
	interest ndn.Interest, rawInterest enc.Wire, sigCovered enc.Wire,
	reply ndn.ReplyFunc, deadline time.Time, matching enc.Matching,
)

OnInterest is the function called when an Interest comes.

func (*ExpressPoint) SearchCache

func (n *ExpressPoint) SearchCache(
	matching enc.Matching, name enc.Name, canBePrefix bool, mustBeFresh bool, context Context,
) enc.Wire

func (*ExpressPoint) Set

func (n *ExpressPoint) Set(propName PropKey, value any) error

Set a property. Use Get() to update callback events.

type LeafNode

type LeafNode struct {
	ExpressPoint
	// contains filtered or unexported fields
}

LeafNode is a leaf of the NTSchema tree, a point where Data packets can be named.

func (*LeafNode) Get

func (n *LeafNode) Get(propName PropKey) any

Get a property or callback event

func (*LeafNode) Init

func (n *LeafNode) Init(parent NTNode, edge enc.ComponentPattern)

func (*LeafNode) Provide

func (n *LeafNode) Provide(
	matching enc.Matching, name enc.Name, content enc.Wire, context Context,
) enc.Wire

Provide a Data packet with given name and content. Name is constructed from matching if nil. If given, name must agree with matching. TODO: make sure code handles when context or matching is nil.

func (*LeafNode) Set

func (n *LeafNode) Set(propName PropKey, value any) error

Set a property. Use Get() to update callback events.

type NTNode

type NTNode interface {
	// NodeTrait is the type trait of NTNode
	NodeTrait() NTNode

	// Child of given edge
	Child(edge enc.ComponentPattern) NTNode

	// Children include all children of a node
	Children() []NTNode

	// Parent of this node
	Parent() NTNode

	// UpEdge is the edge value from its parent to itself
	UpEdge() enc.ComponentPattern

	// Depth of the node in the tree.
	// It includes the attached prefix, so the root node may have a positive depth
	Depth() uint

	// Match an NDN name to a (variable) matching
	// TODO: do people like the current matching or a simpler version that makes everything into []byte?
	Match(name enc.Name) (NTNode, enc.Matching)

	// Apply a (variable) matching and obtain the corresponding NDN name
	Apply(matching enc.Matching) enc.Name

	// Get a property or callback event
	// TODO: reflection may be better than manual implementation?
	Get(propName PropKey) any

	// Set a property
	// Please use Get to set callback event.
	// To avoid annoying type cast, consider use AddEventListener to help.
	Set(propName PropKey, value any) error

	// ConstructName is the aux function used by Apply
	ConstructName(matching enc.Matching, ret enc.Name) error

	// OnInterest is the callback function when there is an incoming Interest.
	OnInterest(interest ndn.Interest, rawInterest enc.Wire, sigCovered enc.Wire,
		reply ndn.ReplyFunc, deadline time.Time, matching enc.Matching)

	// OnAttach is called when the node is attached to an engine
	OnAttach(path enc.NamePattern, engine ndn.Engine) error

	// OnDetach is called when the node is detached from an engine
	OnDetach()

	// At gets a node/subtree at a given pattern path. The path does not include the attached prefix.
	At(path enc.NamePattern) NTNode

	// PutNode puts a node/subtree at a given pattern path. The path does not include the attached prefix.
	// The path must not be put with an existing node.
	// The node will be initialized after PutNode.
	// Note: the correct sig of this func should be Put[T NTNode](path), but golang provents this.
	PutNode(path enc.NamePattern, node NTNode) error

	// Init initializes a node with a specified parent and edge
	// This is the first part where one can modify the properties of the node.
	// It acts as the constructor, so the properties set here are the default values, and will be
	// overwriten by the policies' apply().
	Init(parent NTNode, edge enc.ComponentPattern)

	// AttachedPrefix returns the attached prefix if this node is the root of a schema tree.
	// Return nil otherwise.
	AttachedPrefix() enc.Name

	// SetAttachedPrefix set the attached prefix if the node is the root of a schema tree.
	SetAttachedPrefix(enc.Name) error
}

NTNode represents a node (subtree) of NTSchema. See comments for NTPolicy below for more details TODO: See also BaseNode for TODO points

type NTPolicy

type NTPolicy interface {
	// PolicyTrait is the type trait of NTPolicy
	PolicyTrait() NTPolicy

	// Apply the policy at a node (subtree). May modify the children of the given node.
	// The execution order is node.Init() -> policy.Apply() -> onAttach()
	// So the properties set here will overwrite Init()'s default values,
	// but be overwriten by onAttach().
	Apply(node NTNode) error
}

NTPolicy represents a policy, which is a modifier that sets properties and registers events during the initialization of a schema tree. The execution order is: construct the tree -> apply policies & env setup -> attach to engine (see Tree) Though policies are also considered as static knowledge (at compile time), they may be configured differently on different nodes. For example, an storage may access different folders for different instances. TODO: Design for this configuration under different environments. For example, the path to a storage, the name of the self-key, etc are knowledge specific to one instance, and thus dynamically configured. Currently I don't have an idea on the best way to separate the "statically shared part" (NTTree and the nodes) and the "dynamically configure part". (#ENV)

type NeedResult

type NeedResult struct {
	Status  ndn.InterestResult
	Content enc.Wire
}

func (NeedResult) Get

func (r NeedResult) Get() (ndn.InterestResult, enc.Wire)

type NodeGetSignerEvent

type NodeGetSignerEvent = func(enc.Matching, enc.Name, Context) ndn.Signer

NodeGetSignerEvent is the event triggered when the node needs a signer for an Interest or a Data. When there are multiple callbacks, the first non-nil signer returned is taken. Args: name matching, full name, context Context: (user defined fields only)

type NodeOnAttachEvent

type NodeOnAttachEvent = func(enc.NamePattern, ndn.Engine) error

NodeOnAttachEvent is the event triggered when attaching to an engine. This is called after the tree is built and policies are attached, so the properties modified here will overwrite the properties set before. Args: the path to this node, the engine to attach Return: a non-nil error to abort attaching. Nil when it can continue.

type NodeOnDetachEvent

type NodeOnDetachEvent = func(ndn.Engine)

NodeOnDetachEvent is the event triggered when detaching from the engine.

type NodeOnIntEvent

type NodeOnIntEvent = func(enc.Matching, enc.Wire, ndn.ReplyFunc, Context) bool

NodeOnIntEvent is the event triggered when an Interest is received. Only used by ExpressingPoint and LeafNode. Args: name matching, app params, reply, context Return: whether to abort processing (ignore events after the current one) Context: CkInterest, CkDeadline, CkRawPacket, CkSigCovered, CkName, CkEngine, CkContent(=AppParam)

type NodeSaveStorageEvent

type NodeSaveStorageEvent = func(enc.Matching, enc.Name, enc.Wire, time.Time, Context)

NodeSaveStorageEvent is the event triggered when the node stores the Data into the storage. Args: name matching, full name, raw data packet, validity time (See CkValidDuration), context Context: CkData, CkRawPacket, CkSigCovered, CkName, CkEngine, CkContent

type NodeSearchStorageEvent

type NodeSearchStorageEvent = func(enc.Matching, enc.Name, bool, bool, Context) enc.Wire

NodeSearchStorageEvent is the event triggered when the node searches the storage for data. Used by ExpressingPoint and LeafNode. Args: name matching, full name, can be prefix, must be fresh, context Return: the raw wire of Data packet. Nil if not existing Context: CkInterest, CkDeadline, CkRawPacket, CkSigCovered, CkName, CkEngine, CkContent(=AppParam)

type NodeValidateEvent

type NodeValidateEvent = func(enc.Matching, enc.Name, ndn.Signature, enc.Wire, Context) ValidRes

NodeValidateEvent is the event triggered when the node needs to validate an Interest or a Data Used by ExpressingPoint and LeafNode. Args: name matching, full name, signature, covered part, context Return: the result of current validation process Context: CkInterest/CkData, CkName, CkDeadline, CkRawPacket, CkSigCovered, CkEngine, CkContent(=Content/AppParam) CkLastValidResult (the VrResult given by the last callback in the chain)

type PropKey

type PropKey string

PropKey is the type of properties of a node. A property of a node gives the default setting of some procedure as well as event callbacks. We design in this way to support DSL and WASM in future.

const (
	// The event called when the node is attached to an engine. [NodeOnAttachEvent]
	PropOnAttach PropKey = "OnAttach"

	// The event called when the node is detached from an engine. [NodeOnDetachEvent]
	PropOnDetach PropKey = "OnDetach"

	// The event called when an ExpressingPoint or LeafNode receives an Interest. [NodeOnIntEvent]
	PropOnInterest PropKey = "OnInterest"

	// The event called when an ExpressingPoint or LeafNode verifies the signature of an Interest. [NodeValidateEvent]
	PropOnValidateInt PropKey = "OnValidateInt"

	// The event called when an ExpressingPoint or LeafNode verifies the signature of a Data. [NodeValidateEvent]
	PropOnValidateData PropKey = "OnValidateData"

	// The event called when an ExpressingPoint or LeafNode searches the storage on Need(). [NodeSearchStorageEvent]
	PropOnSearchStorage PropKey = "OnSearchStorage"

	// The event called to get a signer for an Interest
	PropOnGetIntSigner PropKey = "OnGetIntSigner"

	// The event called to get a signer for a Data
	PropOnGetDataSigner PropKey = "OnGetDataSigner"

	// The event called when an ExpressingPoint or LeafNode saves a packet into the storage.
	// The packet may be produced locally or fetched from the network.
	// TODO: Add a sign to distinguish them.
	// [NodeSaveStorageEvent]
	PropOnSaveStorage PropKey = "OnSaveStorage"

	// Default CanBePrefix for outgoing Interest. [bool]
	PropCanBePrefix PropKey = "CanBePrefix"
	// Default MustBeFresh for outgoing Interest. [bool]
	PropMustBeFresh PropKey = "MustBeFresh"
	// Default Lifetime for outgoing Interest. [time.Duration]
	PropLifetime PropKey = "Lifetime"
	// If true, only local storage is searched. No Interest will be expressed.
	// Note: may be overwritten by the Context.
	// [bool]
	PropSuppressInt PropKey = "SupressInt"

	// Default ContentType for produced Data. [ndn.ContentType]
	PropContentType PropKey = "ContentType"
	// Default FreshnessPeriod for produced Data. [time.Duration]
	PropFreshness PropKey = "Freshness"
	// See CkValidDuration. [time.Duration]
	PropValidDuration PropKey = "ValidDuration"
)

type Tree

type Tree struct {
	Root NTNode

	Engine ndn.Engine
	// contains filtered or unexported fields
}

Tree represents an NTSchema tree. It is supposed to be a static knowledge and shared by all parties in the system at compile time. The execution order: construct the tree -> apply policies & env setup -> attach to engine

func (*Tree) At

func (t *Tree) At(path enc.NamePattern) NTNode

At the path return the node. Path does not include the attached prefix.

func (*Tree) Attach

func (t *Tree) Attach(prefix enc.Name, engine ndn.Engine) error

Attach the tree to the engine at prefix

func (*Tree) Detach

func (t *Tree) Detach()

Detach the schema tree from the engine

func (*Tree) Match

func (t *Tree) Match(name enc.Name) (NTNode, enc.Matching)

Match an NDN name to a (variable) matching

func (*Tree) PutNode

func (t *Tree) PutNode(path enc.NamePattern, node NTNode) error

PutNode puts the specified node at the specified path. Path does not include the attached prefix.

func (*Tree) RLock

func (t *Tree) RLock()

RLock locks the tree for read use

func (*Tree) RUnlock

func (t *Tree) RUnlock()

RUnlock unlocks the tree locked by RLock

type ValidRes

type ValidRes = int

ValidRes is the result of data/interest signature validation, given by one validator. When there are multiple validators chained, a packet is valid when there is at least one VrPass and no VrFail.

const (
	VrFail       ValidRes = -2 // An immediate failure. Abort the validation.
	VrTimeout    ValidRes = -1 // Timeout. Abort the validation.
	VrSilence    ValidRes = 0  // The current validator cannot give any result.
	VrPass       ValidRes = 1  // The current validator approves the packet.
	VrBypass     ValidRes = 2  // An immediate success. Bypasses the rest validators that are not executed yet.
	VrCachedData ValidRes = 3  // The data is obtained from a local cache, and the signature is checked before.
)

Directories

Path Synopsis
Generated by the generator, DO NOT modify manually
Generated by the generator, DO NOT modify manually
Basic custom nodes for test and demo use.
Basic custom nodes for test and demo use.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL