FinalCommander/content/entry.go
DataHoarder e1d0e27c29
All checks were successful
continuous-integration/drone/push Build is passing
Use backing database for aliases and/or access checks
2022-01-19 21:46:05 +01:00

170 lines
3.3 KiB
Go

package content
import (
"bytes"
"encoding/binary"
"fmt"
"git.gammaspectra.live/S.O.N.G/FinalCommander/utilities"
"github.com/ipfs/go-cid"
"github.com/multiformats/go-multihash"
"time"
)
// HashIdentifier Main identifier
type HashIdentifier multihash.DecodedMultihash
func (i *HashIdentifier) IsKey() bool {
return i.Code == multihash.SHA2_256
}
func (i *HashIdentifier) Encode() []byte {
b, _ := multihash.Encode(i.Digest, i.Code)
return b
}
func (i *HashIdentifier) CID() cid.Cid {
return cid.NewCidV1(cid.Raw, i.Hash())
}
func (i *HashIdentifier) Hash() multihash.Multihash {
return i.Encode()
}
func (i *HashIdentifier) Equals(o *HashIdentifier) bool {
return i.Code == o.Code && bytes.Compare(i.Digest, o.Digest) == 0
}
func NewHashIdentifierFromMultihash(mh multihash.Multihash) *HashIdentifier {
d, err := multihash.Decode(mh)
if err != nil {
return nil
}
i := HashIdentifier(*d)
return &i
}
type Entry struct {
Key HashIdentifier
Version uint64
// CheckTime indicates relative unix time entry was accessed
AccessTime int64
// CheckTime indicates next unix time a check shall be made
CheckTime int64
InvalidList []int
}
type Alias struct {
Key HashIdentifier
Identifier HashIdentifier
}
func (e *Alias) Encode() []byte {
return e.Identifier.Encode()
}
func DecodeAlias(key HashIdentifier, message []byte) *Alias {
buffer := bytes.NewBuffer(message)
read, mh, err := multihash.MHFromBytes(buffer.Bytes())
if err != nil {
return nil
}
buffer.Next(read)
if buffer.Len() != 0 { //Unknown extra data
return nil
}
return &Alias{
Key: key,
Identifier: *NewHashIdentifierFromMultihash(mh),
}
}
func (e *Entry) Encode() ([]byte, error) {
if !e.Valid() {
return nil, fmt.Errorf("invalid Entry")
}
message := &bytes.Buffer{}
buf := make([]byte, binary.MaxVarintLen64)
n := binary.PutUvarint(buf, e.Version)
_, _ = message.Write(buf[:n])
if e.Version == 0 {
n := binary.PutVarint(buf, e.AccessTime)
_, _ = message.Write(buf[:n])
n = binary.PutVarint(buf, e.CheckTime)
_, _ = message.Write(buf[:n])
message.Write(utilities.EncodeIntegerList(e.InvalidList))
}
return message.Bytes(), nil
}
func DecodeEntry(key HashIdentifier, message []byte) *Entry {
entry := Entry{
Key: key,
}
var err error
buffer := bytes.NewBuffer(message)
entry.Version, err = binary.ReadUvarint(buffer)
if err != nil {
return nil
}
if entry.Version == 0 {
entry.AccessTime, err = binary.ReadVarint(buffer)
if err != nil {
return nil
}
entry.CheckTime, err = binary.ReadVarint(buffer)
if err != nil {
return nil
}
entry.InvalidList = utilities.DecodeIntegerList(buffer.Bytes())
return &entry
}
return nil
}
func (e *Entry) UpdateAccessTime(db *Database) {
now := time.Now().UTC().Unix()
diff := e.AccessTime - now
e.AccessTime = now
if diff < 0 {
diff = -diff
}
if diff > 3600*24 { //Update max every day
_ = db.SetEntry(e)
}
}
func (e *Entry) InInvalidList(i int) bool {
for _, v := range e.InvalidList {
if i == v {
return true
}
}
return false
}
func (e *Entry) NeedsCheck() bool {
return e.CheckTime < time.Now().UTC().Unix()
}
func (e *Entry) Valid() bool {
return e.Key.IsKey() && e.AccessTime != 0 && e.CheckTime != 0
}
func (e *Entry) Multihash() multihash.Multihash {
return e.Key.Hash()
}
func (e *Entry) CID() cid.Cid {
return e.Key.CID()
}