|
|
@ -84,18 +84,34 @@ func (db *BadgerDB) WriteNodeInit(ctx *Context, node *Node) error {
|
|
|
|
|
|
|
|
|
|
|
|
// For each extension:
|
|
|
|
// For each extension:
|
|
|
|
for ext_type, ext := range(node.Extensions) {
|
|
|
|
for ext_type, ext := range(node.Extensions) {
|
|
|
|
// Write each extension's current value
|
|
|
|
ext_info, exists := ctx.Extensions[ext_type]
|
|
|
|
|
|
|
|
if exists == false {
|
|
|
|
|
|
|
|
return fmt.Errorf("Cannot serialize node with unknown extension %s", reflect.TypeOf(ext))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ext_value := reflect.ValueOf(ext).Elem()
|
|
|
|
ext_id := binary.BigEndian.AppendUint64(id_ser, uint64(ext_type))
|
|
|
|
ext_id := binary.BigEndian.AppendUint64(id_ser, uint64(ext_type))
|
|
|
|
written, err := SerializeValue(ctx, reflect.ValueOf(ext).Elem(), db.buffer[cur:])
|
|
|
|
|
|
|
|
|
|
|
|
// Write each field to a seperate key
|
|
|
|
|
|
|
|
for field_tag, field_info := range(ext_info.Fields) {
|
|
|
|
|
|
|
|
field_value := ext_value.FieldByIndex(field_info.Index)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
field_id := make([]byte, len(ext_id) + 8)
|
|
|
|
|
|
|
|
tmp := binary.BigEndian.AppendUint64(ext_id, uint64(GetFieldTag(string(field_tag))))
|
|
|
|
|
|
|
|
copy(field_id, tmp)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
written, err := SerializeValue(ctx, field_value, db.buffer[cur:])
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return fmt.Errorf("Extension serialize err: %s, %w", reflect.TypeOf(ext), err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
err = tx.Set(ext_id, db.buffer[cur:cur+written])
|
|
|
|
|
|
|
|
|
|
|
|
err = tx.Set(field_id, db.buffer[cur:cur+written])
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return fmt.Errorf("Extension set err: %s, %w", reflect.TypeOf(ext), err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cur += written
|
|
|
|
cur += written
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -127,24 +143,44 @@ func (db *BadgerDB) WriteNodeChanges(ctx *Context, node *Node, changes map[ExtTy
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// For each ext in changes
|
|
|
|
// For each ext in changes
|
|
|
|
for ext_type := range(changes) {
|
|
|
|
for ext_type, changes := range(changes) {
|
|
|
|
// Write each ext
|
|
|
|
ext_info, exists := ctx.Extensions[ext_type]
|
|
|
|
|
|
|
|
if exists == false {
|
|
|
|
|
|
|
|
return fmt.Errorf("%s is not an extension in ctx", ext_type)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ext, exists := node.Extensions[ext_type]
|
|
|
|
ext, exists := node.Extensions[ext_type]
|
|
|
|
if exists == false {
|
|
|
|
if exists == false {
|
|
|
|
return fmt.Errorf("%s is not an extension in %s", ext_type, node.ID)
|
|
|
|
return fmt.Errorf("%s is not an extension in %s", ext_type, node.ID)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ext_id := binary.BigEndian.AppendUint64(id_bytes[:], uint64(ext_type))
|
|
|
|
ext_id := binary.BigEndian.AppendUint64(id_bytes[:], uint64(ext_type))
|
|
|
|
written, err := SerializeValue(ctx, reflect.ValueOf(ext).Elem(), db.buffer[cur:])
|
|
|
|
ext_value := reflect.ValueOf(ext)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Write each field
|
|
|
|
|
|
|
|
for _, tag := range(changes) {
|
|
|
|
|
|
|
|
field_info, exists := ext_info.Fields[tag]
|
|
|
|
|
|
|
|
if exists == false {
|
|
|
|
|
|
|
|
return fmt.Errorf("Cannot serialize field %s of extension %s, does not exist", tag, ext_type)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
field_value := ext_value.FieldByIndex(field_info.Index)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
field_id := make([]byte, len(ext_id) + 8)
|
|
|
|
|
|
|
|
tmp := binary.BigEndian.AppendUint64(ext_id, uint64(GetFieldTag(string(tag))))
|
|
|
|
|
|
|
|
copy(field_id, tmp)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
written, err := SerializeValue(ctx, field_value, db.buffer[cur:])
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Extension serialize err: %s, %w", reflect.TypeOf(ext), err)
|
|
|
|
return fmt.Errorf("Extension serialize err: %s, %w", reflect.TypeOf(ext), err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
err = tx.Set(ext_id, db.buffer[cur:cur+written])
|
|
|
|
err = tx.Set(field_id, db.buffer[cur:cur+written])
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("Extension set err: %s, %w", reflect.TypeOf(ext), err)
|
|
|
|
return fmt.Errorf("Extension set err: %s, %w", reflect.TypeOf(ext), err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cur += written
|
|
|
|
cur += written
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -156,13 +192,13 @@ func (db *BadgerDB) LoadNode(ctx *Context, id NodeID) (*Node, error) {
|
|
|
|
// Get the base key bytes
|
|
|
|
// Get the base key bytes
|
|
|
|
id_ser, err := id.MarshalBinary()
|
|
|
|
id_ser, err := id.MarshalBinary()
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return fmt.Errorf("Failed to serialize node_id: %w", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Get the node value
|
|
|
|
// Get the node value
|
|
|
|
node_item, err := tx.Get(id_ser)
|
|
|
|
node_item, err := tx.Get(id_ser)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return fmt.Errorf("Failed to get node_item: %w", NodeNotFoundError)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
err = node_item.Value(func(val []byte) error {
|
|
|
|
err = node_item.Value(func(val []byte) error {
|
|
|
@ -179,14 +215,14 @@ func (db *BadgerDB) LoadNode(ctx *Context, id NodeID) (*Node, error) {
|
|
|
|
sigqueue_id := append(id_ser, []byte(" - SIGQUEUE")...)
|
|
|
|
sigqueue_id := append(id_ser, []byte(" - SIGQUEUE")...)
|
|
|
|
sigqueue_item, err := tx.Get(sigqueue_id)
|
|
|
|
sigqueue_item, err := tx.Get(sigqueue_id)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return fmt.Errorf("Failed to get sigqueue_id: %w", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
err = sigqueue_item.Value(func(val []byte) error {
|
|
|
|
err = sigqueue_item.Value(func(val []byte) error {
|
|
|
|
node.SignalQueue, err = Deserialize[[]QueuedSignal](ctx, val)
|
|
|
|
node.SignalQueue, err = Deserialize[[]QueuedSignal](ctx, val)
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
})
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return fmt.Errorf("Failed to deserialize []QueuedSignal for %s: %w", id, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Get the extension list
|
|
|
|
// Get the extension list
|
|
|
@ -205,35 +241,34 @@ func (db *BadgerDB) LoadNode(ctx *Context, id NodeID) (*Node, error) {
|
|
|
|
// Get the extensions
|
|
|
|
// Get the extensions
|
|
|
|
for _, ext_type := range(ext_list) {
|
|
|
|
for _, ext_type := range(ext_list) {
|
|
|
|
ext_id := binary.BigEndian.AppendUint64(id_ser, uint64(ext_type))
|
|
|
|
ext_id := binary.BigEndian.AppendUint64(id_ser, uint64(ext_type))
|
|
|
|
ext_item, err := tx.Get(ext_id)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ext_info, exists := ctx.Extensions[ext_type]
|
|
|
|
ext_info, exists := ctx.Extensions[ext_type]
|
|
|
|
if exists == false {
|
|
|
|
if exists == false {
|
|
|
|
return fmt.Errorf("Extension %s not in context", ext_type)
|
|
|
|
return fmt.Errorf("Extension %s not in context", ext_type)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var ext Extension
|
|
|
|
ext := reflect.New(ext_info.Type)
|
|
|
|
var ok bool
|
|
|
|
for field_tag, field_info := range(ext_info.Fields) {
|
|
|
|
err = ext_item.Value(func(val []byte) error {
|
|
|
|
field_id := binary.BigEndian.AppendUint64(ext_id, uint64(GetFieldTag(string(field_tag))))
|
|
|
|
value, _, err := DeserializeValue(ctx, val, ext_info.Type)
|
|
|
|
field_item, err := tx.Get(field_id)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return fmt.Errorf("Failed to find key for %s:%s(%x) - %w", ext_type, field_tag, field_id, err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
err = field_item.Value(func(val []byte) error {
|
|
|
|
|
|
|
|
value, _, err := DeserializeValue(ctx, val, field_info.Type)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ext, ok = value.Addr().Interface().(Extension)
|
|
|
|
ext.Elem().FieldByIndex(field_info.Index).Set(value)
|
|
|
|
if ok == false {
|
|
|
|
|
|
|
|
return fmt.Errorf("Parsed value %+v is not extension", value.Type())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
node.Extensions[ext_type] = ext
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
node.Extensions[ext_type] = ext.Interface().(Extension)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|