github.com/TrueCloudLab/frostfs-api-go/v2@v2.0.0-20230228134343-196241c4e79a/object/lock.go (about) 1 package object 2 3 import ( 4 "errors" 5 "fmt" 6 7 lock "github.com/TrueCloudLab/frostfs-api-go/v2/lock/grpc" 8 "github.com/TrueCloudLab/frostfs-api-go/v2/refs" 9 refsGRPC "github.com/TrueCloudLab/frostfs-api-go/v2/refs/grpc" 10 "github.com/TrueCloudLab/frostfs-api-go/v2/rpc/grpc" 11 "github.com/TrueCloudLab/frostfs-api-go/v2/rpc/message" 12 "github.com/TrueCloudLab/frostfs-api-go/v2/util/proto" 13 ) 14 15 // Lock represents object Lock message from NeoFS API V2 protocol. 16 type Lock struct { 17 members []refs.ObjectID 18 } 19 20 // NumberOfMembers returns length of lock list. 21 func (x *Lock) NumberOfMembers() int { 22 if x != nil { 23 return len(x.members) 24 } 25 26 return 0 27 } 28 29 // IterateMembers passes members of the lock list to f. 30 func (x *Lock) IterateMembers(f func(refs.ObjectID)) { 31 if x != nil { 32 for i := range x.members { 33 f(x.members[i]) 34 } 35 } 36 } 37 38 // SetMembers sets list of locked members. 39 // Arg must not be mutated for the duration of the Lock. 40 func (x *Lock) SetMembers(ids []refs.ObjectID) { 41 x.members = ids 42 } 43 44 const ( 45 _ = iota 46 fNumLockMembers 47 ) 48 49 // StableMarshal encodes the Lock into Protocol Buffers binary format 50 // with direct field order. 51 func (x *Lock) StableMarshal(buf []byte) []byte { 52 if x == nil || len(x.members) == 0 { 53 return []byte{} 54 } 55 56 if buf == nil { 57 buf = make([]byte, x.StableSize()) 58 } 59 60 var offset int 61 62 for i := range x.members { 63 offset += proto.NestedStructureMarshal(fNumLockMembers, buf[offset:], &x.members[i]) 64 } 65 66 return buf 67 } 68 69 // StableSize size of the buffer required to write the Lock in Protocol Buffers 70 // binary format. 71 func (x *Lock) StableSize() (sz int) { 72 if x != nil { 73 for i := range x.members { 74 sz += proto.NestedStructureSize(fNumLockMembers, &x.members[i]) 75 } 76 } 77 78 return 79 } 80 81 // Unmarshal decodes the Lock from its Protocol Buffers binary format. 82 func (x *Lock) Unmarshal(data []byte) error { 83 return message.Unmarshal(x, data, new(lock.Lock)) 84 } 85 86 func (x *Lock) ToGRPCMessage() grpc.Message { 87 var m *lock.Lock 88 89 if x != nil { 90 m = new(lock.Lock) 91 92 var members []*refsGRPC.ObjectID 93 94 if x.members != nil { 95 members = make([]*refsGRPC.ObjectID, len(x.members)) 96 97 for i := range x.members { 98 members[i] = x.members[i].ToGRPCMessage().(*refsGRPC.ObjectID) 99 } 100 } 101 102 m.SetMembers(members) 103 } 104 105 return m 106 } 107 108 func (x *Lock) FromGRPCMessage(m grpc.Message) error { 109 v, ok := m.(*lock.Lock) 110 if !ok { 111 return message.NewUnexpectedMessageType(m, v) 112 } 113 114 members := v.GetMembers() 115 if members == nil { 116 x.members = nil 117 } else { 118 x.members = make([]refs.ObjectID, len(members)) 119 var err error 120 121 for i := range x.members { 122 err = x.members[i].FromGRPCMessage(members[i]) 123 if err != nil { 124 return err 125 } 126 } 127 } 128 129 return nil 130 } 131 132 // WriteLock writes Lock to the Object as a payload content. 133 // The object must not be nil. 134 func WriteLock(obj *Object, lock Lock) { 135 hdr := obj.GetHeader() 136 if hdr == nil { 137 hdr = new(Header) 138 obj.SetHeader(hdr) 139 } 140 141 hdr.SetObjectType(TypeLock) 142 143 payload := lock.StableMarshal(nil) 144 obj.SetPayload(payload) 145 } 146 147 // ReadLock reads Lock from the Object payload content. 148 func ReadLock(lock *Lock, obj Object) error { 149 payload := obj.GetPayload() 150 if len(payload) == 0 { 151 return errors.New("empty payload") 152 } 153 154 err := lock.Unmarshal(payload) 155 if err != nil { 156 return fmt.Errorf("decode lock content from payload: %w", err) 157 } 158 159 return nil 160 }