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  }