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 org.apache.log4j.Logger;
import com.linkedin.databus.client.pub.DatabusClientGroupMember;
public class DatabusClientDSCUpdater implements Runnable
{
public static final String MODULE = DatabusClientDSCUpdater.class.getName();
public static final Logger LOG = Logger.getLogger(MODULE);
public static final String DSCKEY = "dscLastWriteTimestamp";
private enum State {INIT,RUNNING,STOPPED};
private final DatabusClientGroupMember _groupMember;
private final LastWriteTimeTrackerImpl _writeTimeTracker;
private final long _dscUpdateDelayInMs ;
private boolean _shutdownRequested =false;
private State _state = State.INIT ;
public DatabusClientDSCUpdater(DatabusClientGroupMember groupMember,
LastWriteTimeTrackerImpl writeTimeTracker,
long dscUpdateDelayInMs)
{
_groupMember=groupMember;
_writeTimeTracker = writeTimeTracker;
_dscUpdateDelayInMs = dscUpdateDelayInMs;
}
public void init()
{
_state = State.INIT;
_shutdownRequested = false;
}
/** Required to read timestamp **/
@Override
public void run()
{
try
{
if (_writeTimeTracker != null)
{
LOG.info("Started! DSC Updater thread started with clientNode=" + _groupMember);
_state = State.RUNNING;
while (!_shutdownRequested)
{
//read and update _writeTimeTracker
long lastWriteTimeMillis = getTimestamp();
if (lastWriteTimeMillis > 0 )
{
//thread-safe ; update time tracker locally to enable DSC router to obtain the last write update timestamp of the cluster
if (lastWriteTimeMillis > _writeTimeTracker.getLastWriteTimeMillis())
{
_writeTimeTracker.setLastWriteTimeMillis(lastWriteTimeMillis);
}
else
{
LOG.info("DSCUpdater: Skipping update of lastWriteEventTimestamp: current= " + _writeTimeTracker.getLastWriteTimeMillis() + " new=" + lastWriteTimeMillis);
}
}
Thread.sleep(_dscUpdateDelayInMs);
}
}
} catch (InterruptedException e)
{
LOG.info("DSC Updater thread interrupted!");
}
synchronized (this)
{
_state = State.STOPPED;
this.notify();
}
LOG.info("DSC Updater thread stopped!");
}
/** return 0 on error; otherwise returns timestamp */
public long getTimestamp()
{
if (_groupMember != null)
{
Long ts = (Long) _groupMember.readSharedData(DSCKEY);
if (ts != null)
{
return ts.longValue();
}
else
{
LOG.info("DSCUpdater: error reading " + DSCKEY + " from " + _groupMember);
}
}
else
{
return getLocalTimestamp();
}
return 0;
}
/** return 0 on error; otherwise returns timestamp */
public long getLocalTimestamp()
{
if (_writeTimeTracker != null)
{
return _writeTimeTracker.getLastWriteTimeMillis();
}
return 0;
}
/** Has thread terminated or interrupted? Returns false if thread was never run*/
public boolean isStopped()
{
return _state == State.STOPPED;
}
/** Is thread running */
public boolean isRunning()
{
return _state == State.RUNNING;
}
/** Asynchronous stop request **/
public synchronized void stop()
{
_shutdownRequested = true;
}
/** blocking call
* return status of thread; **/
public synchronized boolean awaitShutdown()
{
try
{
while (_state != State.STOPPED)
{
this.wait();
}
}
catch (InterruptedException e)
{
LOG.info("DSC Thread interrupted while awaiting shutdown! ");
}
return _state == State.STOPPED;
}
public void writeLocalTimestamp(long timestampInMillis)
{
// write to local memory
if (_writeTimeTracker != null)
{
//threadsafe
_writeTimeTracker.setLastWriteTimeMillis(timestampInMillis);
}
}
public void writeTimestamp(long timestampInMillis)
{
writeLocalTimestamp(timestampInMillis);
//write to shared location;
if (_groupMember != null )
{
_groupMember.writeSharedData(DSCKEY,timestampInMillis);
}
}
}