/* ==================================================================== * The Vovida Software License, Version 1.0 * * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The names "VOCAL", "Vovida Open Communication Application Library", * and "Vovida Open Communication Application Library (VOCAL)" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor * may "VOCAL" appear in their name, without prior written * permission of Vovida Networks, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * ==================================================================== * * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc. For more information on Vovida Networks, Inc., please see * . * */ static const char* const Server_cxx_Version = "$Id: Server.cxx,v 1.20 2002/02/25 05:46:18 sprajpat Exp $"; #include "cpLog.h" #include "Server.hxx" #include "HeartbeatParms.hxx" #include "HeartbeatUtil.h" /** * Constructor * @param serverType Type of server to be created */ Server::Server( const ServerType serverType) : itsType(serverType), itsStatus(Inactive), heartbeatCount(0), numOfHeartbeatMissed(0) { itsMaxMissedHB = HeartbeatParms::instance().getMaxMissedHeartbeats(); } /** * Constructor provided for applications that don't talk to provisioning. * @param serverType Type of server to be created * @param maxMissedHB the maximum number of heartbeat could be missed */ Server::Server( const ServerType serverType, const int maxMissedHB) : itsType(serverType), itsStatus(Inactive), heartbeatCount(0), numOfHeartbeatMissed(0), itsMaxMissedHB(maxMissedHB) {} /** * Copy Constructor * @param rhs Object from which to copy */ Server::Server( const Server& rhs ) { if (this != &rhs) { copyRhsToThis( rhs ); } } /** * Operator overload for "=" * @param rhs Object from which to copy * @return Reference to this object with new data */ Server& Server::operator=( const Server& rhs ) { if ( this != &rhs ) { copyRhsToThis( rhs ); } return *this; } /** * Copy member data from given object into this one * @param rhs Object from which to copy */ void Server::copyRhsToThis( const Server& rhs ) { itsType = rhs.itsType; itsStatus = rhs.itsStatus; heartbeatCount = rhs.heartbeatCount; numOfHeartbeatMissed = rhs.numOfHeartbeatMissed; itsMaxMissedHB = rhs.itsMaxMissedHB; } /** * Destructor */ Server::~Server() { } /** * Obtain the server's type * @return The server's type */ ServerType Server::getType() const { return itsType; } /** * Obtain the status of this server * @return This server's status */ ServerStatus Server::getStatus() const { return itsStatus; } /** * Obtain the current heartbeat count * @return The number of heartbeats counted for this server */ int Server::getHeartbeatCount() const { return heartbeatCount; } /** * Obtain the number of heartbeats missed for this server * @return Number of heartbeats missed */ int Server::getNumOfHeartbeatMissed() const { return numOfHeartbeatMissed; } /** * Obtain the maximum number of heartbeats allowed before the server * is considered to be down. * @return Max number of missed heartbeats */ int Server::getMaxMissedHB() const { return itsMaxMissedHB; } /** * Store the maximum number of missed heartbeats * @param Maximum number of missed heartbeats */ void Server::setMaxMissedHB( const int maxMissedHB ) { itsMaxMissedHB = maxMissedHB; } /** * Handle an incoming heartbeat by updating the server's counts * @param key Server's address */ void Server::processHeartbeat( const Data& key ) { incrHeartbeatCountByOne(); if (itsStatus == Inactive) { gotFirstHeartbeat(key); } else if (itsStatus == ActivePending ) { gotHiccup(); } } /** * Handle the first heartbeat for the given server by changing its state to active. * @param key Server's address */ void Server::gotFirstHeartbeat( const Data& key ) { setStatus(Active); displayStatus(key); } void Server::displayStatus(const Data& key) { cpLog( LOG_ALERT, "\n"); cpLog( LOG_ALERT, "** %s Up: %s **", convertToString(itsType), key.logData() ); } /** * Handle receiving a heartbeat after one or more was missed by making * the server active. */ void Server::gotHiccup() { /// first heartbeat received after losing /// 1..(maxHBloss-1) beats. /// Assume for now that hiccups are ignored setStatus(Active); /// reset hb missed counter clearNumOfHeartbeatMissed(); } /** * Increment the count of heartbeats received. */ void Server::incrHeartbeatCountByOne() { heartbeatCount++; } /** * Increment the count of heartbeats missed. */ void Server::incrNumOfHeartbeatMissed() { numOfHeartbeatMissed++; } /** * Check to see if a server is no longer heartbeating. * @return True if the max number of heartbeats missed has exceeded the * allowed limit, false if not. */ bool Server::serverIsDead() const { /// dead if missed max number of HB's allowed if ( numOfHeartbeatMissed >= itsMaxMissedHB ) { return true; } return false; } /** * Check if given server is no longer heartbeating and * change its state accordingly. Clear the counts if necessary * @param serverId Address of server */ void Server::doHouseKeeping( const Data& serverId ) { if ( itsStatus != Inactive ) { if ( heartbeatCount == 0 ) { incrNumOfHeartbeatMissed(); /// *** keep this code around in case we decide /// *** to reinstate the ActivePending state. ///if ( itsStatus == Active) /// setStatus(ActivePending); cpLog( LOG_DEBUG_HB,"missed %d HBs", numOfHeartbeatMissed); if ( serverIsDead() ) { setStatus(Inactive); cpLog( LOG_ALERT, "\n"); cpLog( LOG_ALERT, "** %s Down: %s **", convertToString(itsType), serverId.logData() ); /// clear HB counters clearHeartbeatCount(); clearNumOfHeartbeatMissed(); } } else { /// clear HB counters clearHeartbeatCount(); clearNumOfHeartbeatMissed(); } } } /** * Store the server type * @param type Type of server */ void Server::setType( const ServerType type ) { itsType = type; } /** * Store the server's current status * @param status Status of server */ void Server::setStatus( const ServerStatus status ) { itsStatus = status; } /** * Reset the heartbeat count to zero */ void Server::clearHeartbeatCount () { heartbeatCount = 0; } /** * Reset the number of missed heartbeats to zero */ void Server::clearNumOfHeartbeatMissed () { numOfHeartbeatMissed = 0; }