2024-01-07 09:30:03 +00:00
|
|
|
package storage
|
2024-01-06 14:45:00 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"git.lumeweb.com/LumeWeb/libs5-go/encoding"
|
|
|
|
"github.com/vmihailenco/msgpack/v5"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2024-01-30 00:24:50 +00:00
|
|
|
_ msgpack.CustomDecoder = (*StorageLocationMap)(nil)
|
|
|
|
_ msgpack.CustomEncoder = (*StorageLocationMap)(nil)
|
|
|
|
_ StorageLocation = (*StorageLocationImpl)(nil)
|
|
|
|
_ SignedStorageLocation = (*SignedStorageLocationImpl)(nil)
|
2024-01-06 14:45:00 +00:00
|
|
|
)
|
|
|
|
|
2024-01-09 12:01:19 +00:00
|
|
|
type StorageLocationMap map[int]NodeStorage
|
|
|
|
type NodeStorage map[string]NodeDetailsStorage
|
|
|
|
type NodeDetailsStorage map[int]interface{}
|
|
|
|
|
2024-01-07 08:13:35 +00:00
|
|
|
func (s *StorageLocationImpl) BytesURL() string {
|
|
|
|
return s.parts[0]
|
2024-01-06 14:45:00 +00:00
|
|
|
}
|
|
|
|
|
2024-01-07 08:13:35 +00:00
|
|
|
func (s *StorageLocationImpl) OutboardBytesURL() string {
|
|
|
|
if len(s.parts) == 1 {
|
|
|
|
return s.parts[0] + ".obao"
|
2024-01-06 14:45:00 +00:00
|
|
|
}
|
2024-01-07 08:13:35 +00:00
|
|
|
return s.parts[1]
|
2024-01-06 14:45:00 +00:00
|
|
|
}
|
|
|
|
|
2024-01-07 08:13:35 +00:00
|
|
|
func (s *StorageLocationImpl) String() string {
|
|
|
|
expiryDate := time.Unix(s.expiry, 0)
|
|
|
|
return "StorageLocationImpl(" + strconv.Itoa(s.Type()) + ", " + fmt.Sprint(s.parts) + ", expiry: " + expiryDate.Format(time.RFC3339) + ")"
|
2024-01-06 14:45:00 +00:00
|
|
|
}
|
|
|
|
|
2024-01-07 08:13:35 +00:00
|
|
|
type SignedStorageLocationImpl struct {
|
2024-01-09 12:01:19 +00:00
|
|
|
nodeID *encoding.NodeId
|
2024-01-29 04:59:43 +00:00
|
|
|
location StorageLocation
|
2024-01-06 14:45:00 +00:00
|
|
|
}
|
|
|
|
|
2024-01-29 04:59:43 +00:00
|
|
|
func NewSignedStorageLocation(NodeID *encoding.NodeId, Location StorageLocation) SignedStorageLocation {
|
2024-01-07 08:13:35 +00:00
|
|
|
return &SignedStorageLocationImpl{
|
2024-01-09 12:01:19 +00:00
|
|
|
nodeID: NodeID,
|
|
|
|
location: Location,
|
2024-01-06 14:45:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-07 08:13:35 +00:00
|
|
|
func (ssl *SignedStorageLocationImpl) String() string {
|
2024-01-09 12:01:19 +00:00
|
|
|
nodeString, _ := ssl.nodeID.ToString()
|
2024-01-06 14:45:00 +00:00
|
|
|
|
|
|
|
if nodeString == "" {
|
|
|
|
nodeString = "failed to decode node id"
|
|
|
|
}
|
|
|
|
|
2024-01-09 12:01:19 +00:00
|
|
|
return "SignedStorageLocationImpl(" + ssl.location.String() + ", " + nodeString + ")"
|
2024-01-06 14:45:00 +00:00
|
|
|
}
|
|
|
|
|
2024-01-09 12:01:19 +00:00
|
|
|
func (ssl *SignedStorageLocationImpl) NodeId() *encoding.NodeId {
|
|
|
|
return ssl.nodeID
|
|
|
|
}
|
2024-01-29 04:59:43 +00:00
|
|
|
func (ssl *SignedStorageLocationImpl) Location() StorageLocation {
|
2024-01-09 13:15:13 +00:00
|
|
|
return ssl.location
|
|
|
|
}
|
2024-01-06 14:45:00 +00:00
|
|
|
|
2024-01-07 09:33:40 +00:00
|
|
|
func (s *StorageLocationMap) DecodeMsgpack(dec *msgpack.Decoder) error {
|
2024-01-06 14:45:00 +00:00
|
|
|
if *s == nil {
|
2024-01-09 20:50:14 +00:00
|
|
|
*s = make(StorageLocationMap)
|
2024-01-06 14:45:00 +00:00
|
|
|
}
|
|
|
|
|
2024-01-09 20:50:14 +00:00
|
|
|
// Decode directly into a temp map
|
|
|
|
temp := make(map[int]map[string]map[int]interface{})
|
|
|
|
err := dec.Decode(&temp)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error decoding msgpack: %w", err)
|
2024-01-06 14:45:00 +00:00
|
|
|
}
|
|
|
|
|
2024-01-09 20:50:14 +00:00
|
|
|
// Convert temp map to StorageLocationMap
|
|
|
|
for k, v := range temp {
|
|
|
|
nodeStorage, exists := (*s)[k]
|
|
|
|
if !exists {
|
|
|
|
nodeStorage = make(NodeStorage, len(v)) // preallocate if size is known
|
|
|
|
(*s)[k] = nodeStorage
|
|
|
|
}
|
|
|
|
|
|
|
|
for nk, nv := range v {
|
|
|
|
nodeDetailsStorage, exists := nodeStorage[nk]
|
|
|
|
if !exists {
|
|
|
|
nodeDetailsStorage = make(NodeDetailsStorage, len(nv)) // preallocate if size is known
|
|
|
|
nodeStorage[nk] = nodeDetailsStorage
|
|
|
|
}
|
|
|
|
|
|
|
|
for ndk, ndv := range nv {
|
|
|
|
nodeDetailsStorage[ndk] = ndv
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-01-06 14:45:00 +00:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-01-07 09:33:40 +00:00
|
|
|
func (s StorageLocationMap) EncodeMsgpack(enc *msgpack.Encoder) error {
|
2024-01-06 14:45:00 +00:00
|
|
|
// Create a temporary map to hold the encoded data
|
2024-01-06 15:53:20 +00:00
|
|
|
tempMap := make(map[int]map[string]map[int]interface{})
|
2024-01-06 14:45:00 +00:00
|
|
|
|
|
|
|
// Populate the temporary map with data from storageLocationMap
|
|
|
|
for storageKey, nodeStorages := range s {
|
2024-01-06 15:53:20 +00:00
|
|
|
tempNodeStorages := make(map[string]map[int]interface{})
|
2024-01-06 14:45:00 +00:00
|
|
|
for nodeId, nodeDetails := range nodeStorages {
|
|
|
|
tempNodeStorages[nodeId] = nodeDetails
|
|
|
|
}
|
|
|
|
tempMap[storageKey] = tempNodeStorages
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode the temporary map using MessagePack
|
|
|
|
return enc.Encode(tempMap)
|
|
|
|
}
|
|
|
|
|
2024-01-07 09:33:40 +00:00
|
|
|
func NewStorageLocationMap() StorageLocationMap {
|
|
|
|
return StorageLocationMap{}
|
2024-01-06 14:45:00 +00:00
|
|
|
}
|
2024-01-09 12:00:00 +00:00
|
|
|
|
2024-01-29 04:59:43 +00:00
|
|
|
type StorageLocationProvider interface {
|
|
|
|
Start() error
|
|
|
|
Next() (SignedStorageLocation, error)
|
|
|
|
Upvote(uri SignedStorageLocation) error
|
|
|
|
Downvote(uri SignedStorageLocation) error
|
|
|
|
}
|