/*=========================================================================
 * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
 * This product is protected by U.S. and international copyright
 * and intellectual property laws. Pivotal products are covered by
 * more patents listed at http://www.pivotal.io/patents.
 *========================================================================
 */


#include "ThinClientHARegion.hpp"
#include "TcrHADistributionManager.hpp"
#include "CacheImpl.hpp"
#include "../SystemProperties.hpp"
#include "ReadWriteLock.hpp"
#include "../PoolManager.hpp"
#include "ThinClientPoolHADM.hpp"
namespace gemfire
{

  ThinClientHARegion::ThinClientHARegion( const std::string& name,
      CacheImpl* cache, RegionInternal* rPtr,
      const RegionAttributesPtr& attributes, const CacheStatisticsPtr& stats,
      bool shared, bool enableNotification )
    : m_processedMarker( false ), m_attribute( attributes ), ThinClientRegion( name, cache, rPtr, attributes, stats, shared ),
    /* adongre
     * CID 28976: Uninitialized scalar field (UNINIT_CTOR)
     */
    m_poolDM(false)
  {
    setClientNotificationEnabled( enableNotification );
  }

  void ThinClientHARegion::initTCR()
  {
    try {
      bool isPool = m_attribute->getPoolName() != NULL && strlen(m_attribute->getPoolName()) > 0;
      if( DistributedSystem::getSystemProperties()->isGridClient() ) {
        LOGWARN("Region: HA region having notification channel created for grid "
          "client; force starting required notification, cleanup and "
          "failover threads");
        m_cacheImpl->tcrConnectionManager().startFailoverAndCleanupThreads(isPool);
      }

      if( m_attribute->getPoolName() == NULL || strlen(m_attribute->getPoolName()) == 0 ){
        m_poolDM = false;
        m_tcrdm = new TcrHADistributionManager(this,m_cacheImpl->tcrConnectionManager(), m_cacheImpl->getAttributes());
        m_tcrdm->init();
      }
      else {
        m_tcrdm =dynamic_cast< ThinClientPoolHADM* >( PoolManager::find( m_attribute->getPoolName( ) ).ptr( ) );
        if( m_tcrdm ) {
          m_poolDM = true;
          //Pool DM should only be inited once and it
          //is already done in PoolFactory::create();
          //m_tcrdm->init();
          ThinClientPoolHADM* poolDM = dynamic_cast< ThinClientPoolHADM* >( m_tcrdm );
          poolDM->addRegion( this );
          poolDM->incRegionCount( );


        } else {
          throw IllegalStateException( "pool not found" );
        }
      }
    }
    catch (const Exception& ex) {
      GF_SAFE_DELETE(m_tcrdm);
      LOGERROR("ThinClientHARegion: failed to create a DistributionManager "
      "object due to: %s: %s", ex.getName(), ex.getMessage());
      throw;
    }

  }

  void ThinClientHARegion::acquireGlobals(bool isFailover)
  {
    if (isFailover) {
      ThinClientRegion::acquireGlobals(isFailover);
    }
    else {
      m_tcrdm->acquireRedundancyLock( );
    }
  }

  void ThinClientHARegion::releaseGlobals(bool isFailover)
  {
    if (isFailover) {
      ThinClientRegion::releaseGlobals(isFailover);
    }
    else {
      m_tcrdm->releaseRedundancyLock( );
    }
  }

  void ThinClientHARegion::handleMarker()
  {
    TryReadGuard guard( m_rwLock, m_destroyPending);
    if( m_destroyPending ) {
      return;
    }

    if ( m_listener != NULLPTR && !m_processedMarker) {
      RegionEvent event(RegionPtr(this), NULLPTR, false);
      int64 sampleStartNanos =Utils::startStatOpTime();
      try {
        m_listener->afterRegionLive(event);
      }
      catch (const Exception& ex) {
        LOGERROR("Exception in CacheListener::afterRegionLive: %s: %s", ex.getName(), ex.getMessage());
      }
      catch (...) {
        LOGERROR( "Unknown exception in CacheListener::afterRegionLive");
      }
      m_cacheImpl->m_cacheStats->incListenerCalls();
      Utils::updateStatOpTime(m_regionStats->getStat(), RegionStatType::getInstance()->getListenerCallTimeId(), sampleStartNanos);
      m_regionStats->incListenerCallsCompleted();
    }
    m_processedMarker = true;
  }

  bool ThinClientHARegion::getProcessedMarker()
  {
    return m_processedMarker || !isDurableClient();
  }

  void ThinClientHARegion::destroyDM( bool keepEndpoints )
  {
    if ( m_poolDM ) {
      LOGDEBUG( "ThinClientHARegion::destroyDM( ): removing region from ThinClientPoolHADM list." );
      ThinClientPoolHADM* poolDM = dynamic_cast< ThinClientPoolHADM* >( m_tcrdm );
      poolDM->removeRegion( this );
      poolDM->decRegionCount( );
    }
    else {
      ThinClientRegion::destroyDM( keepEndpoints );
    }
  }
}

void ThinClientHARegion::addDisMessToQueue()
{
  if( m_poolDM ){
    ThinClientPoolHADM* poolDM = dynamic_cast< ThinClientPoolHADM* >( m_tcrdm );
    poolDM->addDisMessToQueue( this );

    if( poolDM->m_redundancyManager->m_globalProcessedMarker && !m_processedMarker ){
      TcrMessage* regionMsg = new TcrMessage( );
      regionMsg->setMessageType( TcrMessage::CLIENT_MARKER );
      receiveNotification( regionMsg );
    }
  }
}

GfErrType ThinClientHARegion::getNoThrow_FullObject( EventIdPtr eventId, CacheablePtr& fullObject, VersionTagPtr& versionTag )
{
  TcrMessage fullObjectMsg( eventId );
  TcrMessage reply;

  ThinClientPoolHADM* poolHADM = dynamic_cast< ThinClientPoolHADM* >( m_tcrdm );
  GfErrType err = GF_NOTCON;
  if ( poolHADM ) {
    err = poolHADM->sendRequestToPrimary( fullObjectMsg, reply );
  }
  else {
    err = static_cast< TcrHADistributionManager* >( m_tcrdm )->sendRequestToPrimary( fullObjectMsg, reply );
  }
  if ( err == GF_NOERR ) {
    fullObject = reply.getValue( );
  }
  versionTag = reply.getVersionTag();
  return err;
}

