/* ====================================================================
 * 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
 * <http://www.vovida.org/>.
 *
 */

static const char* const BaseServerContainer_cxx_Version =
    "$Id: BaseServerContainer.cxx,v 1.23 2002/09/06 09:00:42 bko Exp $";
#include "cpLog.h"
#include "SnmpCommon.h"
#include "BaseServerContainer.hxx"
#include "HeartbeatUtil.h"
#include "ReadLockHelper.hxx"
#include "WriteLockHelper.hxx"
#include "CommandLine.hxx"

/**
 * Constructor
 */
BaseServerContainer::BaseServerContainer()
{
    // no heartbeat debug messages
    heartbeatDebug = false;
}

/**
 * Copy Constructor
 * @param rhs Element to be copied
 */
BaseServerContainer::BaseServerContainer( const BaseServerContainer& rhs )
{
    if (this != &rhs)
        copyRhsToThis( rhs );
}

/**
 * Assignment Operator
 * @param rhs Element contains data to copy
 * @return This element
 */
BaseServerContainer&
BaseServerContainer::operator=( const BaseServerContainer& rhs )
{
    if ( this != &rhs )
    {
        copyRhsToThis( rhs );
    }
    return *this;
}


/**
 * Copy data from an element into self
 * @param rhs Element contains data to copy
 */
void
BaseServerContainer::copyRhsToThis( const BaseServerContainer& rhs )
{
    serverList = rhs.serverList;
    heartbeatDebug = rhs.heartbeatDebug;
}


/**
 * Check if HeartbeatDebug flag is On
 * @return true/false  
 */
bool
BaseServerContainer::isHeartbeatDebugOn()
{
    return heartbeatDebug;
}


/**
 * Turn HeartbeatDebug flag On 
 */
void
BaseServerContainer::turnHeartbeatDebugOn()
{
    heartbeatDebug = true;
}

/**
 * Destructor
 */
BaseServerContainer::~BaseServerContainer( )
{}

/**
 * Get the server type using the key  
 * @param key ip address
 * @return server type  
 */
ServerType
BaseServerContainer::getType( const Data& key )
{
    TableIter i;

    ReadLockHelper tableHelper(tableLock);

    /// Search the container for the key
    i = serverList.find(key);

    if (i == serverList.end())
        return SERVER_Unknown;
    else
    {
        /// Retrieve the Server
        return (i->second)->getType();
    }

}


/**
 * Get the status of a particular server using the key  
 * @param key ip address
 * @return server status  
 */
ServerStatus
BaseServerContainer::getStatus( const Data& key )
{
    TableIter i;

    ReadLockHelper tableHelper(tableLock);

    /// Search the container for the key
    i = serverList.find(key);

    if (i == serverList.end())
        return Inactive;
    else
    {
        /// Retrieve the Server
        return (i->second)->getStatus();
    }

}

/**
 * Add a new server to the container   
 * @param key ip address
 * @param serverType type of server 
 */
void
BaseServerContainer::addServer( const Data& key, const ServerType serverType)
{
    cpLog( LOG_DEBUG, "entering ServerContainer::add");

    /// create a Server with 'new'
    Sptr < Server > server = new Server( serverType );
    addServer(key, server);
}

/**
 * Add a new server to the container (for applications that do not get data from provisioning) 
 * @param key ip address
 * @param serverType type of server 
 * @param maxMissedHB maximum # of heartbeats missed allowed before a server is considered dead. 
 */
void
BaseServerContainer::addServer( const Data& key, const ServerType serverType, const int maxMissedHB)
{
    cpLog( LOG_DEBUG, "entering ServerContainer::add");

    /// create a Server with 'new'
    Sptr < Server > server = new Server( serverType, maxMissedHB );
    addServer(key, server);

}

void
BaseServerContainer::addServer(const Data& key, Sptr < Server > server)
{
    WriteLockHelper tableHelper(tableLock);

    /// insert the Server in the map
    serverList[key] = server;
    if(!CommandLine::instance()->getInt("HEARTBEAT"))
    {
        cpLog( LOG_INFO, "Heartbeat mechanism is disabled, setting server (%s) to be active", key.logData());
        server->setStatus(Active);
        server->displayStatus(key);
    }
}

/**
 * Remove a server from the Container.  
 * @param key ip address
 */
void
BaseServerContainer::remove(const Data& key )
{
    cpLog( LOG_DEBUG, "BaseServerContainer::remove");
    TableIter i;

    WriteLockHelper tableHelper(tableLock);

    /// Find the Server in the database using the key
    i = serverList.find(key);

    /// Verify that a Server was found
    if (i != serverList.end())
    {
        /// remove the key/Server from the map
        serverList.erase(i);
    }

}


/**
 * Return the Server object which corresponds to the key 
 * @param key ip address
 * @param server server object 
 * @return true/false 
 */
bool
BaseServerContainer::search( const Data& key, Sptr < Server > & server )
{
    TableIter i;

    ReadLockHelper tableHelper(tableLock);

    /// Search the container for the key
    i = serverList.find(key);

    if (i == serverList.end())
        return false;
    else
    {
        /// Retrieve the Server
        server = i->second;
        return true;
    }

}

/**
 * Display attributes of a server given the key 
 * @param key ip address
 */
void
BaseServerContainer::display( const Data& key)
{
    Sptr < Server > serverPtr;
    cpLog( LOG_DEBUG, "key: %s", key.logData());

    /// Find the Server in the container
    if (search(key, serverPtr))
    {
        ReadLockHelper tableHelper(tableLock);
        displayServer( *serverPtr );
    }
    else
        cpLog(LOG_DEBUG, "Server not in system");
}


/**
 * Display attributes of a server given the server object 
 * @param server server object 
 */
void
BaseServerContainer::displayServer( const Server& serverPtr)
{
    /// print data contained in the server object
    cpLog( LOG_DEBUG_HB, "------------------------");
    cpLog( LOG_DEBUG_HB, "ServerType: %s", convertToString( serverPtr.getType() ) );
    cpLog( LOG_DEBUG_HB, "Status: %s", convertToString( serverPtr.getStatus() ) );
    cpLog( LOG_DEBUG_HB, "HB Count: %d  #Missed: %d", serverPtr.getHeartbeatCount(),
           serverPtr.getNumOfHeartbeatMissed() );
    cpLog( LOG_DEBUG_HB, "------------------------");

}

// End of File


syntax highlighted by Code2HTML, v. 0.9.1