package com.linkedin.databus.client;
/*
*
* Copyright 2013 LinkedIn Corp. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import java.util.List;
import javax.management.MBeanServer;
import org.apache.log4j.Logger;
import com.linkedin.databus.client.DatabusSourcesConnection.StaticConfig;
import com.linkedin.databus.client.consumer.MultiConsumerCallback;
import com.linkedin.databus.client.pub.CheckpointPersistenceProvider;
import com.linkedin.databus.client.pub.DatabusCombinedConsumer;
import com.linkedin.databus.client.pub.RegistrationId;
import com.linkedin.databus.core.Checkpoint;
import com.linkedin.databus.core.DbusClientMode;
import com.linkedin.databus.core.DbusEvent;
import com.linkedin.databus.core.DbusEventBuffer;
import com.linkedin.databus.core.DbusEventUtils;
import com.linkedin.databus.core.DbusPrettyLogUtils;
import com.linkedin.databus.core.SCNRegressMessage;
import com.linkedin.databus.core.async.LifecycleMessage;
import com.linkedin.databus.core.data_model.DatabusSubscription;
public class RelayDispatcher extends GenericDispatcher<DatabusCombinedConsumer>
{
private final BootstrapPullThread _bootstrapPuller;
public RelayDispatcher(String name,
StaticConfig connConfig,
List<DatabusSubscription> subsList,
CheckpointPersistenceProvider checkpointPersistor,
DbusEventBuffer dataEventsBuffer,
MultiConsumerCallback asyncCallback,
BootstrapPullThread bootstrapPuller,
MBeanServer mbeanServer,
DatabusHttpClientImpl serverHandle,
RegistrationId registrationId,
Logger log)
{
super(name, connConfig, subsList, checkpointPersistor, dataEventsBuffer, asyncCallback, mbeanServer,
serverHandle, registrationId, connConfig.getDispatcherRetries(), log);
_bootstrapPuller = bootstrapPuller;
}
@Override
protected Checkpoint createCheckpoint(DispatcherState curState, DbusEvent event)
{
return createOnlineConsumptionCheckpoint(_lastWindowScn, _lastEowTsNsecs, curState, event);
}
@Override
protected boolean processSysEvent(DispatcherState curState, DbusEvent event)
{
boolean success = true;
if (event.isCheckpointMessage())
{
Checkpoint ckpt = null;
try
{
ckpt = DbusEventUtils.getCheckpointFromEvent(event);
DbusClientMode bootstrapMode = ckpt.getConsumptionMode();
if (bootstrapMode != DbusClientMode.ONLINE_CONSUMPTION)
{
if(_bootstrapPuller == null) {
_log.error("Checkpoint specifies that the consumer is bootstrapping, but bootstrapPuller is not present (Is bootstrap disabled ?)");
return false;
}
ckpt.setConsumptionMode(DbusClientMode.BOOTSTRAP_SNAPSHOT);
if (curState.getStateId() != DispatcherState.StateId.EXPECT_EVENT_WINDOW)
{
_log.warn("The current state of the dispatcher is NOT as expected (" + DispatcherState.StateId.EXPECT_EVENT_WINDOW.name() + "). State prior to this: " + curState.getStateId().name());
//Fixing bug that caused TestRelayBootstrapSwitch to fail; no apparent need to rollback
//curState.switchToRollback();
//doRollback(curState);
}
curState.getEventsIterator().getEventBuffer().clear();
curState.resetIterators();
curState.switchToExpectEventWindow();
_bootstrapPuller.enqueueMessage(LifecycleMessage.createStartMessage());
_log.info("Switching to bootstrap mode");
}
else
{
success = super.processSysEvent(curState, event);
}
}
catch (Exception e )
{
DbusPrettyLogUtils.logExceptionAtError("Internal error processing a system event", e, _log);
success = false;
}
}
else if (event.isSCNRegressMessage())
{
SCNRegressMessage message = DbusEventUtils.getSCNRegressFromEvent(event);
_log.info("Switching relays, some of the events maybe replayed. The Checkpoint to which the client with regress: " + message);
curState.setSCNRegress(true);
curState.switchToExpectEventWindow();
//enqueueMessage(curState);
}
else
{
success = super.processSysEvent(curState, event);
}
return success;
}
}