forked from TrueCloudLab/frostfs-api-go
[#372] object: Add object notification attributes
Also, add functions for parsing and setting object notifications. Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>support/v2.15
parent
aabc2dd927
commit
4007aa86f4
|
@ -1,5 +1,11 @@
|
|||
package object
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// SysAttributePrefix is a prefix of key to system attribute.
|
||||
const SysAttributePrefix = "__NEOFS__"
|
||||
|
||||
|
@ -9,4 +15,155 @@ const (
|
|||
|
||||
// SysAttributeExpEpoch tells GC to delete object after that epoch.
|
||||
SysAttributeExpEpoch = SysAttributePrefix + "EXPIRATION_EPOCH"
|
||||
|
||||
// SysAttributeTickEpoch defines what epoch must produce object
|
||||
// notification.
|
||||
SysAttributeTickEpoch = SysAttributePrefix + "TICK_EPOCH"
|
||||
|
||||
// SysAttributeTickTopic defines what topic object notification
|
||||
// must be sent to.
|
||||
SysAttributeTickTopic = SysAttributePrefix + "TICK_TOPIC"
|
||||
)
|
||||
|
||||
// NotificationInfo groups information about object notification
|
||||
// that can be written to object.
|
||||
//
|
||||
// Topic is an optional field.
|
||||
type NotificationInfo struct {
|
||||
epoch uint64
|
||||
topic string
|
||||
}
|
||||
|
||||
// Epoch returns object notification tick
|
||||
// epoch.
|
||||
func (n NotificationInfo) Epoch() uint64 {
|
||||
return n.epoch
|
||||
}
|
||||
|
||||
// SetEpoch sets object notification tick
|
||||
// epoch.
|
||||
func (n *NotificationInfo) SetEpoch(epoch uint64) {
|
||||
n.epoch = epoch
|
||||
}
|
||||
|
||||
// Topic return optional object notification
|
||||
// topic.
|
||||
func (n NotificationInfo) Topic() string {
|
||||
return n.topic
|
||||
}
|
||||
|
||||
// SetTopic sets optional object notification
|
||||
// topic.
|
||||
func (n *NotificationInfo) SetTopic(topic string) {
|
||||
n.topic = topic
|
||||
}
|
||||
|
||||
// WriteNotificationInfo writes NotificationInfo to the Object via attributes. Object must not be nil.
|
||||
//
|
||||
// Existing notification attributes are expected to be key-unique, otherwise undefined behavior.
|
||||
func WriteNotificationInfo(o *Object, ni NotificationInfo) {
|
||||
h := o.GetHeader()
|
||||
if h == nil {
|
||||
h = new(Header)
|
||||
o.SetHeader(h)
|
||||
}
|
||||
|
||||
var (
|
||||
attrs = h.GetAttributes()
|
||||
|
||||
epoch = strconv.FormatUint(ni.Epoch(), 10)
|
||||
topic = ni.Topic()
|
||||
|
||||
changedEpoch bool
|
||||
changedTopic bool
|
||||
deleteIndex = -1
|
||||
)
|
||||
|
||||
for i := range attrs {
|
||||
switch attrs[i].GetKey() {
|
||||
case SysAttributeTickEpoch:
|
||||
attrs[i].SetValue(epoch)
|
||||
changedEpoch = true
|
||||
case SysAttributeTickTopic:
|
||||
changedTopic = true
|
||||
|
||||
if topic == "" {
|
||||
deleteIndex = i
|
||||
break
|
||||
}
|
||||
|
||||
attrs[i].SetValue(topic)
|
||||
}
|
||||
|
||||
if changedEpoch && changedTopic {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if deleteIndex != -1 {
|
||||
// approach without allocation/waste
|
||||
// coping works since the attributes
|
||||
// order is not important
|
||||
attrs[deleteIndex] = attrs[len(attrs)-1]
|
||||
attrs = attrs[:len(attrs)-1]
|
||||
}
|
||||
|
||||
notifyAttrs := make([]*Attribute, 0, 2)
|
||||
|
||||
if !changedEpoch {
|
||||
eAttr := new(Attribute)
|
||||
eAttr.SetKey(SysAttributeTickEpoch)
|
||||
eAttr.SetValue(epoch)
|
||||
|
||||
notifyAttrs = append(notifyAttrs, eAttr)
|
||||
}
|
||||
|
||||
if !changedTopic && topic != "" {
|
||||
tAttr := new(Attribute)
|
||||
tAttr.SetKey(SysAttributeTickTopic)
|
||||
tAttr.SetValue(topic)
|
||||
|
||||
notifyAttrs = append(notifyAttrs, tAttr)
|
||||
}
|
||||
|
||||
attrs = append(attrs, notifyAttrs...)
|
||||
|
||||
h.SetAttributes(attrs)
|
||||
}
|
||||
|
||||
// ErrNotificationNotSet means that object does not have notification.
|
||||
var ErrNotificationNotSet = errors.New("notification for object is not set")
|
||||
|
||||
// GetNotificationInfo looks for object notification attributes. Object must not be nil.
|
||||
// Returns ErrNotificationNotSet if no corresponding attributes
|
||||
// were found.
|
||||
//
|
||||
// Existing notification attributes are expected to be key-unique, otherwise undefined behavior.
|
||||
func GetNotificationInfo(o *Object) (*NotificationInfo, error) {
|
||||
var (
|
||||
foundEpoch bool
|
||||
ni = new(NotificationInfo)
|
||||
)
|
||||
|
||||
for _, attr := range o.GetHeader().GetAttributes() {
|
||||
switch key := attr.GetKey(); key {
|
||||
case SysAttributeTickEpoch:
|
||||
epoch, err := strconv.ParseUint(attr.GetValue(), 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse epoch: %w", err)
|
||||
}
|
||||
|
||||
ni.SetEpoch(epoch)
|
||||
|
||||
foundEpoch = true
|
||||
case SysAttributeTickTopic:
|
||||
ni.SetTopic(attr.GetValue())
|
||||
}
|
||||
}
|
||||
|
||||
if !foundEpoch {
|
||||
return nil, ErrNotificationNotSet
|
||||
}
|
||||
|
||||
return ni, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue