github.com/lirm/aeron-go@v0.0.0-20230415210743-920325491dc4/aeron/driver/listeneradapter.go (about)

     1  /*
     2  Copyright 2016-2018 Stanislav Liberman
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package driver
    18  
    19  import (
    20  	"strings"
    21  
    22  	"github.com/lirm/aeron-go/aeron/logging"
    23  
    24  	"github.com/lirm/aeron-go/aeron/atomic"
    25  	"github.com/lirm/aeron-go/aeron/broadcast"
    26  	"github.com/lirm/aeron-go/aeron/command"
    27  )
    28  
    29  var logger = logging.MustGetLogger("driver")
    30  
    31  var Events = struct {
    32  	/** Error Response */
    33  	OnError int32
    34  	/** New subscription Buffer Notification */
    35  	OnAvailableImage int32
    36  	/** New publication Buffer Notification */
    37  	OnPublicationReady int32
    38  	/** Operation Succeeded */
    39  	OnOperationSuccess int32
    40  	/** Inform client of timeout and removal of inactive image */
    41  	OnUnavailableImage int32
    42  	/** New Exclusive Publication Buffer notification */
    43  	OnExclusivePublicationReady int32
    44  	/** New subscription notification */
    45  	OnSubscriptionReady int32
    46  	/** New counter notification */
    47  	OnCounterReady int32
    48  	/** inform clients of removal of counter */
    49  	OnUnavailableCounter int32
    50  	/** inform clients of client timeout */
    51  	OnClientTimeout int32
    52  }{
    53  	0x0F01,
    54  	0x0F02,
    55  	0x0F03,
    56  	0x0F04,
    57  	0x0F05,
    58  	0x0F06,
    59  	0x0F07,
    60  	0x0F08,
    61  	0x0F09,
    62  	0x0F0A,
    63  }
    64  
    65  type SubscriberPosition struct {
    66  	indicatorID    int32
    67  	registrationID int64
    68  }
    69  
    70  func (pos *SubscriberPosition) RegistrationID() int64 {
    71  	return pos.registrationID
    72  }
    73  
    74  func (pos *SubscriberPosition) IndicatorID() int32 {
    75  	return pos.indicatorID
    76  }
    77  
    78  type Listener interface {
    79  	OnNewPublication(streamID int32, sessionID int32, positionLimitCounterID int32, channelStatusIndicatorID int32,
    80  		logFileName string, correlationID int64, registrationID int64)
    81  	OnNewExclusivePublication(streamID int32, sessionID int32, positionLimitCounterID int32, channelStatusIndicatorID int32,
    82  		logFileName string, correlationID int64, registrationID int64)
    83  	OnAvailableImage(streamID int32, sessionID int32, logFilename string, sourceIdentity string,
    84  		subscriberPositionID int32, subsRegID int64, correlationID int64)
    85  	OnUnavailableImage(correlationID int64, subscriptionRegistrationID int64)
    86  	OnOperationSuccess(correlationID int64)
    87  	OnErrorResponse(offendingCommandCorrelationID int64, errorCode int32, errorMessage string)
    88  	OnChannelEndpointError(correlationID int64, errorMessage string)
    89  	OnSubscriptionReady(correlationID int64, channelStatusIndicatorID int32)
    90  	OnAvailableCounter(correlationID int64, counterID int32)
    91  	OnUnavailableCounter(correlationID int64, counterID int32)
    92  	OnClientTimeout(clientID int64)
    93  }
    94  
    95  type ListenerAdapter struct {
    96  	listener          Listener
    97  	broadcastReceiver *broadcast.CopyReceiver
    98  }
    99  
   100  func NewAdapter(driverListener Listener, broadcastReceiver *broadcast.CopyReceiver) *ListenerAdapter {
   101  	adapter := new(ListenerAdapter)
   102  	adapter.listener = driverListener
   103  	adapter.broadcastReceiver = broadcastReceiver
   104  
   105  	return adapter
   106  }
   107  
   108  func (adapter *ListenerAdapter) ReceiveMessages() int {
   109  	handler := func(msgTypeID int32, buffer *atomic.Buffer, offset int32, length int32) {
   110  		logger.Debugf("received %d", msgTypeID)
   111  		switch int32(msgTypeID) {
   112  		case Events.OnPublicationReady:
   113  			logger.Debugf("received ON_PUBLICATION_READY")
   114  
   115  			var msg publicationReady
   116  			msg.Wrap(buffer, int(offset))
   117  
   118  			streamID := msg.streamID.Get()
   119  			sessionID := msg.sessionID.Get()
   120  			positionLimitCounterID := msg.publicationLimitOffset.Get()
   121  			channelStatusIndicatorID := msg.channelStatusIndicatorID.Get()
   122  			correlationID := msg.correlationID.Get()
   123  			registrationID := msg.registrationID.Get()
   124  			logFileName := msg.logFileName.Get()
   125  
   126  			adapter.listener.OnNewPublication(streamID, sessionID, positionLimitCounterID, channelStatusIndicatorID,
   127  				logFileName, correlationID, registrationID)
   128  		case Events.OnExclusivePublicationReady:
   129  			logger.Debugf("received ON_EXCLUSIVE_PUBLICATION_READY")
   130  
   131  			var msg publicationReady
   132  			msg.Wrap(buffer, int(offset))
   133  
   134  			streamID := msg.streamID.Get()
   135  			sessionID := msg.sessionID.Get()
   136  			positionLimitCounterID := msg.publicationLimitOffset.Get()
   137  			channelStatusIndicatorID := msg.channelStatusIndicatorID.Get()
   138  			correlationID := msg.correlationID.Get()
   139  			registrationID := msg.registrationID.Get()
   140  			logFileName := msg.logFileName.Get()
   141  
   142  			adapter.listener.OnNewExclusivePublication(streamID, sessionID, positionLimitCounterID, channelStatusIndicatorID,
   143  				logFileName, correlationID, registrationID)
   144  		case Events.OnSubscriptionReady:
   145  			logger.Debugf("received ON_SUBSCRIPTION_READY")
   146  
   147  			var msg subscriptionReady
   148  			msg.Wrap(buffer, int(offset))
   149  
   150  			correlationID := msg.correlationID.Get()
   151  			channelStatusIndicatorID := msg.channelStatusIndicatorID.Get()
   152  
   153  			adapter.listener.OnSubscriptionReady(correlationID, channelStatusIndicatorID)
   154  		case Events.OnAvailableImage:
   155  			logger.Debugf("received ON_AVAILABLE_IMAGE")
   156  
   157  			var header imageReadyHeader
   158  			header.Wrap(buffer, int(offset))
   159  
   160  			streamID := header.streamID.Get()
   161  			sessionID := header.sessionID.Get()
   162  			logFileName := header.logFile.Get()
   163  			sourceIdentity := header.sourceIdentity.Get()
   164  			subsPosID := header.subsPosID.Get()
   165  			subsRegID := header.subsRegistrationID.Get()
   166  			correlationID := header.correlationID.Get()
   167  
   168  			logger.Debugf("logFileName: %v", logFileName)
   169  			logger.Debugf("sourceIdentity: %v", sourceIdentity)
   170  
   171  			adapter.listener.OnAvailableImage(streamID, sessionID, logFileName, sourceIdentity, subsPosID, subsRegID,
   172  				correlationID)
   173  		case Events.OnOperationSuccess:
   174  			logger.Debugf("received ON_OPERATION_SUCCESS")
   175  
   176  			var msg command.CorrelatedMessage
   177  			msg.Wrap(buffer, int(offset))
   178  
   179  			correlationID := msg.CorrelationID.Get()
   180  
   181  			adapter.listener.OnOperationSuccess(correlationID)
   182  		case Events.OnUnavailableImage:
   183  			logger.Debugf("received ON_UNAVAILABLE_IMAGE")
   184  
   185  			var msg command.ImageMessage
   186  			msg.Wrap(buffer, int(offset))
   187  
   188  			correlationID := msg.CorrelationID.Get()
   189  			subscriptionRegistrationID := msg.SubscriptionRegistrationID.Get()
   190  
   191  			adapter.listener.OnUnavailableImage(correlationID, subscriptionRegistrationID)
   192  		case Events.OnError:
   193  			logger.Debugf("received ON_ERROR")
   194  
   195  			var msg errorMessage
   196  			msg.Wrap(buffer, int(offset))
   197  
   198  			if msg.errorCode.Get() == command.ErrorCodeChannelEndpointError ||
   199  				strings.Contains(msg.errorMessage.Get(), "Address already in use") { // hack for c media driver
   200  				adapter.listener.OnChannelEndpointError(msg.offendingCommandCorrelationID.Get(), msg.errorMessage.Get())
   201  			} else {
   202  				adapter.listener.OnErrorResponse(msg.offendingCommandCorrelationID.Get(),
   203  					msg.errorCode.Get(), msg.errorMessage.Get())
   204  			}
   205  		case Events.OnCounterReady:
   206  			logger.Debugf("received ON_COUNTER_READY")
   207  
   208  			var msg counterUpdate
   209  			msg.Wrap(buffer, int(offset))
   210  
   211  			adapter.listener.OnAvailableCounter(msg.correlationID.Get(), msg.counterID.Get())
   212  		case Events.OnUnavailableCounter:
   213  			logger.Debugf("received ON_UNAVAILABLE_COUNTER")
   214  
   215  			var msg counterUpdate
   216  			msg.Wrap(buffer, int(offset))
   217  
   218  			adapter.listener.OnUnavailableCounter(msg.correlationID.Get(), msg.counterID.Get())
   219  		case Events.OnClientTimeout:
   220  			logger.Debugf("received ON_CLIENT_TIMEOUT")
   221  
   222  			var msg clientTimeout
   223  			msg.Wrap(buffer, int(offset))
   224  
   225  			adapter.listener.OnClientTimeout(msg.clientID.Get())
   226  		default:
   227  			// Note: Java silently ignores unhandled events
   228  			logger.Fatalf("received unhandled %d", msgTypeID)
   229  		}
   230  	}
   231  
   232  	return adapter.broadcastReceiver.Receive(handler)
   233  }