2023-06-23 20:56:09 -06:00
|
|
|
package graphvent
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
)
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
type ListenerExt struct {
|
2023-07-26 11:56:10 -06:00
|
|
|
Buffer int
|
2023-07-26 15:08:14 -06:00
|
|
|
Chan chan Signal
|
2023-07-24 16:04:56 -06:00
|
|
|
}
|
|
|
|
|
2023-07-26 11:56:10 -06:00
|
|
|
func NewListenerExt(buffer int) *ListenerExt {
|
|
|
|
return &ListenerExt{
|
|
|
|
Buffer: buffer,
|
2023-07-26 15:08:14 -06:00
|
|
|
Chan: make(chan Signal, buffer),
|
2023-07-24 16:04:56 -06:00
|
|
|
}
|
2023-06-23 22:19:43 -06:00
|
|
|
}
|
|
|
|
|
2023-07-26 11:56:10 -06:00
|
|
|
func LoadListenerExt(ctx *Context, data []byte) (Extension, error) {
|
|
|
|
var j int
|
|
|
|
err := json.Unmarshal(data, &j)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return NewListenerExt(j), nil
|
|
|
|
}
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
const ListenerExtType = ExtType("LISTENER")
|
2023-07-26 15:40:33 -06:00
|
|
|
func (listener *ListenerExt) Type() ExtType {
|
2023-07-25 21:43:15 -06:00
|
|
|
return ListenerExtType
|
2023-06-23 22:19:43 -06:00
|
|
|
}
|
|
|
|
|
2023-07-27 15:27:14 -06:00
|
|
|
func (ext *ListenerExt) Process(ctx *Context, princ_id NodeID, node *Node, signal Signal) {
|
|
|
|
ctx.Log.Logf("signal", "LISTENER_PROCESS: %s - %+v", node.ID, signal)
|
2023-07-25 21:43:15 -06:00
|
|
|
select {
|
|
|
|
case ext.Chan <- signal:
|
|
|
|
default:
|
2023-07-27 15:27:14 -06:00
|
|
|
ctx.Log.Logf("listener", "LISTENER_OVERFLOW: %s", node.ID)
|
2023-07-25 21:43:15 -06:00
|
|
|
}
|
2023-07-27 15:27:14 -06:00
|
|
|
return
|
2023-07-09 14:30:30 -06:00
|
|
|
}
|
|
|
|
|
2023-07-26 15:40:33 -06:00
|
|
|
func (ext *ListenerExt) Serialize() ([]byte, error) {
|
2023-07-26 11:56:10 -06:00
|
|
|
return json.MarshalIndent(ext.Buffer, "", " ")
|
2023-07-24 16:04:56 -06:00
|
|
|
}
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
type LockableExt struct {
|
2023-07-27 15:27:14 -06:00
|
|
|
Owner *NodeID `json:"owner"`
|
|
|
|
Requirements []NodeID `json:"requirements"`
|
|
|
|
Dependencies []NodeID `json:"dependencies"`
|
|
|
|
LocksHeld map[NodeID]*NodeID `json:"locks_held"`
|
2023-06-23 20:56:09 -06:00
|
|
|
}
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
const LockableExtType = ExtType("LOCKABLE")
|
|
|
|
func (ext *LockableExt) Type() ExtType {
|
|
|
|
return LockableExtType
|
2023-06-28 21:49:23 -06:00
|
|
|
}
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
func (ext *LockableExt) Serialize() ([]byte, error) {
|
2023-07-27 15:27:14 -06:00
|
|
|
return json.MarshalIndent(ext, "", " ")
|
2023-07-26 00:18:11 -06:00
|
|
|
}
|
|
|
|
|
2023-07-27 15:27:14 -06:00
|
|
|
func NewLockableExt(owner *NodeID, requirements []NodeID, dependencies []NodeID, locks_held map[NodeID]*NodeID) *LockableExt {
|
2023-07-26 11:56:10 -06:00
|
|
|
if locks_held == nil {
|
2023-07-27 15:27:14 -06:00
|
|
|
locks_held = map[NodeID]*NodeID{}
|
2023-07-26 11:56:10 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return &LockableExt{
|
|
|
|
Owner: owner,
|
|
|
|
Requirements: requirements,
|
|
|
|
Dependencies: dependencies,
|
|
|
|
LocksHeld: locks_held,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-26 00:18:11 -06:00
|
|
|
func LoadLockableExt(ctx *Context, data []byte) (Extension, error) {
|
2023-07-27 15:27:14 -06:00
|
|
|
var ext LockableExt
|
|
|
|
err := json.Unmarshal(data, &ext)
|
2023-07-26 00:18:11 -06:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2023-06-23 20:56:09 -06:00
|
|
|
}
|
|
|
|
|
2023-07-27 15:27:14 -06:00
|
|
|
ctx.Log.Logf("db", "DB_LOADING_LOCKABLE_EXT_JSON: %+v", ext)
|
2023-06-23 20:56:09 -06:00
|
|
|
|
2023-07-27 15:27:14 -06:00
|
|
|
return &ext, nil
|
2023-06-30 13:25:35 -06:00
|
|
|
}
|
|
|
|
|
2023-07-27 15:27:14 -06:00
|
|
|
func (ext *LockableExt) Process(ctx *Context, source NodeID, node *Node, signal Signal) {
|
|
|
|
ctx.Log.Logf("signal", "LOCKABLE_PROCESS: %s", node.ID)
|
2023-07-22 20:21:17 -06:00
|
|
|
|
|
|
|
switch signal.Direction() {
|
|
|
|
case Up:
|
2023-07-27 12:20:49 -06:00
|
|
|
owner_sent := false
|
|
|
|
for _, dependency := range(ext.Dependencies) {
|
2023-07-27 16:13:43 -06:00
|
|
|
err := ctx.Send(node.ID, dependency, signal)
|
2023-07-27 12:20:49 -06:00
|
|
|
if err != nil {
|
2023-07-27 15:27:14 -06:00
|
|
|
ctx.Log.Logf("signal", "LOCKABLE_SIGNAL_ERR: %s->%s - %e", node.ID, dependency, err)
|
2023-07-09 14:30:30 -06:00
|
|
|
}
|
2023-07-27 15:27:14 -06:00
|
|
|
|
2023-07-27 12:20:49 -06:00
|
|
|
if ext.Owner != nil {
|
2023-07-27 15:27:14 -06:00
|
|
|
if dependency == *ext.Owner {
|
2023-07-27 12:20:49 -06:00
|
|
|
owner_sent = true
|
2023-07-22 20:21:17 -06:00
|
|
|
}
|
|
|
|
}
|
2023-07-27 12:20:49 -06:00
|
|
|
}
|
2023-07-27 15:27:14 -06:00
|
|
|
|
2023-07-27 12:20:49 -06:00
|
|
|
if ext.Owner != nil && owner_sent == false {
|
2023-07-27 15:27:14 -06:00
|
|
|
if *ext.Owner != node.ID {
|
2023-07-27 16:13:43 -06:00
|
|
|
err := ctx.Send(node.ID, *ext.Owner, signal)
|
2023-07-09 14:30:30 -06:00
|
|
|
if err != nil {
|
2023-07-27 15:27:14 -06:00
|
|
|
ctx.Log.Logf("signal", "LOCKABLE_SIGNAL_ERR: %s->%s - %e", node.ID, *ext.Owner, err)
|
2023-07-09 14:30:30 -06:00
|
|
|
}
|
|
|
|
}
|
2023-07-27 12:20:49 -06:00
|
|
|
}
|
|
|
|
case Down:
|
|
|
|
for _, requirement := range(ext.Requirements) {
|
2023-07-27 16:13:43 -06:00
|
|
|
err := ctx.Send(node.ID, requirement, signal)
|
2023-07-27 12:20:49 -06:00
|
|
|
if err != nil {
|
2023-07-27 15:27:14 -06:00
|
|
|
ctx.Log.Logf("signal", "LOCKABLE_SIGNAL_ERR: %s->%s - %e", node.ID, requirement, err)
|
2023-07-27 12:20:49 -06:00
|
|
|
}
|
|
|
|
}
|
2023-07-22 20:21:17 -06:00
|
|
|
case Direct:
|
|
|
|
default:
|
2023-07-24 17:07:27 -06:00
|
|
|
}
|
2023-07-25 21:43:15 -06:00
|
|
|
}
|
|
|
|
|
2023-07-27 15:27:14 -06:00
|
|
|
func (ext *LockableExt) RecordUnlock(node NodeID) *NodeID {
|
|
|
|
last_owner, exists := ext.LocksHeld[node]
|
2023-07-25 21:43:15 -06:00
|
|
|
if exists == false {
|
|
|
|
panic("Attempted to take a get the original lock holder of a lockable we don't own")
|
|
|
|
}
|
2023-07-27 15:27:14 -06:00
|
|
|
delete(ext.LocksHeld, node)
|
2023-07-25 21:43:15 -06:00
|
|
|
return last_owner
|
|
|
|
}
|
|
|
|
|
2023-07-27 15:27:14 -06:00
|
|
|
func (ext *LockableExt) RecordLock(node NodeID, last_owner *NodeID) {
|
|
|
|
_, exists := ext.LocksHeld[node]
|
2023-07-25 21:43:15 -06:00
|
|
|
if exists == true {
|
|
|
|
panic("Attempted to lock a lockable we're already holding(lock cycle)")
|
|
|
|
}
|
2023-07-27 15:27:14 -06:00
|
|
|
ext.LocksHeld[node] = last_owner
|
2023-06-23 20:56:09 -06:00
|
|
|
}
|
|
|
|
|
2023-07-26 00:18:11 -06:00
|
|
|
func SaveNode(node *Node) string {
|
|
|
|
str := ""
|
|
|
|
if node != nil {
|
|
|
|
str = node.ID.String()
|
|
|
|
}
|
|
|
|
return str
|
|
|
|
}
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
func RestoreNode(ctx *Context, id_str string) (*Node, error) {
|
2023-07-26 15:40:33 -06:00
|
|
|
if id_str == "" {
|
|
|
|
return nil, nil
|
|
|
|
}
|
2023-07-25 21:43:15 -06:00
|
|
|
id, err := ParseID(id_str)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2023-06-28 21:49:23 -06:00
|
|
|
}
|
2023-07-25 21:43:15 -06:00
|
|
|
|
|
|
|
return LoadNode(ctx, id)
|
2023-07-09 14:30:30 -06:00
|
|
|
}
|
2023-06-28 21:49:23 -06:00
|
|
|
|
2023-07-26 00:18:11 -06:00
|
|
|
func SaveNodeMap(nodes NodeMap) map[string]string {
|
|
|
|
m := map[string]string{}
|
|
|
|
for id, node := range(nodes) {
|
|
|
|
m[id.String()] = SaveNode(node)
|
|
|
|
}
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
func RestoreNodeMap(ctx *Context, ids map[string]string) (NodeMap, error) {
|
|
|
|
nodes := NodeMap{}
|
|
|
|
for id_str_1, id_str_2 := range(ids) {
|
|
|
|
id_1, err := ParseID(id_str_1)
|
2023-07-21 00:02:53 -06:00
|
|
|
if err != nil {
|
2023-07-25 21:43:15 -06:00
|
|
|
return nil, err
|
2023-06-30 13:25:35 -06:00
|
|
|
}
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
node_1, err := LoadNode(ctx, id_1)
|
2023-06-28 21:49:23 -06:00
|
|
|
if err != nil {
|
2023-07-25 21:43:15 -06:00
|
|
|
return nil, err
|
2023-06-28 21:49:23 -06:00
|
|
|
}
|
2023-07-25 21:43:15 -06:00
|
|
|
|
2023-07-26 15:40:33 -06:00
|
|
|
|
|
|
|
var node_2 *Node = nil
|
|
|
|
if id_str_2 != "" {
|
|
|
|
id_2, err := ParseID(id_str_2)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
node_2, err = LoadNode(ctx, id_2)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-07-21 00:02:53 -06:00
|
|
|
}
|
2023-07-25 21:43:15 -06:00
|
|
|
|
|
|
|
nodes[node_1.ID] = node_2
|
2023-06-28 21:49:23 -06:00
|
|
|
}
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
return nodes, nil
|
|
|
|
}
|
2023-07-09 14:30:30 -06:00
|
|
|
|
2023-07-26 00:18:11 -06:00
|
|
|
func SaveNodeList(nodes NodeMap) []string {
|
|
|
|
ids := make([]string, len(nodes))
|
|
|
|
i := 0
|
|
|
|
for id, _ := range(nodes) {
|
|
|
|
ids[i] = id.String()
|
|
|
|
i += 1
|
|
|
|
}
|
|
|
|
|
|
|
|
return ids
|
|
|
|
}
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
func RestoreNodeList(ctx *Context, ids []string) (NodeMap, error) {
|
|
|
|
nodes := NodeMap{}
|
|
|
|
|
|
|
|
for _, id_str := range(ids) {
|
|
|
|
node, err := RestoreNode(ctx, id_str)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2023-06-28 21:49:23 -06:00
|
|
|
}
|
2023-07-25 21:43:15 -06:00
|
|
|
nodes[node.ID] = node
|
2023-06-28 21:49:23 -06:00
|
|
|
}
|
|
|
|
|
2023-07-25 21:43:15 -06:00
|
|
|
return nodes, nil
|
2023-06-23 20:56:09 -06:00
|
|
|
}
|
2023-07-25 21:43:15 -06:00
|
|
|
|