github.com/lirm/aeron-go@v0.0.0-20230415210743-920325491dc4/aeron/driver/proxy.go (about) 1 /* 2 Copyright 2016 Stanislav Liberman 3 Copyright (C) 2022 Talos, Inc. 4 5 Licensed under the Apache License, Version 2.0 (the "License"); 6 you may not use this file except in compliance with the License. 7 You may obtain a copy of the License at 8 9 http://www.apache.org/licenses/LICENSE-2.0 10 11 Unless required by applicable law or agreed to in writing, software 12 distributed under the License is distributed on an "AS IS" BASIS, 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 See the License for the specific language governing permissions and 15 limitations under the License. 16 */ 17 18 package driver 19 20 import ( 21 "errors" 22 "github.com/lirm/aeron-go/aeron/atomic" 23 "github.com/lirm/aeron-go/aeron/command" 24 rb "github.com/lirm/aeron-go/aeron/ringbuffer" 25 ) 26 27 // Proxy is a media driver proxy class that is used to send commands 28 type Proxy struct { 29 toDriverCommandBuffer *rb.ManyToOne 30 clientID int64 31 } 32 33 // Init initializes media driver proxy class 34 func (driver *Proxy) Init(buffer *rb.ManyToOne) *Proxy { 35 driver.toDriverCommandBuffer = buffer 36 driver.clientID = driver.toDriverCommandBuffer.NextCorrelationID() 37 logger.Infof("aeron clientID:%d", driver.clientID) 38 return driver 39 } 40 41 // ClientID returns the client ID for this connection to the driver. 42 func (driver *Proxy) ClientID() int64 { 43 return driver.clientID 44 } 45 46 // TimeOfLastDriverKeepalive gets the time of the last keep alive update sent to media driver 47 func (driver *Proxy) TimeOfLastDriverKeepalive() int64 { 48 return driver.toDriverCommandBuffer.ConsumerHeartbeatTime() 49 } 50 51 // NextCorrelationID generates the next correlation id that is unique for the connected Media Driver. 52 func (driver *Proxy) NextCorrelationID() int64 { 53 return driver.toDriverCommandBuffer.NextCorrelationID() 54 } 55 56 // AddSubscription sends driver command to add new subscription 57 func (driver *Proxy) AddSubscription(channel string, streamID int32) (int64, error) { 58 59 correlationID := driver.toDriverCommandBuffer.NextCorrelationID() 60 61 logger.Debugf("driver.AddSubscription: correlationId=%d", correlationID) 62 63 filler := func(buffer *atomic.Buffer, length *int) int32 { 64 65 var message command.SubscriptionMessage 66 message.Wrap(buffer, 0) 67 68 message.ClientID.Set(driver.clientID) 69 message.CorrelationID.Set(correlationID) 70 message.RegistrationCorrelationID.Set(-1) 71 message.StreamID.Set(streamID) 72 message.Channel.Set(channel) 73 74 *length = message.Size() 75 76 return command.AddSubscription 77 } 78 79 if err := driver.writeCommandToDriver(filler); err == nil { 80 return correlationID, nil 81 } else { 82 return 0, err 83 } 84 } 85 86 // RemoveSubscription sends driver command to remove subscription 87 func (driver *Proxy) RemoveSubscription(registrationID int64) error { 88 correlationID := driver.toDriverCommandBuffer.NextCorrelationID() 89 90 logger.Debugf("driver.RemoveSubscription: correlationId=%d (subId=%d)", correlationID, registrationID) 91 92 filler := func(buffer *atomic.Buffer, length *int) int32 { 93 94 var message command.RemoveMessage 95 message.Wrap(buffer, 0) 96 97 message.ClientID.Set(driver.clientID) 98 message.CorrelationID.Set(correlationID) 99 message.RegistrationID.Set(registrationID) 100 101 *length = message.Size() 102 103 return command.RemoveSubscription 104 } 105 106 return driver.writeCommandToDriver(filler) 107 } 108 109 // AddPublication sends driver command to add new publication 110 func (driver *Proxy) AddPublication(channel string, streamID int32) (int64, error) { 111 112 correlationID := driver.toDriverCommandBuffer.NextCorrelationID() 113 114 logger.Debugf("driver.AddPublication: clientId=%d correlationId=%d", 115 driver.clientID, correlationID) 116 117 filler := func(buffer *atomic.Buffer, length *int) int32 { 118 119 var message command.PublicationMessage 120 message.Wrap(buffer, 0) 121 message.ClientID.Set(driver.clientID) 122 message.CorrelationID.Set(correlationID) 123 message.StreamID.Set(streamID) 124 message.Channel.Set(channel) 125 126 *length = message.Size() 127 128 return command.AddPublication 129 } 130 131 if err := driver.writeCommandToDriver(filler); err == nil { 132 return correlationID, nil 133 } else { 134 return 0, err 135 } 136 } 137 138 // AddExclusivePublication sends driver command to add new publication 139 func (driver *Proxy) AddExclusivePublication(channel string, streamID int32) (int64, error) { 140 141 correlationID := driver.toDriverCommandBuffer.NextCorrelationID() 142 143 logger.Debugf("driver.AddExclusivePublication: clientId=%d correlationId=%d", 144 driver.clientID, correlationID) 145 146 filler := func(buffer *atomic.Buffer, length *int) int32 { 147 148 var message command.PublicationMessage 149 message.Wrap(buffer, 0) 150 message.ClientID.Set(driver.clientID) 151 message.CorrelationID.Set(correlationID) 152 message.StreamID.Set(streamID) 153 message.Channel.Set(channel) 154 155 *length = message.Size() 156 157 return command.AddExclusivePublication 158 } 159 160 if err := driver.writeCommandToDriver(filler); err == nil { 161 return correlationID, nil 162 } else { 163 return 0, err 164 } 165 } 166 167 // RemovePublication sends driver command to remove publication 168 func (driver *Proxy) RemovePublication(registrationID int64) error { 169 correlationID := driver.toDriverCommandBuffer.NextCorrelationID() 170 171 logger.Debugf("driver.RemovePublication: clientId=%d correlationId=%d (regId=%d)", 172 driver.clientID, correlationID, registrationID) 173 174 filler := func(buffer *atomic.Buffer, length *int) int32 { 175 176 var message command.RemoveMessage 177 message.Wrap(buffer, 0) 178 179 message.ClientID.Set(driver.clientID) 180 message.CorrelationID.Set(correlationID) 181 message.RegistrationID.Set(registrationID) 182 183 *length = message.Size() 184 185 return command.RemovePublication 186 } 187 188 return driver.writeCommandToDriver(filler) 189 } 190 191 // ClientClose sends a client close to the driver. 192 func (driver *Proxy) ClientClose() error { 193 correlationID := driver.toDriverCommandBuffer.NextCorrelationID() 194 195 logger.Debugf("driver.ClientClose: clientId=%d correlationId=%d", 196 driver.clientID, correlationID) 197 198 filler := func(buffer *atomic.Buffer, length *int) int32 { 199 200 var message command.CorrelatedMessage 201 message.Wrap(buffer, 0) 202 203 message.ClientID.Set(driver.clientID) 204 message.CorrelationID.Set(correlationID) 205 206 *length = message.Size() 207 208 return command.ClientClose 209 } 210 211 return driver.writeCommandToDriver(filler) 212 } 213 214 // AddDestination sends driver command to add a destination to an existing Publication. 215 func (driver *Proxy) AddDestination(registrationID int64, channel string) (int64, error) { 216 217 correlationID := driver.toDriverCommandBuffer.NextCorrelationID() 218 219 logger.Debugf("driver.AddDestination: clientID=%d registrationID=%d correlationID=%d", 220 driver.clientID, registrationID, correlationID) 221 222 filler := func(buffer *atomic.Buffer, length *int) int32 { 223 224 var message command.DestinationMessage 225 message.Wrap(buffer, 0) 226 message.RegistrationCorrelationID.Set(registrationID) 227 message.Channel.Set(channel) 228 message.CorrelationID.Set(correlationID) 229 message.ClientID.Set(driver.clientID) 230 231 *length = message.Size() 232 233 return command.AddDestination 234 } 235 236 if err := driver.writeCommandToDriver(filler); err == nil { 237 return correlationID, nil 238 } else { 239 return 0, err 240 } 241 } 242 243 // RemoveDestination sends driver command to remove a destination from an existing Publication. 244 func (driver *Proxy) RemoveDestination(registrationID int64, channel string) (int64, error) { 245 246 correlationID := driver.toDriverCommandBuffer.NextCorrelationID() 247 248 logger.Debugf("driver.RemoveDestination: clientID=%d registrationID=%d correlationID=%d", 249 driver.clientID, registrationID, correlationID) 250 251 filler := func(buffer *atomic.Buffer, length *int) int32 { 252 253 var message command.DestinationMessage 254 message.Wrap(buffer, 0) 255 message.RegistrationCorrelationID.Set(registrationID) 256 message.Channel.Set(channel) 257 message.CorrelationID.Set(correlationID) 258 message.ClientID.Set(driver.clientID) 259 260 *length = message.Size() 261 262 return command.RemoveDestination 263 } 264 265 if err := driver.writeCommandToDriver(filler); err == nil { 266 return correlationID, nil 267 } else { 268 return 0, err 269 } 270 } 271 272 // AddRcvDestination sends driver command to add a destination to the receive 273 // channel of an existing MDS Subscription. 274 func (driver *Proxy) AddRcvDestination(registrationID int64, channel string) (int64, error) { 275 276 correlationID := driver.toDriverCommandBuffer.NextCorrelationID() 277 278 logger.Debugf("driver.AddRcvDestination: clientID=%d registrationID=%d correlationID=%d channel=%s", 279 driver.clientID, registrationID, correlationID, channel) 280 281 filler := func(buffer *atomic.Buffer, length *int) int32 { 282 283 var message command.DestinationMessage 284 message.Wrap(buffer, 0) 285 message.RegistrationCorrelationID.Set(registrationID) 286 message.Channel.Set(channel) 287 message.CorrelationID.Set(correlationID) 288 message.ClientID.Set(driver.clientID) 289 290 *length = message.Size() 291 292 return command.AddRcvDestination 293 } 294 295 if err := driver.writeCommandToDriver(filler); err == nil { 296 return correlationID, nil 297 } else { 298 return 0, nil 299 } 300 } 301 302 // RemoveRcvDestination sends driver command to remove a destination from the 303 // receive channel of an existing MDS Subscription. 304 func (driver *Proxy) RemoveRcvDestination(registrationID int64, channel string) (int64, error) { 305 306 correlationID := driver.toDriverCommandBuffer.NextCorrelationID() 307 308 logger.Debugf("driver.RemoveRcvDestination: clientID=%d registrationID=%d correlationID=%d", 309 driver.clientID, registrationID, correlationID) 310 311 filler := func(buffer *atomic.Buffer, length *int) int32 { 312 313 var message command.DestinationMessage 314 message.Wrap(buffer, 0) 315 message.RegistrationCorrelationID.Set(registrationID) 316 message.Channel.Set(channel) 317 message.CorrelationID.Set(correlationID) 318 message.ClientID.Set(driver.clientID) 319 320 *length = message.Size() 321 322 return command.RemoveRcvDestination 323 } 324 325 if err := driver.writeCommandToDriver(filler); err == nil { 326 return correlationID, nil 327 } else { 328 return 0, err 329 } 330 } 331 332 // AddCounter adds a new counter with a type id plus the label and key are provided in buffers. 333 func (driver *Proxy) AddCounter(typeId int32, keyBuffer *atomic.Buffer, keyOffset int32, keyLength int32, 334 labelBuffer *atomic.Buffer, labelOffset int32, labelLength int32) (int64, error) { 335 correlationID := driver.toDriverCommandBuffer.NextCorrelationID() 336 337 filler := func(buffer *atomic.Buffer, length *int) int32 { 338 var message command.CounterMessage 339 message.Wrap(buffer, 0) 340 message.ClientID.Set(driver.clientID) 341 message.CorrelationID.Set(correlationID) 342 message.CounterTypeID.Set(typeId) 343 message.CopyKeyBuffer(keyBuffer, keyOffset, keyLength) 344 message.CopyLabelBuffer(labelBuffer, labelOffset, labelLength) 345 346 *length = message.Size() 347 348 return command.AddCounter 349 } 350 351 if err := driver.writeCommandToDriver(filler); err == nil { 352 return correlationID, nil 353 } else { 354 return 0, err 355 } 356 } 357 358 // AddCounterByLabel adds a new counter with a type id and label. The key will be blank. 359 func (driver *Proxy) AddCounterByLabel(typeId int32, label string) (int64, error) { 360 correlationID := driver.toDriverCommandBuffer.NextCorrelationID() 361 362 filler := func(buffer *atomic.Buffer, length *int) int32 { 363 var message command.CounterMessage 364 message.Wrap(buffer, 0) 365 message.ClientID.Set(driver.clientID) 366 message.CorrelationID.Set(correlationID) 367 message.CounterTypeID.Set(typeId) 368 message.CopyLabelString(label) 369 370 *length = message.Size() 371 372 return command.AddCounter 373 } 374 375 if err := driver.writeCommandToDriver(filler); err == nil { 376 return correlationID, nil 377 } else { 378 return 0, err 379 } 380 } 381 382 // RemoveCounter instructs the media driver to remove an existing counter by its registration id. Returns the 383 // correlation id for the command. 384 385 // RemoveCounter instructs the media driver to remove an existing counter by its registration id. Returns the 386 // correlation id for the command. 387 func (driver *Proxy) RemoveCounter(registrationId int64) (int64, error) { 388 correlationId := driver.toDriverCommandBuffer.NextCorrelationID() 389 390 logger.Debugf("driver.RemoveCounter: correlationId=%d (counter registrationId=%d)", correlationId, registrationId) 391 392 filler := func(buffer *atomic.Buffer, length *int) int32 { 393 var message command.RemoveMessage 394 message.Wrap(buffer, 0) 395 396 message.ClientID.Set(driver.clientID) 397 message.CorrelationID.Set(correlationId) 398 message.RegistrationID.Set(registrationId) 399 400 *length = message.Size() 401 402 return command.RemoveCounter 403 } 404 405 if err := driver.writeCommandToDriver(filler); err == nil { 406 return correlationId, nil 407 } else { 408 return 0, err 409 } 410 } 411 412 func (driver *Proxy) writeCommandToDriver(filler func(*atomic.Buffer, *int) int32) error { 413 messageBuffer := make([]byte, 512) 414 415 buffer := atomic.MakeBuffer(messageBuffer) 416 417 length := len(messageBuffer) 418 419 msgTypeID := filler(buffer, &length) 420 421 if driver.toDriverCommandBuffer.Write(int32(msgTypeID), buffer, 0, int32(length)) { 422 return nil 423 } else { 424 return errors.New("couldn't write command to driver") 425 } 426 }