X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=openflowplugin-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fimpl%2Fstatistics%2FStatisticsContextImpl.java;h=d3b2e72cd9cb2be0878272f8cdf06e888a5a4275;hb=510c6087aec01a0d47b02c7f7b722e247e2d8db9;hp=eab57c27958dd96bb539a608fb38a525553115a9;hpb=039e2f7cb8d5522b12fbef658fe17e3950dcabf9;p=openflowplugin.git diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpl.java index eab57c2795..d3b2e72cd9 100644 --- a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpl.java +++ b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpl.java @@ -12,45 +12,45 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterators; +import com.google.common.util.concurrent.AsyncFunction; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.SettableFuture; import io.netty.util.Timeout; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Objects; -import java.util.Optional; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.GuardedBy; import org.opendaylight.mdsal.common.api.TransactionChainClosedException; import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier; +import org.opendaylight.openflowplugin.api.ConnectionException; import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext; import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext; import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo; import org.opendaylight.openflowplugin.api.openflow.device.DeviceState; import org.opendaylight.openflowplugin.api.openflow.device.RequestContext; -import org.opendaylight.openflowplugin.api.openflow.device.handlers.ClusterInitializationPhaseHandler; -import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService; +import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainMastershipState; +import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainMastershipWatcher; import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener; import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext; import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager; +import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider; import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext; import org.opendaylight.openflowplugin.impl.rpc.listener.ItemLifecycleListenerImpl; -import org.opendaylight.openflowplugin.impl.services.RequestContextUtil; +import org.opendaylight.openflowplugin.impl.services.util.RequestContextUtil; import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringOnTheFlyService; import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringService; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -class StatisticsContextImpl implements StatisticsContext { +class StatisticsContextImpl implements StatisticsContext { private static final Logger LOG = LoggerFactory.getLogger(StatisticsContextImpl.class); private static final String CONNECTION_CLOSED = "Connection closed."; @@ -59,46 +59,41 @@ class StatisticsContextImpl implements StatisticsContext { private final Collection> requestContexts = new HashSet<>(); private final DeviceContext deviceContext; private final DeviceState devState; - private final ListenableFuture emptyFuture; private final boolean isStatisticsPollingOn; - private final SinglePurposeMultipartReplyTranslator multipartReplyTranslator; private final Object collectionStatTypeLock = new Object(); + private final ConvertorExecutor convertorExecutor; + private final MultipartWriterProvider statisticsWriterProvider; + private final DeviceInfo deviceInfo; + private final StatisticsManager myManager; @GuardedBy("collectionStatTypeLock") private List collectingStatType; - - private StatisticsGatheringService statisticsGatheringService; - private StatisticsGatheringOnTheFlyService statisticsGatheringOnTheFlyService; + private StatisticsGatheringService statisticsGatheringService; + private StatisticsGatheringOnTheFlyService statisticsGatheringOnTheFlyService; private Timeout pollTimeout; - private final DeviceInfo deviceInfo; - private final StatisticsManager myManager; - private final LifecycleService lifecycleService; + private ContextChainMastershipWatcher contextChainMastershipWatcher; + private volatile ContextState state = ContextState.INITIALIZATION; private volatile boolean schedulingEnabled; - private volatile CONTEXT_STATE state; - private ClusterInitializationPhaseHandler clusterInitializationPhaseHandler; - private ClusterInitializationPhaseHandler initialSubmitHandler; - - private ListenableFuture lastDataGathering; + private volatile ListenableFuture lastDataGathering; - StatisticsContextImpl(@Nonnull final DeviceInfo deviceInfo, - final boolean isStatisticsPollingOn, - @Nonnull final LifecycleService lifecycleService, + StatisticsContextImpl(final boolean isStatisticsPollingOn, + @Nonnull final DeviceContext deviceContext, @Nonnull final ConvertorExecutor convertorExecutor, - @Nonnull final StatisticsManager myManager) { - this.lifecycleService = lifecycleService; - this.deviceContext = lifecycleService.getDeviceContext(); + @Nonnull final StatisticsManager myManager, + @Nonnull final MultipartWriterProvider statisticsWriterProvider) { + this.deviceContext = deviceContext; this.devState = Preconditions.checkNotNull(deviceContext.getDeviceState()); this.isStatisticsPollingOn = isStatisticsPollingOn; - multipartReplyTranslator = new SinglePurposeMultipartReplyTranslator(convertorExecutor); - emptyFuture = Futures.immediateFuture(false); - statisticsGatheringService = new StatisticsGatheringService(this, deviceContext); - statisticsGatheringOnTheFlyService = new StatisticsGatheringOnTheFlyService(this, deviceContext, convertorExecutor); + this.convertorExecutor = convertorExecutor; + statisticsGatheringService = new StatisticsGatheringService<>(this, deviceContext); + statisticsGatheringOnTheFlyService = new StatisticsGatheringOnTheFlyService<>(this, + deviceContext, convertorExecutor, statisticsWriterProvider); itemLifeCycleListener = new ItemLifecycleListenerImpl(deviceContext); statListForCollectingInitialization(); - this.state = CONTEXT_STATE.INITIALIZATION; - this.deviceInfo = deviceInfo; + this.deviceInfo = deviceContext.getDeviceInfo(); this.myManager = myManager; this.lastDataGathering = null; + this.statisticsWriterProvider = statisticsWriterProvider; } @Override @@ -125,46 +120,39 @@ class StatisticsContextImpl implements StatisticsContext { if (devState.isQueueStatisticsAvailable()) { statListForCollecting.add(MultipartType.OFPMPQUEUE); } - collectingStatType = ImmutableList.copyOf(statListForCollecting); + collectingStatType = ImmutableList.copyOf(statListForCollecting); } } - - @Override - public ListenableFuture initialGatherDynamicData() { - return gatherDynamicData(true); - } - @Override - public ListenableFuture gatherDynamicData(){ - return gatherDynamicData(false); - } - - private ListenableFuture gatherDynamicData(final boolean initial) { - this.lastDataGathering = null; + public ListenableFuture gatherDynamicData() { if (!isStatisticsPollingOn) { LOG.debug("Statistics for device {} is not enabled.", getDeviceInfo().getNodeId().getValue()); return Futures.immediateFuture(Boolean.TRUE); } - final ListenableFuture errorResultFuture = deviceConnectionCheck(); - if (errorResultFuture != null) { - return errorResultFuture; + + if (Objects.isNull(lastDataGathering) + || lastDataGathering.isCancelled() + || lastDataGathering.isDone()) { + lastDataGathering = Futures.immediateFuture(Boolean.TRUE); } - synchronized (collectionStatTypeLock) { - final Iterator statIterator = collectingStatType.iterator(); - final SettableFuture settableStatResultFuture = SettableFuture.create(); + synchronized (collectionStatTypeLock) { // write start timestamp to state snapshot container StatisticsGatheringUtils.markDeviceStateSnapshotStart(deviceContext); - statChainFuture(statIterator, settableStatResultFuture, initial); + lastDataGathering = collectingStatType.stream().reduce( + lastDataGathering, + this::statChainFuture, + (a, b) -> Futures.transformAsync(a, (AsyncFunction) result -> b)); // write end timestamp to state snapshot container - Futures.addCallback(settableStatResultFuture, new FutureCallback() { + Futures.addCallback(lastDataGathering, new FutureCallback() { @Override - public void onSuccess(@Nullable final Boolean result) { - StatisticsGatheringUtils.markDeviceStateSnapshotEnd(deviceContext, true); + public void onSuccess(final Boolean result) { + StatisticsGatheringUtils.markDeviceStateSnapshotEnd(deviceContext, result); } + @Override public void onFailure(final Throwable t) { if (!(t instanceof TransactionChainClosedException)) { @@ -172,38 +160,38 @@ class StatisticsContextImpl implements StatisticsContext { } } }); - this.lastDataGathering = settableStatResultFuture; - return settableStatResultFuture; } + + return lastDataGathering; } - private ListenableFuture chooseStat(final MultipartType multipartType, final boolean initial){ + private ListenableFuture chooseStat(final MultipartType multipartType){ ListenableFuture result = Futures.immediateCheckedFuture(Boolean.TRUE); switch (multipartType) { case OFPMPFLOW: - result = collectFlowStatistics(multipartType, initial); + result = collectStatistics(multipartType, devState.isFlowStatisticsAvailable(), true); break; case OFPMPTABLE: - result = collectTableStatistics(multipartType); + result = collectStatistics(multipartType, devState.isTableStatisticsAvailable(), false); break; case OFPMPPORTSTATS: - result = collectPortStatistics(multipartType); + result = collectStatistics(multipartType, devState.isPortStatisticsAvailable(), false); break; case OFPMPQUEUE: - result = collectQueueStatistics(multipartType); + result = collectStatistics(multipartType, devState.isQueueStatisticsAvailable(), false); break; case OFPMPGROUPDESC: - result = collectGroupDescStatistics(multipartType); + result = collectStatistics(multipartType, devState.isGroupAvailable(), false); break; case OFPMPGROUP: - result = collectGroupStatistics(multipartType); + result = collectStatistics(multipartType, devState.isGroupAvailable(), false); break; case OFPMPMETERCONFIG: - result = collectMeterConfigStatistics(multipartType); + result = collectStatistics(multipartType, devState.isMetersAvailable(), false); break; case OFPMPMETER: - result = collectMeterStatistics(multipartType); + result = collectStatistics(multipartType, devState.isMetersAvailable(), false); break; default: LOG.warn("Unsupported Statistics type {}", multipartType); @@ -227,27 +215,16 @@ class StatisticsContextImpl implements StatisticsContext { @Override public void close() { - if (CONTEXT_STATE.TERMINATION.equals(getState())) { + if (ContextState.TERMINATION.equals(state)) { if (LOG.isDebugEnabled()) { LOG.debug("StatisticsContext for node {} is already in TERMINATION state.", getDeviceInfo().getLOGValue()); } } else { - try { - stopClusterServices(true).get(); - } catch (Exception e) { - LOG.debug("Failed to close StatisticsContext for node {} with exception: ", getDeviceInfo().getLOGValue(), e); - } - - this.state = CONTEXT_STATE.TERMINATION; - - for (final Iterator> iterator = Iterators.consumingIterator(requestContexts.iterator()); - iterator.hasNext(); ) { - RequestContextUtil.closeRequestContextWithRpcError(iterator.next(), CONNECTION_CLOSED); - } - - if (null != pollTimeout && !pollTimeout.isExpired()) { - pollTimeout.cancel(); - } + this.state = ContextState.TERMINATION; + stopGatheringData(); + requestContexts.forEach(requestContext -> RequestContextUtil + .closeRequestContextWithRpcError(requestContext, CONNECTION_CLOSED)); + requestContexts.clear(); } } @@ -266,155 +243,53 @@ class StatisticsContextImpl implements StatisticsContext { this.pollTimeout = pollTimeout; } - @Override - public Optional getPollTimeout() { - return Optional.ofNullable(pollTimeout); - } - - private void statChainFuture(final Iterator iterator, final SettableFuture resultFuture, final boolean initial) { - if (ConnectionContext.CONNECTION_STATE.RIP.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) { - final String errMsg = String.format("Device connection is closed for Node : %s.", - getDeviceInfo().getNodeId()); - LOG.debug(errMsg); - resultFuture.setException(new IllegalStateException(errMsg)); - return; - } - if ( ! iterator.hasNext()) { - resultFuture.set(Boolean.TRUE); - LOG.debug("Stats collection successfully finished for node {}", getDeviceInfo().getLOGValue()); - return; - } + private ListenableFuture statChainFuture(final ListenableFuture prevFuture, final MultipartType multipartType) { + return Futures.transformAsync(deviceConnectionCheck(), (AsyncFunction) connectionResult -> Futures + .transformAsync(prevFuture, (AsyncFunction) result -> { + LOG.debug("Status of previous stat iteration for node {}: {}", deviceInfo.getLOGValue(), result); + LOG.debug("Stats iterating to next type for node {} of type {}", + deviceInfo.getLOGValue(), + multipartType); - final MultipartType nextType = iterator.next(); - LOG.debug("Stats iterating to next type for node {} of type {}", getDeviceInfo().getLOGValue(), nextType); - - final ListenableFuture deviceStatisticsCollectionFuture = chooseStat(nextType, initial); - Futures.addCallback(deviceStatisticsCollectionFuture, new FutureCallback() { - @Override - public void onSuccess(final Boolean result) { - statChainFuture(iterator, resultFuture, initial); - } - @Override - public void onFailure(@Nonnull final Throwable t) { - resultFuture.setException(t); - } - }); + return chooseStat(multipartType); + })); } - /** - * Method checks a device state. It returns null for be able continue. Otherwise it returns immediateFuture - * which has to be returned from caller too - * - * @return - */ @VisibleForTesting ListenableFuture deviceConnectionCheck() { - if (!ConnectionContext.CONNECTION_STATE.WORKING.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) { - ListenableFuture resultingFuture; - switch (deviceContext.getPrimaryConnectionContext().getConnectionState()) { - case RIP: - final String errMsg = String.format("Device connection doesn't exist anymore. Primary connection status : %s", + if (ConnectionContext.CONNECTION_STATE.RIP.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) { + final String errMsg = String + .format("Device connection for node %s doesn't exist anymore. Primary connection status : %s", + getDeviceInfo().getNodeId(), deviceContext.getPrimaryConnectionContext().getConnectionState()); - resultingFuture = Futures.immediateFailedFuture(new Throwable(errMsg)); - break; - default: - resultingFuture = Futures.immediateCheckedFuture(Boolean.TRUE); - break; - } - return resultingFuture; - } - return null; - } - - //TODO: Refactor twice sending deviceContext into gatheringStatistics - private ListenableFuture collectFlowStatistics(final MultipartType multipartType, final boolean initial) { - return devState.isFlowStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringOnTheFlyService, - getDeviceInfo(), - /*MultipartType.OFPMPFLOW*/ multipartType, - deviceContext, - deviceContext, - initial, multipartReplyTranslator) : emptyFuture; - } - - private ListenableFuture collectTableStatistics(final MultipartType multipartType) { - return devState.isTableStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, - getDeviceInfo(), - /*MultipartType.OFPMPTABLE*/ multipartType, - deviceContext, - deviceContext, - false, multipartReplyTranslator) : emptyFuture; - } - - private ListenableFuture collectPortStatistics(final MultipartType multipartType) { - return devState.isPortStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, - getDeviceInfo(), - /*MultipartType.OFPMPPORTSTATS*/ multipartType, - deviceContext, - deviceContext, - false, multipartReplyTranslator) : emptyFuture; - } - - private ListenableFuture collectQueueStatistics(final MultipartType multipartType) { - return !devState.isQueueStatisticsAvailable() ? emptyFuture : StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, - getDeviceInfo(), - /*MultipartType.OFPMPQUEUE*/ multipartType, - deviceContext, - deviceContext, - false, multipartReplyTranslator); - } - private ListenableFuture collectGroupDescStatistics(final MultipartType multipartType) { - return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, - getDeviceInfo(), - /*MultipartType.OFPMPGROUPDESC*/ multipartType, - deviceContext, - deviceContext, - false, multipartReplyTranslator) : emptyFuture; - } + return Futures.immediateFailedFuture(new ConnectionException(errMsg)); + } - private ListenableFuture collectGroupStatistics(final MultipartType multipartType) { - return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, - getDeviceInfo(), - /*MultipartType.OFPMPGROUP*/ multipartType, - deviceContext, - deviceContext, - false, multipartReplyTranslator) : emptyFuture; + return Futures.immediateFuture(Boolean.TRUE); } - private ListenableFuture collectMeterConfigStatistics(final MultipartType multipartType) { - return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, + private ListenableFuture collectStatistics(final MultipartType multipartType, + final boolean supported, + final boolean onTheFly) { + // TODO: Refactor twice sending deviceContext into gatheringStatistics + return supported ? StatisticsGatheringUtils.gatherStatistics( + onTheFly ? statisticsGatheringOnTheFlyService : statisticsGatheringService, getDeviceInfo(), - /*MultipartType.OFPMPMETERCONFIG*/ multipartType, + multipartType, deviceContext, deviceContext, - false, multipartReplyTranslator) : emptyFuture; - } - - private ListenableFuture collectMeterStatistics(final MultipartType multipartType) { - return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics( - statisticsGatheringService, - getDeviceInfo(), - /*MultipartType.OFPMPMETER*/ multipartType, - deviceContext, - deviceContext, - false, multipartReplyTranslator) : emptyFuture; + convertorExecutor, + statisticsWriterProvider) : Futures.immediateFuture(Boolean.FALSE); } @VisibleForTesting - void setStatisticsGatheringService(final StatisticsGatheringService statisticsGatheringService) { + void setStatisticsGatheringService(final StatisticsGatheringService statisticsGatheringService) { this.statisticsGatheringService = statisticsGatheringService; } @VisibleForTesting - void setStatisticsGatheringOnTheFlyService(final StatisticsGatheringOnTheFlyService - statisticsGatheringOnTheFlyService) { + void setStatisticsGatheringOnTheFlyService(final StatisticsGatheringOnTheFlyService statisticsGatheringOnTheFlyService) { this.statisticsGatheringOnTheFlyService = statisticsGatheringOnTheFlyService; } @@ -424,30 +299,23 @@ class StatisticsContextImpl implements StatisticsContext { } @Override - public CONTEXT_STATE getState() { - return this.state; - } - - @Override - public ServiceGroupIdentifier getServiceIdentifier() { - return this.deviceInfo.getServiceIdentifier(); + public DeviceInfo getDeviceInfo() { + return this.deviceInfo; } @Override - public DeviceInfo getDeviceInfo() { - return this.deviceInfo; + public void registerMastershipWatcher(@Nonnull final ContextChainMastershipWatcher contextChainMastershipWatcher) { + this.contextChainMastershipWatcher = contextChainMastershipWatcher; } @Override - public ListenableFuture stopClusterServices(boolean connectionInterrupted) { - if (CONTEXT_STATE.TERMINATION.equals(getState())) { - return Futures.immediateCancelledFuture(); - } + public ListenableFuture closeServiceInstance() { + LOG.info("Stopping statistics context cluster services for node {}", deviceInfo.getLOGValue()); - return Futures.transform(Futures.immediateFuture(null), new Function() { + return Futures.transform(Futures.immediateFuture(null), new Function() { @Nullable @Override - public Void apply(@Nullable Object input) { + public Void apply(@Nullable final Void input) { schedulingEnabled = false; stopGatheringData(); return null; @@ -462,58 +330,65 @@ class StatisticsContextImpl implements StatisticsContext { @Override public DeviceContext gainDeviceContext() { - return this.lifecycleService.getDeviceContext(); + return this.deviceContext; } @Override public void stopGatheringData() { - if (Objects.nonNull(this.lastDataGathering)) { - if (LOG.isDebugEnabled()) { - LOG.debug("Stop the running statistics gathering for node {}", this.deviceInfo.getLOGValue()); - } + LOG.info("Stopping running statistics gathering for node {}", deviceInfo.getLOGValue()); + if (Objects.nonNull(lastDataGathering) && !lastDataGathering.isDone() && !lastDataGathering.isCancelled()) { lastDataGathering.cancel(true); } - } - @Override - public void setLifecycleInitializationPhaseHandler(final ClusterInitializationPhaseHandler handler) { - this.clusterInitializationPhaseHandler = handler; + if (Objects.nonNull(pollTimeout) && !pollTimeout.isExpired()) { + pollTimeout.cancel(); + } } @Override - public boolean onContextInstantiateService(final ConnectionContext connectionContext) { - if (connectionContext.getConnectionState().equals(ConnectionContext.CONNECTION_STATE.RIP)) { - LOG.warn("Connection on device {} was interrupted, will stop starting master services.", deviceInfo.getLOGValue()); - return false; - } - + public void instantiateServiceInstance() { LOG.info("Starting statistics context cluster services for node {}", deviceInfo.getLOGValue()); - this.statListForCollectingInitialization(); - Futures.addCallback(this.initialGatherDynamicData(), new FutureCallback() { + Futures.addCallback(this.gatherDynamicData(), new FutureCallback() { @Override public void onSuccess(@Nullable Boolean aBoolean) { - initialSubmitHandler.initialSubmitTransaction(); + contextChainMastershipWatcher.onMasterRoleAcquired( + deviceInfo, + ContextChainMastershipState.INITIAL_GATHERING + ); + + if (deviceContext.initialSubmitTransaction()) { + contextChainMastershipWatcher.onMasterRoleAcquired( + deviceInfo, + ContextChainMastershipState.INITIAL_SUBMIT + ); + + if (isStatisticsPollingOn) { + myManager.startScheduling(deviceInfo); + } + } else { + contextChainMastershipWatcher.onNotAbleToStartMastershipMandatory( + deviceInfo, + "Initial transaction cannot be submitted." + ); + } } @Override - public void onFailure(Throwable throwable) { - LOG.warn("Initial gathering statistics unsuccessful for node {}", deviceInfo.getLOGValue()); - lifecycleService.closeConnection(); + public void onFailure(@Nonnull Throwable throwable) { + contextChainMastershipWatcher.onNotAbleToStartMastershipMandatory( + deviceInfo, + "Initial gathering statistics unsuccessful." + ); } }); - - if (this.isStatisticsPollingOn) { - myManager.startScheduling(deviceInfo); - } - - return this.clusterInitializationPhaseHandler.onContextInstantiateService(connectionContext); } + @Nonnull @Override - public void setInitialSubmitHandler(final ClusterInitializationPhaseHandler initialSubmitHandler) { - this.initialSubmitHandler = initialSubmitHandler; + public ServiceGroupIdentifier getIdentifier() { + return deviceInfo.getServiceIdentifier(); } -} \ No newline at end of file +}