github.com/TrueCloudLab/frostfs-api-go/v2@v2.0.0-20230228134343-196241c4e79a/object/attributes.go (about) 1 package object 2 3 import ( 4 "errors" 5 "fmt" 6 "strconv" 7 ) 8 9 // SysAttributePrefix is a prefix of key to system attribute. 10 const SysAttributePrefix = "__NEOFS__" 11 12 const ( 13 // SysAttributeUploadID marks smaller parts of a split bigger object. 14 SysAttributeUploadID = SysAttributePrefix + "UPLOAD_ID" 15 16 // SysAttributeExpEpoch tells GC to delete object after that epoch. 17 SysAttributeExpEpoch = SysAttributePrefix + "EXPIRATION_EPOCH" 18 19 // SysAttributeTickEpoch defines what epoch must produce object 20 // notification. 21 SysAttributeTickEpoch = SysAttributePrefix + "TICK_EPOCH" 22 23 // SysAttributeTickTopic defines what topic object notification 24 // must be sent to. 25 SysAttributeTickTopic = SysAttributePrefix + "TICK_TOPIC" 26 ) 27 28 // NotificationInfo groups information about object notification 29 // that can be written to object. 30 // 31 // Topic is an optional field. 32 type NotificationInfo struct { 33 epoch uint64 34 topic string 35 } 36 37 // Epoch returns object notification tick 38 // epoch. 39 func (n NotificationInfo) Epoch() uint64 { 40 return n.epoch 41 } 42 43 // SetEpoch sets object notification tick 44 // epoch. 45 func (n *NotificationInfo) SetEpoch(epoch uint64) { 46 n.epoch = epoch 47 } 48 49 // Topic return optional object notification 50 // topic. 51 func (n NotificationInfo) Topic() string { 52 return n.topic 53 } 54 55 // SetTopic sets optional object notification 56 // topic. 57 func (n *NotificationInfo) SetTopic(topic string) { 58 n.topic = topic 59 } 60 61 // WriteNotificationInfo writes NotificationInfo to the Object via attributes. Object must not be nil. 62 // 63 // Existing notification attributes are expected to be key-unique, otherwise undefined behavior. 64 func WriteNotificationInfo(o *Object, ni NotificationInfo) { 65 h := o.GetHeader() 66 if h == nil { 67 h = new(Header) 68 o.SetHeader(h) 69 } 70 71 var ( 72 attrs = h.GetAttributes() 73 74 epoch = strconv.FormatUint(ni.Epoch(), 10) 75 topic = ni.Topic() 76 77 changedEpoch bool 78 changedTopic bool 79 deleteIndex = -1 80 ) 81 82 for i := range attrs { 83 switch attrs[i].GetKey() { 84 case SysAttributeTickEpoch: 85 attrs[i].SetValue(epoch) 86 changedEpoch = true 87 case SysAttributeTickTopic: 88 changedTopic = true 89 90 if topic == "" { 91 deleteIndex = i 92 break 93 } 94 95 attrs[i].SetValue(topic) 96 } 97 98 if changedEpoch && changedTopic { 99 break 100 } 101 } 102 103 if deleteIndex != -1 { 104 // approach without allocation/waste 105 // coping works since the attributes 106 // order is not important 107 attrs[deleteIndex] = attrs[len(attrs)-1] 108 attrs = attrs[:len(attrs)-1] 109 } 110 111 if !changedEpoch { 112 index := len(attrs) 113 attrs = append(attrs, Attribute{}) 114 attrs[index].SetKey(SysAttributeTickEpoch) 115 attrs[index].SetValue(epoch) 116 } 117 118 if !changedTopic && topic != "" { 119 index := len(attrs) 120 attrs = append(attrs, Attribute{}) 121 attrs[index].SetKey(SysAttributeTickTopic) 122 attrs[index].SetValue(topic) 123 } 124 125 h.SetAttributes(attrs) 126 } 127 128 // ErrNotificationNotSet means that object does not have notification. 129 var ErrNotificationNotSet = errors.New("notification for object is not set") 130 131 // GetNotificationInfo looks for object notification attributes. Object must not be nil. 132 // Returns ErrNotificationNotSet if no corresponding attributes 133 // were found. 134 // 135 // Existing notification attributes are expected to be key-unique, otherwise undefined behavior. 136 func GetNotificationInfo(o *Object) (*NotificationInfo, error) { 137 var ( 138 foundEpoch bool 139 ni = new(NotificationInfo) 140 ) 141 142 for _, attr := range o.GetHeader().GetAttributes() { 143 switch key := attr.GetKey(); key { 144 case SysAttributeTickEpoch: 145 epoch, err := strconv.ParseUint(attr.GetValue(), 10, 64) 146 if err != nil { 147 return nil, fmt.Errorf("could not parse epoch: %w", err) 148 } 149 150 ni.SetEpoch(epoch) 151 152 foundEpoch = true 153 case SysAttributeTickTopic: 154 ni.SetTopic(attr.GetValue()) 155 } 156 } 157 158 if !foundEpoch { 159 return nil, ErrNotificationNotSet 160 } 161 162 return ni, nil 163 }