<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/plat/prdfPlatServices_ipl.C $               */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

/**
 * @file  prdfPlatServices_ipl.C
 * @brief Wrapper code for external interfaces used by PRD (IPL only).
 *
 * This file contains code that is strictly specific to Hostboot. All code that
 * is common between FSP and Hostboot should be in the respective common file.
 */

#include <prdfPlatServices.H>

#include <prdfGlobal.H>
#include <prdfErrlUtil.H>
#include <prdfTrace.H>

//#include <prdfCenDqBitmap.H> TODO RTC 164707
#include <prdfMemScrubUtils.H>

#include <diag/mdia/mdia.H>
#include <config.h>

using namespace TARGETING;

namespace PRDF
{

namespace PlatServices
{

//##############################################################################
//##                        Memory specific functions
//##############################################################################

bool isInMdiaMode()
{
    bool o_isInMdiaMode = false;
#ifndef CONFIG_VPO_COMPILE
    MDIA::waitingForMaintCmdEvents(o_isInMdiaMode);
#endif
    return o_isInMdiaMode;
}

//------------------------------------------------------------------------------

int32_t mdiaSendEventMsg( TargetHandle_t i_trgt,
                          MDIA::MaintCommandEventType i_eventType )
{
    #define PRDF_FUNC "[PlatServices::mdiaSendEventMsg] "

    int32_t o_rc = SUCCESS;

#ifndef CONFIG_VPO_COMPILE

    PRDF_ASSERT( nullptr != i_trgt );

    // Only MCBIST and MBA supported.
    TYPE trgtType = getTargetType( i_trgt );
    PRDF_ASSERT( TYPE_MCBIST == trgtType || TYPE_MBA == trgtType );

    // MDIA must be running.
    PRDF_ASSERT( isInMdiaMode() );

    // Send command complete to MDIA.
    MDIA::MaintCommandEvent mdiaEvent;
    mdiaEvent.target = i_trgt;
    mdiaEvent.type   = i_eventType;

    errlHndl_t errl = MDIA::processEvent( mdiaEvent );
    if ( NULL != errl )
    {
        PRDF_ERR( PRDF_FUNC "MDIA::processEvent() failed: i_target=0x%08x "
                  "i_eventType=%d", getHuid(i_trgt), i_eventType );
        PRDF_COMMIT_ERRL( errl, ERRL_ACTION_REPORT );
        o_rc = FAIL;
    }

#endif

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

bool rcdParityErrorReconfigLoop()
{
    TargetHandle_t top = getSystemTarget();

    // Check the current reconfig count.
    uint8_t allowed = top->getAttr<ATTR_RCD_PARITY_RECONFIG_LOOPS_ALLOWED>();
    uint8_t count   = top->getAttr<ATTR_RCD_PARITY_RECONFIG_LOOP_COUNT>();

    if ( count <= allowed )
    {
        // Set the RCD parity error flag in the reconfig loop attribute. This
        // will trigger a reconfig loop at the end of the current istep.
        ATTR_RECONFIGURE_LOOP_type attr = top->getAttr<ATTR_RECONFIGURE_LOOP>();
        if ( 0 == (attr & RECONFIGURE_LOOP_RCD_PARITY_ERROR) )
        {
            attr |= RECONFIGURE_LOOP_RCD_PARITY_ERROR;
            top->setAttr<ATTR_RECONFIGURE_LOOP>(attr);
        }

        // Increment the count.
        top->setAttr<ATTR_RCD_PARITY_RECONFIG_LOOP_COUNT>(++count);

        return false;
    }

    return true;
}

//------------------------------------------------------------------------------

/* TODO RTC 164707
int32_t mssRestoreDramRepairs( TargetHandle_t i_mbaTarget,
                               uint8_t & o_repairedRankMask,
                               uint8_t & o_badDimmMask )
{
    int32_t o_rc = SUCCESS;

    errlHndl_t errl = NULL;

    FAPI_INVOKE_HWP( errl, mss_restore_DRAM_repairs,
                     fapi::Target(fapi::TARGET_TYPE_MBA_CHIPLET, i_mbaTarget),
                     o_repairedRankMask, o_badDimmMask );

    if ( NULL != errl )
    {
        PRDF_ERR( "[PlatServices::mssRestoreDramRepairs] "
                  "mss_restore_dram_repairs() failed. HUID: 0x%08x",
                  getHuid(i_mbaTarget) );
        PRDF_COMMIT_ERRL( errl, ERRL_ACTION_REPORT );
        o_rc = FAIL;
    }

    return o_rc;
}
*/

//------------------------------------------------------------------------------

/* TODO RTC 157888
int32_t mssIplUeIsolation( TargetHandle_t i_mba, const CenRank & i_rank,
                           CenDqBitmap & o_bitmap )
{
    #define PRDF_FUNC "[PlatServices::mssIplUeIsolation] "

    int32_t o_rc = SUCCESS;

    uint8_t data[MBA_DIMMS_PER_RANK][DIMM_DQ_RANK_BITMAP_SIZE];

    errlHndl_t errl = NULL;
    FAPI_INVOKE_HWP( errl, mss_IPL_UE_isolation, getFapiTarget(i_mba),
                     i_rank.getMaster(), data );
    if ( NULL != errl )
    {
        PRDF_ERR( PRDF_FUNC "mss_IPL_UE_isolation() failed: MBA=0x%08x "
                  "rank=%d", getHuid(i_mba), i_rank.getMaster() );
        PRDF_COMMIT_ERRL( errl, ERRL_ACTION_REPORT );
        o_rc = FAIL;
    }
    else
    {
        o_bitmap = CenDqBitmap ( i_mba, i_rank, data );
    }

    return o_rc;

    #undef PRDF_FUNC
}
*/

//##############################################################################
//##                    Nimbus Maintenance Command wrappers
//##############################################################################

template<>
uint32_t startSfRead<TYPE_MCA>( ExtensibleChip * i_mcaChip,
                                const MemRank & i_rank )
{
    #define PRDF_FUNC "[PlatServices::startSfRead<TYPE_MCA>] "

    PRDF_ASSERT( isInMdiaMode() ); // MDIA must be running.

    PRDF_ASSERT( nullptr != i_mcaChip );
    PRDF_ASSERT( TYPE_MCA == i_mcaChip->getType() );

    uint32_t o_rc = SUCCESS;

    // Get the MCBIST fapi target
    ExtensibleChip * mcbChip = getConnectedParent( i_mcaChip, TYPE_MCBIST );
    fapi2::Target<fapi2::TARGET_TYPE_MCBIST> fapiTrgt ( mcbChip->getTrgt() );

    // Get the stop conditions.
    mss::mcbist::stop_conditions stopCond;
    stopCond.set_pause_on_mpe(mss::ON)
            .set_pause_on_ue(mss::ON)
            .set_nce_inter_symbol_count_enable(mss::ON)
            .set_nce_soft_symbol_count_enable( mss::ON)
            .set_nce_hard_symbol_count_enable( mss::ON);

    // Stop on hard CEs if MNFG CE checking is enable.
    if ( isMfgCeCheckingEnabled() ) stopCond.set_pause_on_nce_hard(mss::ON);

    // Get the first address of the given rank.
    uint32_t port = i_mcaChip->getPos() % MAX_MCA_PER_MCBIST;
    mss::mcbist::address saddr, eaddr;
    mss::mcbist::address::get_srank_range( port,
                                           i_rank.getDimmSlct(),
                                           i_rank.getRankSlct(),
                                           i_rank.getSlave(),
                                           saddr,
                                           eaddr );

    do
    {
        // Clear all of the counters and maintenance ECC attentions.
        o_rc = prepareNextCmd<TYPE_MCBIST>( mcbChip );
        if ( SUCCESS != o_rc )
        {
            PRDF_ERR( PRDF_FUNC "prepareNextCmd(0x%08x) failed",
                      mcbChip->getHuid() );
            break;
        }

        // Start the super fast read command.
        errlHndl_t errl;
        FAPI_INVOKE_HWP( errl, memdiags::sf_read, fapiTrgt, stopCond, saddr );

        if ( nullptr != errl )
        {
            PRDF_ERR( PRDF_FUNC "memdiags::sf_read(0x%08x,%d) failed",
                      mcbChip->getHuid(), i_rank.getMaster() );
            PRDF_COMMIT_ERRL( errl, ERRL_ACTION_REPORT );
            o_rc = FAIL; break;
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

// This specialization only exists to avoid a lot of extra code in some classes.
// The input chip must still be an MCA chip.
template<>
uint32_t startSfRead<TYPE_MCBIST>( ExtensibleChip * i_mcaChip,
                                   const MemRank & i_rank )
{
    return startSfRead<TYPE_MCA>( i_mcaChip, i_rank );
}

//##############################################################################
//##                   Centaur Maintenance Command wrappers
//##############################################################################

template<>
uint32_t startSfRead<TYPE_MBA>( ExtensibleChip * i_mbaChip,
                                const MemRank & i_rank )
{
    #define PRDF_FUNC "[PlatServices::startSfRead<TYPE_MBA>] "

    PRDF_ASSERT( nullptr != i_mbaChip );
    PRDF_ASSERT( TYPE_MBA == i_mbaChip->getType() );

    uint32_t o_rc = SUCCESS;

    do
    {
        // Clear all of the counters and maintenance ECC attentions.
        o_rc = prepareNextCmd<TYPE_MBA>( i_mbaChip );
        if ( SUCCESS != o_rc )
        {
            PRDF_ERR( PRDF_FUNC "prepareNextCmd(0x%08x) failed",
                      i_mbaChip->getHuid() );
            break;
        }

        // Start the background scrub command.
        PRDF_ERR( PRDF_FUNC "function not implemented yet" ); // TODO RTC 157888

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

template<>
uint32_t startVcmPhase1<TYPE_MBA>( ExtensibleChip * i_chip,
                                   const MemRank & i_rank )
{
    #define PRDF_FUNC "[PlatServices::startVcmPhase1<TYPE_MBA>] "

    PRDF_ASSERT( nullptr != i_chip );
    PRDF_ASSERT( TYPE_MBA == i_chip->getType() );

    // TODO RTC 157888
    //  - Start a targeted steer cleanup.
    //  - Stop on RCE ETE (threshold 1).
    //  - The command should always stop at the end of the master rank.

    PRDF_ERR( PRDF_FUNC "function not implemented yet" );

    return SUCCESS;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

template<>
uint32_t startVcmPhase2<TYPE_MBA>( ExtensibleChip * i_chip,
                                   const MemRank & i_rank )
{
    #define PRDF_FUNC "[PlatServices::startVcmPhase2<TYPE_MBA>] "

    PRDF_ASSERT( nullptr != i_chip );
    PRDF_ASSERT( TYPE_MBA == i_chip->getType() );

    // TODO RTC 157888
    //  - Start a targeted super fast read.
    //  - No stop-on-error conditions. Note that RCEs will report as UEs during
    //    read operations. You can still set stop-on-RCE-ETE to be consistent
    //    with phase 1, but it will not have any effect and is not required.
    //  - The command should always stop at the end of the master rank.

    PRDF_ERR( PRDF_FUNC "function not implemented yet" );

    return SUCCESS;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

} // end namespace PlatServices

} // end namespace PRDF

<commit_msg>PRD: set stop-on-AUE during memdiags after TD procedure<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/plat/prdfPlatServices_ipl.C $               */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

/**
 * @file  prdfPlatServices_ipl.C
 * @brief Wrapper code for external interfaces used by PRD (IPL only).
 *
 * This file contains code that is strictly specific to Hostboot. All code that
 * is common between FSP and Hostboot should be in the respective common file.
 */

#include <prdfPlatServices.H>

#include <prdfGlobal.H>
#include <prdfErrlUtil.H>
#include <prdfTrace.H>

//#include <prdfCenDqBitmap.H> TODO RTC 164707
#include <prdfMemScrubUtils.H>

#include <diag/mdia/mdia.H>
#include <config.h>

using namespace TARGETING;

namespace PRDF
{

namespace PlatServices
{

//##############################################################################
//##                        Memory specific functions
//##############################################################################

bool isInMdiaMode()
{
    bool o_isInMdiaMode = false;
#ifndef CONFIG_VPO_COMPILE
    MDIA::waitingForMaintCmdEvents(o_isInMdiaMode);
#endif
    return o_isInMdiaMode;
}

//------------------------------------------------------------------------------

int32_t mdiaSendEventMsg( TargetHandle_t i_trgt,
                          MDIA::MaintCommandEventType i_eventType )
{
    #define PRDF_FUNC "[PlatServices::mdiaSendEventMsg] "

    int32_t o_rc = SUCCESS;

#ifndef CONFIG_VPO_COMPILE

    PRDF_ASSERT( nullptr != i_trgt );

    // Only MCBIST and MBA supported.
    TYPE trgtType = getTargetType( i_trgt );
    PRDF_ASSERT( TYPE_MCBIST == trgtType || TYPE_MBA == trgtType );

    // MDIA must be running.
    PRDF_ASSERT( isInMdiaMode() );

    // Send command complete to MDIA.
    MDIA::MaintCommandEvent mdiaEvent;
    mdiaEvent.target = i_trgt;
    mdiaEvent.type   = i_eventType;

    errlHndl_t errl = MDIA::processEvent( mdiaEvent );
    if ( NULL != errl )
    {
        PRDF_ERR( PRDF_FUNC "MDIA::processEvent() failed: i_target=0x%08x "
                  "i_eventType=%d", getHuid(i_trgt), i_eventType );
        PRDF_COMMIT_ERRL( errl, ERRL_ACTION_REPORT );
        o_rc = FAIL;
    }

#endif

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

bool rcdParityErrorReconfigLoop()
{
    TargetHandle_t top = getSystemTarget();

    // Check the current reconfig count.
    uint8_t allowed = top->getAttr<ATTR_RCD_PARITY_RECONFIG_LOOPS_ALLOWED>();
    uint8_t count   = top->getAttr<ATTR_RCD_PARITY_RECONFIG_LOOP_COUNT>();

    if ( count <= allowed )
    {
        // Set the RCD parity error flag in the reconfig loop attribute. This
        // will trigger a reconfig loop at the end of the current istep.
        ATTR_RECONFIGURE_LOOP_type attr = top->getAttr<ATTR_RECONFIGURE_LOOP>();
        if ( 0 == (attr & RECONFIGURE_LOOP_RCD_PARITY_ERROR) )
        {
            attr |= RECONFIGURE_LOOP_RCD_PARITY_ERROR;
            top->setAttr<ATTR_RECONFIGURE_LOOP>(attr);
        }

        // Increment the count.
        top->setAttr<ATTR_RCD_PARITY_RECONFIG_LOOP_COUNT>(++count);

        return false;
    }

    return true;
}

//------------------------------------------------------------------------------

/* TODO RTC 164707
int32_t mssRestoreDramRepairs( TargetHandle_t i_mbaTarget,
                               uint8_t & o_repairedRankMask,
                               uint8_t & o_badDimmMask )
{
    int32_t o_rc = SUCCESS;

    errlHndl_t errl = NULL;

    FAPI_INVOKE_HWP( errl, mss_restore_DRAM_repairs,
                     fapi::Target(fapi::TARGET_TYPE_MBA_CHIPLET, i_mbaTarget),
                     o_repairedRankMask, o_badDimmMask );

    if ( NULL != errl )
    {
        PRDF_ERR( "[PlatServices::mssRestoreDramRepairs] "
                  "mss_restore_dram_repairs() failed. HUID: 0x%08x",
                  getHuid(i_mbaTarget) );
        PRDF_COMMIT_ERRL( errl, ERRL_ACTION_REPORT );
        o_rc = FAIL;
    }

    return o_rc;
}
*/

//------------------------------------------------------------------------------

/* TODO RTC 157888
int32_t mssIplUeIsolation( TargetHandle_t i_mba, const CenRank & i_rank,
                           CenDqBitmap & o_bitmap )
{
    #define PRDF_FUNC "[PlatServices::mssIplUeIsolation] "

    int32_t o_rc = SUCCESS;

    uint8_t data[MBA_DIMMS_PER_RANK][DIMM_DQ_RANK_BITMAP_SIZE];

    errlHndl_t errl = NULL;
    FAPI_INVOKE_HWP( errl, mss_IPL_UE_isolation, getFapiTarget(i_mba),
                     i_rank.getMaster(), data );
    if ( NULL != errl )
    {
        PRDF_ERR( PRDF_FUNC "mss_IPL_UE_isolation() failed: MBA=0x%08x "
                  "rank=%d", getHuid(i_mba), i_rank.getMaster() );
        PRDF_COMMIT_ERRL( errl, ERRL_ACTION_REPORT );
        o_rc = FAIL;
    }
    else
    {
        o_bitmap = CenDqBitmap ( i_mba, i_rank, data );
    }

    return o_rc;

    #undef PRDF_FUNC
}
*/

//##############################################################################
//##                    Nimbus Maintenance Command wrappers
//##############################################################################

template<>
uint32_t startSfRead<TYPE_MCA>( ExtensibleChip * i_mcaChip,
                                const MemRank & i_rank )
{
    #define PRDF_FUNC "[PlatServices::startSfRead<TYPE_MCA>] "

    PRDF_ASSERT( isInMdiaMode() ); // MDIA must be running.

    PRDF_ASSERT( nullptr != i_mcaChip );
    PRDF_ASSERT( TYPE_MCA == i_mcaChip->getType() );

    uint32_t o_rc = SUCCESS;

    // Get the MCBIST fapi target
    ExtensibleChip * mcbChip = getConnectedParent( i_mcaChip, TYPE_MCBIST );
    fapi2::Target<fapi2::TARGET_TYPE_MCBIST> fapiTrgt ( mcbChip->getTrgt() );

    // Get the stop conditions.
    mss::mcbist::stop_conditions stopCond;
    stopCond.set_pause_on_mpe(mss::ON)
            .set_pause_on_ue(mss::ON)
            .set_pause_on_aue(mss::ON)
            .set_nce_inter_symbol_count_enable(mss::ON)
            .set_nce_soft_symbol_count_enable( mss::ON)
            .set_nce_hard_symbol_count_enable( mss::ON);

    // Stop on hard CEs if MNFG CE checking is enable.
    if ( isMfgCeCheckingEnabled() ) stopCond.set_pause_on_nce_hard(mss::ON);

    // Get the first address of the given rank.
    uint32_t port = i_mcaChip->getPos() % MAX_MCA_PER_MCBIST;
    mss::mcbist::address saddr, eaddr;
    mss::mcbist::address::get_srank_range( port,
                                           i_rank.getDimmSlct(),
                                           i_rank.getRankSlct(),
                                           i_rank.getSlave(),
                                           saddr,
                                           eaddr );

    do
    {
        // Clear all of the counters and maintenance ECC attentions.
        o_rc = prepareNextCmd<TYPE_MCBIST>( mcbChip );
        if ( SUCCESS != o_rc )
        {
            PRDF_ERR( PRDF_FUNC "prepareNextCmd(0x%08x) failed",
                      mcbChip->getHuid() );
            break;
        }

        // Start the super fast read command.
        errlHndl_t errl;
        FAPI_INVOKE_HWP( errl, memdiags::sf_read, fapiTrgt, stopCond, saddr );

        if ( nullptr != errl )
        {
            PRDF_ERR( PRDF_FUNC "memdiags::sf_read(0x%08x,%d) failed",
                      mcbChip->getHuid(), i_rank.getMaster() );
            PRDF_COMMIT_ERRL( errl, ERRL_ACTION_REPORT );
            o_rc = FAIL; break;
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

// This specialization only exists to avoid a lot of extra code in some classes.
// The input chip must still be an MCA chip.
template<>
uint32_t startSfRead<TYPE_MCBIST>( ExtensibleChip * i_mcaChip,
                                   const MemRank & i_rank )
{
    return startSfRead<TYPE_MCA>( i_mcaChip, i_rank );
}

//##############################################################################
//##                   Centaur Maintenance Command wrappers
//##############################################################################

template<>
uint32_t startSfRead<TYPE_MBA>( ExtensibleChip * i_mbaChip,
                                const MemRank & i_rank )
{
    #define PRDF_FUNC "[PlatServices::startSfRead<TYPE_MBA>] "

    PRDF_ASSERT( nullptr != i_mbaChip );
    PRDF_ASSERT( TYPE_MBA == i_mbaChip->getType() );

    uint32_t o_rc = SUCCESS;

    do
    {
        // Clear all of the counters and maintenance ECC attentions.
        o_rc = prepareNextCmd<TYPE_MBA>( i_mbaChip );
        if ( SUCCESS != o_rc )
        {
            PRDF_ERR( PRDF_FUNC "prepareNextCmd(0x%08x) failed",
                      i_mbaChip->getHuid() );
            break;
        }

        // Start the background scrub command.
        PRDF_ERR( PRDF_FUNC "function not implemented yet" ); // TODO RTC 157888

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

template<>
uint32_t startVcmPhase1<TYPE_MBA>( ExtensibleChip * i_chip,
                                   const MemRank & i_rank )
{
    #define PRDF_FUNC "[PlatServices::startVcmPhase1<TYPE_MBA>] "

    PRDF_ASSERT( nullptr != i_chip );
    PRDF_ASSERT( TYPE_MBA == i_chip->getType() );

    // TODO RTC 157888
    //  - Start a targeted steer cleanup.
    //  - Stop on RCE ETE (threshold 1).
    //  - The command should always stop at the end of the master rank.

    PRDF_ERR( PRDF_FUNC "function not implemented yet" );

    return SUCCESS;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

template<>
uint32_t startVcmPhase2<TYPE_MBA>( ExtensibleChip * i_chip,
                                   const MemRank & i_rank )
{
    #define PRDF_FUNC "[PlatServices::startVcmPhase2<TYPE_MBA>] "

    PRDF_ASSERT( nullptr != i_chip );
    PRDF_ASSERT( TYPE_MBA == i_chip->getType() );

    // TODO RTC 157888
    //  - Start a targeted super fast read.
    //  - No stop-on-error conditions. Note that RCEs will report as UEs during
    //    read operations. You can still set stop-on-RCE-ETE to be consistent
    //    with phase 1, but it will not have any effect and is not required.
    //  - The command should always stop at the end of the master rank.

    PRDF_ERR( PRDF_FUNC "function not implemented yet" );

    return SUCCESS;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

} // end namespace PlatServices

} // end namespace PRDF

<|endoftext|>


<commit_before>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#pragma once

#ifndef VSNRAY_PATHTRACING_INL
#define VSNRAY_PATHTRACING_INL 1

#ifndef NDEBUG
#include <iostream>
#include <ostream>
#endif

#include <visionaray/get_surface.h>
#include <visionaray/result_record.h>
#include <visionaray/traverse.h>

namespace visionaray
{
namespace pathtracing
{

template <typename Params>
struct kernel
{

    Params params;

    template <typename Intersector, typename R, typename Sampler>
    VSNRAY_FUNC result_record<typename R::scalar_type> operator()(
            Intersector& isect,
            R ray,
            Sampler& s
            ) const
    {

        using S = typename R::scalar_type;
        using V = typename result_record<S>::vec_type;
        using C = spectrum<S>;

        result_record<S> result;

        auto hit_rec        =  closest_hit(ray, params.prims.begin, params.prims.end, isect);
        auto exited         = !hit_rec.hit;
        auto active_rays    =  hit_rec.hit;
        result.color        =  params.bg_color;

        if (any(hit_rec.hit))
        {
            result.hit = hit_rec.hit;
            result.isect_pos = ray.ori + ray.dir * hit_rec.t;
        }
        else
        {
            result.hit = false;
            return result;
        }

        C dst(1.0);

        for (unsigned d = 0; d < params.num_bounces; ++d)
        {
            if ( any(active_rays) )
            {
                V refl_dir;
                V view_dir = -ray.dir;

                auto surf = get_surface(hit_rec, params);

                auto n = surf.shading_normal;

#if 1 // two-sided
                n = faceforward( n, view_dir, surf.geometric_normal );
#endif

                S pdf(0.0);
                auto sr     = make_shade_record<Params, S>();
                sr.active   = active_rays;
                sr.normal   = n;
                sr.view_dir = view_dir;

                auto src = surf.sample(sr, refl_dir, pdf, s);

                auto zero_pdf = pdf <= S(0.0);
                auto emissive = has_emissive_material(surf);

                src = mul( src, dot(n, refl_dir) / pdf, !emissive, src ); // TODO: maybe have emissive material return refl_dir so that dot(N,R) = 1?
                dst = mul( dst, src, active_rays && !zero_pdf, dst );
                dst = mul( dst, C(0.0), zero_pdf && active_rays, dst );

                active_rays &= !emissive;
                active_rays &= !zero_pdf;

                if (!any(active_rays))
                {
                    break;
                }

                auto isect_pos = ray.ori + ray.dir * hit_rec.t; // TODO: store in hit_rec?!?

                ray.ori = isect_pos + refl_dir * S(params.epsilon);
                ray.dir = refl_dir;

                hit_rec      = closest_hit(ray, params.prims.begin, params.prims.end, isect);
                exited       = active_rays & !hit_rec.hit;
                active_rays &= hit_rec.hit;
            }

            dst = mul( dst, C(from_rgba(params.ambient_color)), exited, dst );
        }

        dst = mul( dst, C(0.0), active_rays, dst );

        result.color = select( result.hit, to_rgba(dst), result.color );

        return result;
    }

    template <typename R, typename Sampler>
    VSNRAY_FUNC result_record<typename R::scalar_type> operator()(
            R ray,
            Sampler& s
            ) const
    {
        default_intersector ignore;
        return (*this)(ignore, ray, s);
    }
};

} // pathtracing
} // visionaray

#endif // VSNRAY_PATHTRACING_INL
<commit_msg>Simplify ray termination in path tracer<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#pragma once

#ifndef VSNRAY_PATHTRACING_INL
#define VSNRAY_PATHTRACING_INL 1

#ifndef NDEBUG
#include <iostream>
#include <ostream>
#endif

#include <visionaray/get_surface.h>
#include <visionaray/result_record.h>
#include <visionaray/traverse.h>

namespace visionaray
{
namespace pathtracing
{

template <typename Params>
struct kernel
{

    Params params;

    template <typename Intersector, typename R, typename Sampler>
    VSNRAY_FUNC result_record<typename R::scalar_type> operator()(
            Intersector& isect,
            R ray,
            Sampler& s
            ) const
    {

        using S = typename R::scalar_type;
        using V = typename result_record<S>::vec_type;
        using C = spectrum<S>;

        result_record<S> result;

        auto hit_rec        =  closest_hit(ray, params.prims.begin, params.prims.end, isect);
        auto exited         = !hit_rec.hit;
        auto active_rays    =  hit_rec.hit;
        result.color        =  params.bg_color;

        if (any(hit_rec.hit))
        {
            result.hit = hit_rec.hit;
            result.isect_pos = ray.ori + ray.dir * hit_rec.t;
        }
        else
        {
            result.hit = false;
            return result;
        }

        C dst(1.0);

        for (unsigned d = 0; d < params.num_bounces; ++d)
        {
            if ( any(active_rays) )
            {
                V refl_dir;
                V view_dir = -ray.dir;

                auto surf = get_surface(hit_rec, params);

                auto n = surf.shading_normal;

#if 1 // two-sided
                n = faceforward( n, view_dir, surf.geometric_normal );
#endif

                S pdf(0.0);
                auto sr     = make_shade_record<Params, S>();
                sr.active   = active_rays;
                sr.normal   = n;
                sr.view_dir = view_dir;

                auto src = surf.sample(sr, refl_dir, pdf, s);

                auto zero_pdf = pdf <= S(0.0);
                auto emissive = has_emissive_material(surf);

                src = mul( src, dot(n, refl_dir) / pdf, !emissive, src ); // TODO: maybe have emissive material return refl_dir so that dot(N,R) = 1?
                dst = mul( dst, src, active_rays && !zero_pdf, dst );
                dst = select( zero_pdf && active_rays, C(0.0), dst );

                active_rays &= !emissive;
                active_rays &= !zero_pdf;

                if (!any(active_rays))
                {
                    break;
                }

                auto isect_pos = ray.ori + ray.dir * hit_rec.t; // TODO: store in hit_rec?!?

                ray.ori = isect_pos + refl_dir * S(params.epsilon);
                ray.dir = refl_dir;

                hit_rec      = closest_hit(ray, params.prims.begin, params.prims.end, isect);
                exited       = active_rays & !hit_rec.hit;
                active_rays &= hit_rec.hit;
            }

            dst = mul( dst, C(from_rgba(params.ambient_color)), exited, dst );
        }

        dst = mul( dst, C(0.0), active_rays, dst );

        result.color = select( result.hit, to_rgba(dst), result.color );

        return result;
    }

    template <typename R, typename Sampler>
    VSNRAY_FUNC result_record<typename R::scalar_type> operator()(
            R ray,
            Sampler& s
            ) const
    {
        default_intersector ignore;
        return (*this)(ignore, ray, s);
    }
};

} // pathtracing
} // visionaray

#endif // VSNRAY_PATHTRACING_INL
<|endoftext|>


<commit_before>/*
 * FuzzyPatternMatchCB.cc
 *
 * Copyright (C) 2015 OpenCog Foundation
 *
 * Author: Leung Man Hin <https://github.com/leungmanhin>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "FuzzyPatternMatchCB.h"

using namespace opencog;

//#define DEBUG

FuzzyPatternMatchCB::FuzzyPatternMatchCB(AtomSpace* as)
	: DefaultPatternMatchCB(as)
{
}

/**
 * Implement the initiate_search calllback.
 *
 * For a fuzzy match, it starts with a full atomspace search to find candidates.
 *
 * @param pme        The pointer of the PatternMatchEngine
 * @param vars       A set of nodes that are considered as variables
 * @param clauses    The clauses for the query
 * @param negations  The negative clauses
 */
void FuzzyPatternMatchCB::initiate_search(PatternMatchEngine* pme,
                                          const std::set<Handle>& vars,
                                          const std::vector<Handle>& clauses)
{
    bool done = false;
    link_type_search(pme, vars, clauses, done);
}

/**
 * Override the link_match callback.
 *
 * This is for finding similar links/hypergraphs in the atomspace. The possible
 * grounding link (gLink) will be compared with the pattern link (pLink) and see
 * if it should be accepted, based on the similarity between them.
 *
 * @param pLink  The link from the query
 * @param gLink  A possible grounding link found by the Pattern Matcher
 * @return       Always return false to search for more solutions
 */
bool FuzzyPatternMatchCB::link_match(const LinkPtr& pLink, const LinkPtr& gLink)
{
    // If two links are identical, skip it
    if (pLink == gLink) return false;

    // Check if the types of the links are the same before going further into
    // the similarity estimation.
    // This is mainly for reducing the amount of hypergraphs being processed
    // as the content of two links with different types are likely to be quite
    // different.
    if (pLink->getType() != gLink->getType()) return false;

    check_if_accept(pLink->getHandle(), gLink->getHandle());

    return false;
}

/**
 * Override the node_match callback.
 *
 * This is for finding similar nodes in the atomspace. The possible grounding
 * node (gNode) will be compared with the pattern node (pNode) and see if it
 * should be accepted, based on the similarity between them.
 *
 * @param pNode  A handle of the node form the query
 * @param gNode  A handle of a possible grounding node
 * @return       Always return false to search for more solutions
 */
bool FuzzyPatternMatchCB::node_match(const Handle& pNode, const Handle& gNode)
{
    // If two handles are identical, skip it
    if (pNode == gNode) return false;

    check_if_accept(pNode, gNode);

    return false;
}

/**
 * Implement the grounding callback.
 *
 * Always return false to search for more solutions.
 *
 * @param var_soln   The variable & links mapping
 * @param pred_soln  The clause mapping
 * @return           Always return false to search for more solutions
 */
bool FuzzyPatternMatchCB::grounding(const std::map<Handle, Handle>& var_soln,
                                    const std::map<Handle, Handle>& pred_soln)
{
    return false;
}

/**
 * Check how similar the two hypergraphs are by computing the edit distance. If
 * the edit distance is smaller than or equals to the previous minimum, then
 * it will be accepted.
 *
 * @param ph  A handle of the hypergraph from the query
 * @param gh  A handle of a possible grounding hypergraph
 * @return    True if it is accepted, false otherwise
 */
bool FuzzyPatternMatchCB::check_if_accept(const Handle& ph, const Handle& gh)
{
    // Compute the edit distance
    cand_edit_dist = ged.compute(ph, gh);

    // Skip identical hypergraphs, if any
    if (cand_edit_dist == 0)
    {
#ifdef DEBUG
        printf("Cost = %.3f\nSkipped!\n\n", cand_edit_dist);
#endif
        return false;
    }

    // If the edit distance of the current hypergraph is smaller than the
    // previous minimum, it becomes the new minimum
    else if (cand_edit_dist < min_edit_dist)
    {
#ifdef DEBUG
        printf("Cost = %.3f\nMin. Cost = %.3f\nAccepted!\n\n",
               cand_edit_dist, min_edit_dist);
#endif
        min_edit_dist = cand_edit_dist;
        solns.clear();
        solns.push_back(gh);
        return true;
    }

    // If the edit distance of the current hypergraph is the same as the
    // previous minimum, add it to the solution-list
    else if (cand_edit_dist == min_edit_dist)
    {
#ifdef DEBUG
        printf("Cost = %.3f\nMin. Cost = %.3f\nAccepted!\n\n",
               cand_edit_dist, min_edit_dist);
#endif
        solns.push_back(gh);
        return true;
    }

    // If the edit distance of the current hypergraph is greater than the
    // previous minimum, reject it
    else
    {
#ifdef DEBUG
        printf("Cost = %.3f\nMin. Cost = %.3f\nRejected!\n\n",
               cand_edit_dist, min_edit_dist);
#endif
        return false;
    }
}
<commit_msg>Fix for the FuzzyUTest<commit_after>/*
 * FuzzyPatternMatchCB.cc
 *
 * Copyright (C) 2015 OpenCog Foundation
 *
 * Author: Leung Man Hin <https://github.com/leungmanhin>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "FuzzyPatternMatchCB.h"

using namespace opencog;

//#define DEBUG

FuzzyPatternMatchCB::FuzzyPatternMatchCB(AtomSpace* as)
	: DefaultPatternMatchCB(as)
{
}

/**
 * Implement the initiate_search calllback.
 *
 * For a fuzzy match, it starts with a full atomspace search to find candidates.
 *
 * @param pme        The pointer of the PatternMatchEngine
 * @param vars       A set of nodes that are considered as variables
 * @param clauses    The clauses for the query
 * @param negations  The negative clauses
 */
void FuzzyPatternMatchCB::initiate_search(PatternMatchEngine* pme,
                                          const std::set<Handle>& vars,
                                          const std::vector<Handle>& clauses)
{
    _root = clauses[0];
    _starter_pred = _root;
    // XXX FIXME  I'm pretty sure that this search is not going to be
    // complete, probably missing lots of similar patterns, simply
    // because it starts out with just the type of the very first
    // clause, and thus missing things that are fuzzily close to it.
    //
    // I know that this is the case, because when I substitute the
    // below with link_type_search(), which normally would be
    // equivalent but faster, the FuzzyUTest failed. Tis means that
    // if the "equivalent" search is missing answers, then the search
    // below is missing them too.
    //
    // So, instead of using the type of clause[0], you probably want
    // look at several types ???  There is a high risk that the
    // resulting search will be very inefficeint: this inefficiency
    // is exactly what link_type_search() was trying to avoid...
    Type ptype = _root->getType();
    HandleSeq handle_set;
    _as->getHandlesByType(handle_set, ptype);
    for (const Handle& h : handle_set)
    {
        bool found = pme->explore_neighborhood(_root, _starter_pred, h);
        if (found) return;
    }
}

/**
 * Override the link_match callback.
 *
 * This is for finding similar links/hypergraphs in the atomspace. The possible
 * grounding link (gLink) will be compared with the pattern link (pLink) and see
 * if it should be accepted, based on the similarity between them.
 *
 * @param pLink  The link from the query
 * @param gLink  A possible grounding link found by the Pattern Matcher
 * @return       Always return false to search for more solutions
 */
bool FuzzyPatternMatchCB::link_match(const LinkPtr& pLink, const LinkPtr& gLink)
{
    // If two links are identical, skip it
    if (pLink == gLink) return false;

    // Check if the types of the links are the same before going further into
    // the similarity estimation.
    // This is mainly for reducing the amount of hypergraphs being processed
    // as the content of two links with different types are likely to be quite
    // different.
    if (pLink->getType() != gLink->getType()) return false;

    check_if_accept(pLink->getHandle(), gLink->getHandle());

    return false;
}

/**
 * Override the node_match callback.
 *
 * This is for finding similar nodes in the atomspace. The possible grounding
 * node (gNode) will be compared with the pattern node (pNode) and see if it
 * should be accepted, based on the similarity between them.
 *
 * @param pNode  A handle of the node form the query
 * @param gNode  A handle of a possible grounding node
 * @return       Always return false to search for more solutions
 */
bool FuzzyPatternMatchCB::node_match(const Handle& pNode, const Handle& gNode)
{
    // If two handles are identical, skip it
    if (pNode == gNode) return false;

    check_if_accept(pNode, gNode);

    return false;
}

/**
 * Implement the grounding callback.
 *
 * Always return false to search for more solutions.
 *
 * @param var_soln   The variable & links mapping
 * @param pred_soln  The clause mapping
 * @return           Always return false to search for more solutions
 */
bool FuzzyPatternMatchCB::grounding(const std::map<Handle, Handle>& var_soln,
                                    const std::map<Handle, Handle>& pred_soln)
{
    return false;
}

/**
 * Check how similar the two hypergraphs are by computing the edit distance. If
 * the edit distance is smaller than or equals to the previous minimum, then
 * it will be accepted.
 *
 * @param ph  A handle of the hypergraph from the query
 * @param gh  A handle of a possible grounding hypergraph
 * @return    True if it is accepted, false otherwise
 */
bool FuzzyPatternMatchCB::check_if_accept(const Handle& ph, const Handle& gh)
{
    // Compute the edit distance
    cand_edit_dist = ged.compute(ph, gh);

    // Skip identical hypergraphs, if any
    if (cand_edit_dist == 0)
    {
#ifdef DEBUG
        printf("Cost = %.3f\nSkipped!\n\n", cand_edit_dist);
#endif
        return false;
    }

    // If the edit distance of the current hypergraph is smaller than the
    // previous minimum, it becomes the new minimum
    else if (cand_edit_dist < min_edit_dist)
    {
#ifdef DEBUG
        printf("Cost = %.3f\nMin. Cost = %.3f\nAccepted!\n\n",
               cand_edit_dist, min_edit_dist);
#endif
        min_edit_dist = cand_edit_dist;
        solns.clear();
        solns.push_back(gh);
        return true;
    }

    // If the edit distance of the current hypergraph is the same as the
    // previous minimum, add it to the solution-list
    else if (cand_edit_dist == min_edit_dist)
    {
#ifdef DEBUG
        printf("Cost = %.3f\nMin. Cost = %.3f\nAccepted!\n\n",
               cand_edit_dist, min_edit_dist);
#endif
        solns.push_back(gh);
        return true;
    }

    // If the edit distance of the current hypergraph is greater than the
    // previous minimum, reject it
    else
    {
#ifdef DEBUG
        printf("Cost = %.3f\nMin. Cost = %.3f\nRejected!\n\n",
               cand_edit_dist, min_edit_dist);
#endif
        return false;
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Matthew Malensek.
// Distributed under the BSD 2-Clause License (see LICENSE.txt for details)

#include "3RVX.h"

#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "Wtsapi32.lib")

#include <Windows.h>
#include <ctime>
#include <gdiplus.h>
#include <iostream>
#include <Wtsapi32.h>

#include "DisplayManager.h"
#include "HotkeyManager.h"
#include "Logger.h"
#include "OSD/EjectOSD.h"
#include "OSD/VolumeOSD.h"
#include "Settings.h"
#include "Skin/SkinManager.h"

int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPWSTR lpCmdLine, _In_ int nShowCmd) {

    Logger::Start();

    QCLOG(L"  _____ ______     ____  _______ ");
    QCLOG(L" |___ /|  _ \\ \\   / /\\ \\/ /___ / ");
    QCLOG(L"   |_ \\| |_) \\ \\ / /  \\  /  |_ \\ ");
    QCLOG(L"  ___) |  _ < \\ V /   /  \\ ___) |");
    QCLOG(L" |____/|_| \\_\\ \\_/   /_/\\_\\____/ ");
    QCLOG(L"");

    QCLOG(L"Starting up...");

    HANDLE mutex;
    mutex = CreateMutex(NULL, FALSE, L"Local\\3RVX");
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        if (mutex) {
            ReleaseMutex(mutex);
        }

        CLOG(L"A previous instance of the program is already running.\n"
            L"Requesting Settings dialog.");
        _3RVX::Message(_3RVX::MSG_SETTINGS, NULL);

#if defined(ENABLE_3RVX_LOG) && (defined(ENABLE_3RVX_LOGTOFILE) == FALSE)
        CLOG(L"Press [enter] to terminate");
        std::cin.get();
#endif

        return EXIT_SUCCESS;
    }

    CLOG(L"App directory: %s", Settings::AppDir().c_str());

    using namespace Gdiplus;
    ULONG_PTR gdiplusToken;
    GdiplusStartupInput gdiplusStartupInput;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    _3RVX mainWnd(hInstance);

    HRESULT hr = CoInitializeEx(NULL,
        COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
    if (hr != S_OK) {
        CLOG(L"Failed to initialize the COM library.");
        return EXIT_FAILURE;
    }

    /* Tell the program to initialize */
    PostMessage(mainWnd.Handle(), _3RVX::WM_3RVX_CTRL, _3RVX::MSG_LOAD, NULL);

    /* Register for session change notifications */
    WTSRegisterSessionNotification(mainWnd.Handle(), NOTIFY_FOR_THIS_SESSION);

    /* Start the event loop */
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    GdiplusShutdown(gdiplusToken);
    CoUninitialize();

    Logger::Stop();

    return (int) msg.wParam;
}

_3RVX::_3RVX(HINSTANCE hInstance) :
Window(_3RVX::CLASS_3RVX, _3RVX::CLASS_3RVX, hInstance) {
    SetTimer(Window::Handle(), TIMER_FIRSTUPDATE, FIRSTUPDATE_INTERVAL, NULL);
}

void _3RVX::Initialize() {
    CLOG(L"Initializing...");

    delete _vOSD;
    delete _eOSD;

    Settings *settings = Settings::Instance();
    settings->Load();

    SkinManager::Instance()->LoadSkin(settings->SkinXML());

    /* TODO: Detect monitor changes, update this map, and reload/reorg OSDs */
    DisplayManager::UpdateMonitorMap();

    /* OSDs */
    _eOSD = new EjectOSD();
    _vOSD = new VolumeOSD();

    /* Hotkey setup */
    if (_hkManager != NULL) {
        _hkManager->Shutdown();
    }
    _hkManager = HotkeyManager::Instance(Handle());

    _hotkeys = Settings::Instance()->Hotkeys();
    for (auto it = _hotkeys.begin(); it != _hotkeys.end(); ++it) {
        /* Enable arg caching */
        it->second.EnableArgCache();

        int combination = it->first;
        _hkManager->Register(combination);
    }

}

void _3RVX::ProcessHotkeys(HotkeyInfo &hki) {
    switch (hki.action) {
    case HotkeyInfo::IncreaseVolume:
    case HotkeyInfo::DecreaseVolume:
    case HotkeyInfo::SetVolume:
    case HotkeyInfo::Mute:
    case HotkeyInfo::VolumeSlider:
        if (_vOSD) {
            _vOSD->ProcessHotkeys(hki);
        }
        break;

    case HotkeyInfo::EjectDrive:
    case HotkeyInfo::EjectLastDisk:
        if (_eOSD) {
            _eOSD->ProcessHotkeys(hki);
        }
        break;

    case HotkeyInfo::MediaKey:
    case HotkeyInfo::VirtualKey:
        _kbHotkeyProcessor.ProcessHotkeys(hki);
        break;

    case HotkeyInfo::Run:
        if (hki.HasArgs()) {
            ShellExecute(NULL, L"open", hki.args[0].c_str(),
                NULL, NULL, SW_SHOWNORMAL);
        }
        break;

    case HotkeyInfo::DisableOSD:
        ToggleOSDs();
        break;

    case HotkeyInfo::Settings:
        ShellExecute(NULL, L"open", Settings::SettingsApp().c_str(),
            NULL, NULL, SW_SHOWNORMAL);
        break;

    case HotkeyInfo::Exit:
        SendMessage(Handle(), WM_CLOSE, NULL, NULL);
        break;
    }
}

void _3RVX::ToggleOSDs() {
    _eOSD->Enabled(!(_eOSD->Enabled()));
    _vOSD->Enabled(!(_vOSD->Enabled()));
}

LRESULT _3RVX::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
    case WM_HOTKEY: {
        CLOG(L"Hotkey: %d", (int) wParam);
        HotkeyInfo hki = _hotkeys[(int) wParam];
        ProcessHotkeys(hki);
        break;
    }

    case WM_WTSSESSION_CHANGE: {
        CLOG(L"Detected session change");
        break;
    }

    case WM_CLOSE: {
        CLOG(L"Shutting down");
        HotkeyManager::Instance()->Shutdown();
        _vOSD->HideIcon();
        break;
    }

    case WM_DESTROY: {
        PostQuitMessage(0);
        break;
    }

    case WM_TIMER:
        if (wParam == TIMER_FIRSTUPDATE || wParam == TIMER_UPDATE) {
            Settings *settings = Settings::Instance();
            long long checkTime = settings->UpdateCheckTime();
            if ((std::time(nullptr) - checkTime) > (UPDATE_INTERVAL / 1000)) {
                /* Enough time has elapsed since the last update check */
                std::wstring settingsApp = Settings::SettingsApp();
                CLOG(L"Launching update task: %s %s",
                    settingsApp.c_str(), L"-update");
                ShellExecute(NULL, L"open",
                    Settings::SettingsApp().c_str(), L"-update", NULL, SW_HIDE);

                if (wParam == TIMER_FIRSTUPDATE) {
                    /* If this was the first update check (30 min after launch),
                     * then kill the first update timer and start the main timer
                     * (checks on 24-hour intervals) */
                    KillTimer(Window::Handle(), TIMER_FIRSTUPDATE);
                    SetTimer(Window::Handle(), TIMER_UPDATE,
                        UPDATE_INTERVAL, NULL);
                }
            }
        }
        break;
    }

    if (message == _3RVX::WM_3RVX_CTRL) {
        switch (wParam) {
        case _3RVX::MSG_LOAD:
            Initialize();
            break;

        case _3RVX::MSG_SETTINGS:
            Settings::LaunchSettingsApp();
            break;

        case _3RVX::MSG_HIDEOSD:
            int except = (OSDType) lParam;
            switch (except) {
            case Volume:
                if (_eOSD) {
                    _eOSD->Hide();
                }
                break;

            case Eject:
                if (_vOSD) {
                    _vOSD->Hide();
                }
                break;
            }

            break;
        }
    }

    return Window::WndProc(hWnd, message, wParam, lParam);
}
<commit_msg>Launch timer during initialization<commit_after>// Copyright (c) 2015, Matthew Malensek.
// Distributed under the BSD 2-Clause License (see LICENSE.txt for details)

#include "3RVX.h"

#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "Wtsapi32.lib")

#include <Windows.h>
#include <ctime>
#include <gdiplus.h>
#include <iostream>
#include <Wtsapi32.h>

#include "DisplayManager.h"
#include "HotkeyManager.h"
#include "Logger.h"
#include "OSD/EjectOSD.h"
#include "OSD/VolumeOSD.h"
#include "Settings.h"
#include "Skin/SkinManager.h"

int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPWSTR lpCmdLine, _In_ int nShowCmd) {

    Logger::Start();

    QCLOG(L"  _____ ______     ____  _______ ");
    QCLOG(L" |___ /|  _ \\ \\   / /\\ \\/ /___ / ");
    QCLOG(L"   |_ \\| |_) \\ \\ / /  \\  /  |_ \\ ");
    QCLOG(L"  ___) |  _ < \\ V /   /  \\ ___) |");
    QCLOG(L" |____/|_| \\_\\ \\_/   /_/\\_\\____/ ");
    QCLOG(L"");

    QCLOG(L"Starting up...");

    HANDLE mutex;
    mutex = CreateMutex(NULL, FALSE, L"Local\\3RVX");
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        if (mutex) {
            ReleaseMutex(mutex);
        }

        CLOG(L"A previous instance of the program is already running.\n"
            L"Requesting Settings dialog.");
        _3RVX::Message(_3RVX::MSG_SETTINGS, NULL);

#if defined(ENABLE_3RVX_LOG) && (defined(ENABLE_3RVX_LOGTOFILE) == FALSE)
        CLOG(L"Press [enter] to terminate");
        std::cin.get();
#endif

        return EXIT_SUCCESS;
    }

    CLOG(L"App directory: %s", Settings::AppDir().c_str());

    using namespace Gdiplus;
    ULONG_PTR gdiplusToken;
    GdiplusStartupInput gdiplusStartupInput;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    _3RVX mainWnd(hInstance);

    HRESULT hr = CoInitializeEx(NULL,
        COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
    if (hr != S_OK) {
        CLOG(L"Failed to initialize the COM library.");
        return EXIT_FAILURE;
    }

    /* Tell the program to initialize */
    PostMessage(mainWnd.Handle(), _3RVX::WM_3RVX_CTRL, _3RVX::MSG_LOAD, NULL);

    /* Register for session change notifications */
    WTSRegisterSessionNotification(mainWnd.Handle(), NOTIFY_FOR_THIS_SESSION);

    /* Start the event loop */
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    GdiplusShutdown(gdiplusToken);
    CoUninitialize();

    Logger::Stop();

    return (int) msg.wParam;
}

_3RVX::_3RVX(HINSTANCE hInstance) :
Window(_3RVX::CLASS_3RVX, _3RVX::CLASS_3RVX, hInstance) {
}

void _3RVX::Initialize() {
    CLOG(L"Initializing...");

    delete _vOSD;
    delete _eOSD;

    Settings *settings = Settings::Instance();
    settings->Load();

    KillTimer(Window::Handle(), TIMER_FIRSTUPDATE);
    KillTimer(Window::Handle(), TIMER_UPDATE);
    if (settings->AutoUpdateEnabled()) {
        SetTimer(
            Window::Handle(),
            TIMER_FIRSTUPDATE,
            FIRSTUPDATE_INTERVAL,
            NULL);
    }

    SkinManager::Instance()->LoadSkin(settings->SkinXML());

    /* TODO: Detect monitor changes, update this map, and reload/reorg OSDs */
    DisplayManager::UpdateMonitorMap();

    /* OSDs */
    _eOSD = new EjectOSD();
    _vOSD = new VolumeOSD();

    /* Hotkey setup */
    if (_hkManager != NULL) {
        _hkManager->Shutdown();
    }
    _hkManager = HotkeyManager::Instance(Handle());

    _hotkeys = Settings::Instance()->Hotkeys();
    for (auto it = _hotkeys.begin(); it != _hotkeys.end(); ++it) {
        /* Enable arg caching */
        it->second.EnableArgCache();

        int combination = it->first;
        _hkManager->Register(combination);
    }

}

void _3RVX::ProcessHotkeys(HotkeyInfo &hki) {
    switch (hki.action) {
    case HotkeyInfo::IncreaseVolume:
    case HotkeyInfo::DecreaseVolume:
    case HotkeyInfo::SetVolume:
    case HotkeyInfo::Mute:
    case HotkeyInfo::VolumeSlider:
        if (_vOSD) {
            _vOSD->ProcessHotkeys(hki);
        }
        break;

    case HotkeyInfo::EjectDrive:
    case HotkeyInfo::EjectLastDisk:
        if (_eOSD) {
            _eOSD->ProcessHotkeys(hki);
        }
        break;

    case HotkeyInfo::MediaKey:
    case HotkeyInfo::VirtualKey:
        _kbHotkeyProcessor.ProcessHotkeys(hki);
        break;

    case HotkeyInfo::Run:
        if (hki.HasArgs()) {
            ShellExecute(NULL, L"open", hki.args[0].c_str(),
                NULL, NULL, SW_SHOWNORMAL);
        }
        break;

    case HotkeyInfo::DisableOSD:
        ToggleOSDs();
        break;

    case HotkeyInfo::Settings:
        ShellExecute(NULL, L"open", Settings::SettingsApp().c_str(),
            NULL, NULL, SW_SHOWNORMAL);
        break;

    case HotkeyInfo::Exit:
        SendMessage(Handle(), WM_CLOSE, NULL, NULL);
        break;
    }
}

void _3RVX::ToggleOSDs() {
    _eOSD->Enabled(!(_eOSD->Enabled()));
    _vOSD->Enabled(!(_vOSD->Enabled()));
}

LRESULT _3RVX::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
    case WM_HOTKEY: {
        CLOG(L"Hotkey: %d", (int) wParam);
        HotkeyInfo hki = _hotkeys[(int) wParam];
        ProcessHotkeys(hki);
        break;
    }

    case WM_WTSSESSION_CHANGE: {
        CLOG(L"Detected session change");
        break;
    }

    case WM_CLOSE: {
        CLOG(L"Shutting down");
        HotkeyManager::Instance()->Shutdown();
        _vOSD->HideIcon();
        break;
    }

    case WM_DESTROY: {
        PostQuitMessage(0);
        break;
    }

    case WM_TIMER:
        if (wParam == TIMER_FIRSTUPDATE || wParam == TIMER_UPDATE) {
            Settings *settings = Settings::Instance();
            long long checkTime = settings->UpdateCheckTime();
            if ((std::time(nullptr) - checkTime) > (UPDATE_INTERVAL / 1000)) {
                /* Enough time has elapsed since the last update check */
                std::wstring settingsApp = Settings::SettingsApp();
                CLOG(L"Launching update task: %s %s",
                    settingsApp.c_str(), L"-update");
                ShellExecute(NULL, L"open",
                    Settings::SettingsApp().c_str(), L"-update", NULL, SW_HIDE);

                if (wParam == TIMER_FIRSTUPDATE) {
                    /* If this was the first update check (30 min after launch),
                     * then kill the first update timer and start the main timer
                     * (checks on 24-hour intervals) */
                    KillTimer(Window::Handle(), TIMER_FIRSTUPDATE);
                    SetTimer(Window::Handle(), TIMER_UPDATE,
                        UPDATE_INTERVAL, NULL);
                }
            }
        }
        break;
    }

    if (message == _3RVX::WM_3RVX_CTRL) {
        switch (wParam) {
        case _3RVX::MSG_LOAD:
            Initialize();
            break;

        case _3RVX::MSG_SETTINGS:
            Settings::LaunchSettingsApp();
            break;

        case _3RVX::MSG_HIDEOSD:
            int except = (OSDType) lParam;
            switch (except) {
            case Volume:
                if (_eOSD) {
                    _eOSD->Hide();
                }
                break;

            case Eject:
                if (_vOSD) {
                    _vOSD->Hide();
                }
                break;
            }

            break;
        }
    }

    return Window::WndProc(hWnd, message, wParam, lParam);
}
<|endoftext|>


<commit_before>/* -*- C++ -*-
 * (c) 2009 Helge Bahmann <hcb@chaoticmind.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1
 * Refer to the file "COPYING" for details.
 */

#include <boost/bind.hpp>

#define private public
#define protected public

#include "tests.h"

#include <tscb/ioready>
#include <pthread.h>

void test_pipe_eventflag(void)
{
	tscb::pipe_eventflag e;

	ASSERT(e.flagged==0);
	e.set();
	ASSERT(e.flagged==1);
	e.clear();
	ASSERT(e.flagged==0);

	e.start_waiting();
	ASSERT(e.waiting==1);
	e.stop_waiting();
	ASSERT(e.waiting==0);

	e.set();
	ASSERT(e.flagged==1);
	e.clear();
}

main()
{
	test_pipe_eventflag();
}
<commit_msg>Silence compiler warning<commit_after>/* -*- C++ -*-
 * (c) 2009 Helge Bahmann <hcb@chaoticmind.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1
 * Refer to the file "COPYING" for details.
 */

#include <boost/bind.hpp>

#define private public
#define protected public

#include "tests.h"

#include <tscb/ioready>
#include <pthread.h>

void test_pipe_eventflag(void)
{
	tscb::pipe_eventflag e;

	ASSERT(e.flagged==0);
	e.set();
	ASSERT(e.flagged==1);
	e.clear();
	ASSERT(e.flagged==0);

	e.start_waiting();
	ASSERT(e.waiting==1);
	e.stop_waiting();
	ASSERT(e.waiting==0);

	e.set();
	ASSERT(e.flagged==1);
	e.clear();
}

int main()
{
	test_pipe_eventflag();
}
<|endoftext|>


<commit_before>/**
 *
 * @file compiled_plugin_base.cpp
 *
 * @date Jan 15, 2013
 * @author partio
 */

#include "compiled_plugin_base.h"
#include <boost/thread.hpp>
#include "plugin_factory.h"
#include "logger_factory.h"
#include "util.h"
#include "cuda_helper.h"

#define HIMAN_AUXILIARY_INCLUDE

#include "fetcher.h"
#include "neons.h"
#include "writer.h"
#include "cache.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan;
using namespace himan::plugin;

const double kInterpolatedValueEpsilon = 0.00001; //<! Max difference between two grid points (if smaller, points are considered the same)
mutex itsAdjustDimensionMutex;

compiled_plugin_base::compiled_plugin_base() : itsPluginIsInitialized(false)
{
	itsBaseLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog("compiled_plugin_base"));
}

bool compiled_plugin_base::AdjustLeadingDimension(const info_t& myTargetInfo)
{

	lock_guard<mutex> lock(itsAdjustDimensionMutex);

	// Leading dimension can be: time or level

	if (itsLeadingDimension == kTimeDimension)
	{
		if (!itsInfo->NextTime())
		{
			return false;
		}

		myTargetInfo->Time(itsInfo->Time());
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		if (!itsInfo->NextLevel())
		{
			return false;
		}

		myTargetInfo->Level(itsInfo->Level());
	}
	else
	{
		throw runtime_error(ClassName() + ": Invalid dimension type: " + boost::lexical_cast<string> (itsLeadingDimension));
	}

	return true;
}

bool compiled_plugin_base::AdjustNonLeadingDimension(const info_t& myTargetInfo)
{
	if (itsLeadingDimension == kTimeDimension)
	{
		return myTargetInfo->NextLevel();
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		return myTargetInfo->NextTime();
	}
	else
	{
		throw runtime_error(ClassName() + ": unsupported leading dimension: " + boost::lexical_cast<string> (itsLeadingDimension));
	}
}

void compiled_plugin_base::ResetNonLeadingDimension(const info_t& myTargetInfo)
{
	if (itsLeadingDimension == kTimeDimension)
	{
		myTargetInfo->ResetLevel();
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		myTargetInfo->ResetTime();
	}
	else
	{
		throw runtime_error(ClassName() + ": unsupported leading dimension: " + boost::lexical_cast<string> (itsLeadingDimension));
	}
}

bool compiled_plugin_base::SetAB(const info_t& myTargetInfo, const info_t& sourceInfo)
{
	if (myTargetInfo->Level().Type() == kHybrid)
	{
		size_t index = myTargetInfo->ParamIndex();

		myTargetInfo->Grid()->AB(sourceInfo->Grid()->AB());

		myTargetInfo->ParamIndex(index);
	}

	return true;
}

bool compiled_plugin_base::SwapTo(const info_t& myTargetInfo, HPScanningMode targetScanningMode)
{

	if (myTargetInfo->Grid()->ScanningMode() != targetScanningMode)
	{
		HPScanningMode originalMode = myTargetInfo->Grid()->ScanningMode();

		myTargetInfo->Grid()->ScanningMode(targetScanningMode);

		myTargetInfo->Grid()->Swap(originalMode);
	}

	return true;
}

void compiled_plugin_base::WriteToFile(const shared_ptr<const info>& targetInfo) const
{
	auto aWriter = dynamic_pointer_cast <writer> (plugin_factory::Instance()->Plugin("writer"));

	// writing might modify iterator positions --> create a copy

	auto tempInfo = make_shared<info> (*targetInfo);

	if (itsConfiguration->FileWriteOption() == kNeons || itsConfiguration->FileWriteOption() == kMultipleFiles)
	{
		// If info holds multiple parameters, we must loop over them all
		// Note! We only loop over the parameters, not over the times or levels!

		tempInfo->ResetParam();

		while (tempInfo->NextParam())
		{
			aWriter->ToFile(tempInfo, itsConfiguration);
		}
	}
	else if (itsConfiguration->FileWriteOption() == kSingleFile)
	{
		aWriter->ToFile(tempInfo, itsConfiguration, itsConfiguration->ConfigurationFile());
	}
}

bool compiled_plugin_base::GetAndSetCuda(int threadIndex)
{
	// This function used to have more logic with regards to thread index, but all that
	// has been removed.

#ifdef HAVE_CUDA
	bool ret = itsConfiguration->UseCuda() && itsConfiguration->CudaDeviceId() < itsConfiguration->CudaDeviceCount();

	if (ret)
	{
		cudaError_t err;

		if ((err = cudaSetDevice(itsConfiguration->CudaDeviceId())) != cudaSuccess)
		{
			cerr << ClassName() << "::Warning Failed to select device #" << itsConfiguration->CudaDeviceId() << ", error: " << cudaGetErrorString(err) << endl;
			cerr << ClassName() << "::Warning Has another CUDA process reserved the card?\n";
			ret = false;
		}
	}
#else
	bool ret = false;
#endif

	return ret;
}

void compiled_plugin_base::ResetCuda() const
{
#ifdef HAVE_CUDA
	CUDA_CHECK(cudaDeviceReset());
#endif
}

void compiled_plugin_base::Start()
{
	if (!itsPluginIsInitialized)
	{
		itsBaseLogger->Error("Start() called before Init()");
		return;
	}

	boost::thread_group g;

	/*
	 * Each thread will have a copy of the target info.
	 */

	for (short i = 0; i < itsThreadCount; i++)
	{

		printf("Info::compiled_plugin: Thread %d starting\n", (i + 1)); // Printf is thread safe

		boost::thread* t = new boost::thread(&compiled_plugin_base::Run,
											 this,
											 make_shared<info> (*itsInfo),
											 i + 1);

		g.add_thread(t);

	}

	g.join_all();

	Finish();
}

void compiled_plugin_base::Init(const shared_ptr<const plugin_configuration> conf)
{

	const short MAX_THREADS = 12; //<! Max number of threads we allow

	itsConfiguration = conf;

	if (itsConfiguration->StatisticsEnabled())
	{
		itsTimer = unique_ptr<timer> (timer_factory::Instance()->GetTimer());
		itsTimer->Start();
		itsConfiguration->Statistics()->UsedGPUCount(conf->CudaDeviceCount());
	}

	// Determine thread count

	short coreCount = static_cast<short> (boost::thread::hardware_concurrency()); // Number of cores

	itsThreadCount = MAX_THREADS;

	// If user has specified thread count, always use that
	if (conf->ThreadCount() > 0)
	{
		itsThreadCount = conf->ThreadCount();
	}
	// we don't want to use all cores in a server by default
	else if (MAX_THREADS > coreCount)
	{
		itsThreadCount = coreCount;
	}

	itsInfo = itsConfiguration->Info();

	itsLeadingDimension = itsConfiguration->LeadingDimension();

	itsPluginIsInitialized = true;
}

void compiled_plugin_base::Run(info_t myTargetInfo, unsigned short threadIndex)
{
	while (AdjustLeadingDimension(myTargetInfo))
	{
		ResetNonLeadingDimension(myTargetInfo);

		while (AdjustNonLeadingDimension(myTargetInfo))
		{
			Calculate(myTargetInfo, threadIndex);

			if (itsConfiguration->FileWriteOption() != kSingleFile)
			{
				WriteToFile(myTargetInfo);
			}

			if (itsConfiguration->StatisticsEnabled())
			{
				itsConfiguration->Statistics()->AddToMissingCount(myTargetInfo->Data().MissingCount());
				itsConfiguration->Statistics()->AddToValueCount(myTargetInfo->Data().Size());
			}
		}
	}
}

void compiled_plugin_base::Finish() const
{

	if (itsConfiguration->StatisticsEnabled())
	{
		itsTimer->Stop();
		itsConfiguration->Statistics()->AddToProcessingTime(itsTimer->GetTime());
	}

	if (itsConfiguration->FileWriteOption() == kSingleFile)
	{
		WriteToFile(itsInfo);
	}
}

void compiled_plugin_base::Calculate(info_t myTargetInfo, unsigned short threadIndex)
{
	itsBaseLogger->Fatal("Top level calculate called");
	exit(1);
}

void compiled_plugin_base::SetParams(initializer_list<param> params)
{
	vector<param> paramVec;

	for (auto it = params.begin(); it != params.end(); ++it)
	{
		paramVec.push_back(*it);
	}

	SetParams(paramVec);
}

void compiled_plugin_base::SetParams(std::vector<param>& params)
{
	if (params.empty())
	{
		itsBaseLogger->Fatal("size of target parameter vector is zero");
		exit(1);
	}

	// GRIB 1

	if (itsConfiguration->OutputFileType() == kGRIB1)
	{
		auto n = dynamic_pointer_cast<plugin::neons> (plugin_factory::Instance()->Plugin("neons"));

		for (unsigned int i = 0; i < params.size(); i++)
		{
			long table2Version = itsInfo->Producer().TableVersion();
			long parm_id = n->NeonsDB().GetGridParameterId(table2Version, params[i].Name());

			if (parm_id == -1)
			{
				itsBaseLogger->Warning("Grib1 parameter definitions not found from Neons");
				itsBaseLogger->Warning("table2Version is " + boost::lexical_cast<string> (table2Version) + ", parm_name is " + params[i].Name());
			}

			params[i].GribIndicatorOfParameter(parm_id);
			params[i].GribTableVersion(table2Version);
		}
	}

	itsInfo->Params(params);

	/*
	 * Create data structures.
	 */

	itsInfo->Create();

	/*
	 * Iterators must be reseted since they are at first position after Create()
	 */

	itsInfo->Reset();

	/*
	 * Do not launch more threads than there are things to calculate.
	 */

	if (itsLeadingDimension == kTimeDimension)
	{
		if (itsInfo->SizeTimes() < static_cast<size_t> (itsThreadCount))
		{
			itsThreadCount = static_cast<short> (itsInfo->SizeTimes());
		}
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		if (itsInfo->SizeLevels() < static_cast<size_t> (itsThreadCount))
		{
			itsThreadCount = static_cast<short> (itsInfo->SizeLevels());
		}
	}

	/*
	 * From the timing perspective at this point plugin initialization is
	 * considered to be done
	 */

	if (itsConfiguration->StatisticsEnabled())
	{
		itsConfiguration->Statistics()->UsedThreadCount(itsThreadCount);
		itsTimer->Stop();
		itsConfiguration->Statistics()->AddToInitTime(itsTimer->GetTime());
		// Start process timing
		itsTimer->Start();
	}

	itsInfo->FirstParam();

}

#ifdef HAVE_CUDA
void compiled_plugin_base::Unpack(initializer_list<info_t> infos)
{
	auto c = dynamic_pointer_cast<plugin::cache> (plugin_factory::Instance()->Plugin("cache"));

	for (auto it = infos.begin(); it != infos.end(); ++it)
	{
		info_t tempInfo = *it;

		if (tempInfo->Grid()->PackedData().packedLength == 0)
		{
			// Safeguard: This particular info does not have packed data
			continue;
		}

		assert(tempInfo->Grid()->PackedData().ClassName() == "simple_packed");

		util::Unpack({ tempInfo->Grid() });

		if (itsConfiguration->UseCache())
		{
			c->Insert(tempInfo);
		}
	}
}
#endif

bool compiled_plugin_base::CompareGrids(initializer_list<shared_ptr<grid>> grids) const
{
	if (grids.size() <= 1)
	{
		throw kUnknownException;
	}

	auto it = grids.begin();
	auto first = *it;

	for (++it; it != grids.end(); ++it)
	{
		if (!*it)
		{
			continue;
		}

		if (*first != **it)
		{
			return false;
		}
	}

	return true;
}

bool compiled_plugin_base::IsMissingValue(initializer_list<double> values) const
{
	for (auto it = values.begin(); it != values.end(); ++it)
	{
		if (*it == kFloatMissing)
		{
			return true;
		}
	}

	return false;
}

info_t compiled_plugin_base::Fetch(const forecast_time& theTime, const level& theLevel, const params& theParams, bool returnPacked) const
{
	auto f = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	info_t ret;

	try
	{
		ret = f->Fetch(itsConfiguration, theTime, theLevel, theParams, itsConfiguration->UseCudaForPacking());

#ifdef HAVE_CUDA
		if (!returnPacked && ret->Grid()->IsPackedData())
		{
			assert(ret->Grid()->PackedData().ClassName() == "simple_packed");

			util::Unpack({ret->Grid()});
		}
#endif
	}
	catch (HPExceptionType& e)
	{
		if (e != kFileDataNotFound)
		{
			throw runtime_error(ClassName() + ": Unable to proceed");
		}
	}

	return ret;
}

info_t compiled_plugin_base::Fetch(const forecast_time& theTime, const level& theLevel, const param& theParam, bool returnPacked) const
{
	auto f = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	info_t ret;

	try
	{
		ret = f->Fetch(itsConfiguration, theTime, theLevel, theParam, itsConfiguration->UseCudaForPacking());

#ifdef HAVE_CUDA
		if (!returnPacked && ret->Grid()->IsPackedData())
		{
			assert(ret->Grid()->PackedData().ClassName() == "simple_packed");

			util::Unpack({ret->Grid()});
		}
#endif
	}
	catch (HPExceptionType& e)
	{
		if (e != kFileDataNotFound)
		{
			throw runtime_error(ClassName() + ": Unable to proceed");
		}
	}

	return ret;
}

info* compiled_plugin_base::FetchRaw(const forecast_time& theTime, const level& theLevel, const param& theParam, bool returnPacked) const
{
	auto r = Fetch(theTime,theLevel,theParam,false);
	cout << *r.get();
	return r.get();
}<commit_msg>reference instead of shared_ptr<commit_after>/**
 *
 * @file compiled_plugin_base.cpp
 *
 * @date Jan 15, 2013
 * @author partio
 */

#include "compiled_plugin_base.h"
#include <boost/thread.hpp>
#include "plugin_factory.h"
#include "logger_factory.h"
#include "util.h"
#include "cuda_helper.h"

#define HIMAN_AUXILIARY_INCLUDE

#include "fetcher.h"
#include "neons.h"
#include "writer.h"
#include "cache.h"

#undef HIMAN_AUXILIARY_INCLUDE

using namespace std;
using namespace himan;
using namespace himan::plugin;

const double kInterpolatedValueEpsilon = 0.00001; //<! Max difference between two grid points (if smaller, points are considered the same)
mutex itsAdjustDimensionMutex;

compiled_plugin_base::compiled_plugin_base() : itsPluginIsInitialized(false)
{
	itsBaseLogger = std::unique_ptr<logger> (logger_factory::Instance()->GetLog("compiled_plugin_base"));
}

bool compiled_plugin_base::AdjustLeadingDimension(const info_t& myTargetInfo)
{

	lock_guard<mutex> lock(itsAdjustDimensionMutex);

	// Leading dimension can be: time or level

	if (itsLeadingDimension == kTimeDimension)
	{
		if (!itsInfo->NextTime())
		{
			return false;
		}

		myTargetInfo->Time(itsInfo->Time());
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		if (!itsInfo->NextLevel())
		{
			return false;
		}

		myTargetInfo->Level(itsInfo->Level());
	}
	else
	{
		throw runtime_error(ClassName() + ": Invalid dimension type: " + boost::lexical_cast<string> (itsLeadingDimension));
	}

	return true;
}

bool compiled_plugin_base::AdjustNonLeadingDimension(const info_t& myTargetInfo)
{
	if (itsLeadingDimension == kTimeDimension)
	{
		return myTargetInfo->NextLevel();
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		return myTargetInfo->NextTime();
	}
	else
	{
		throw runtime_error(ClassName() + ": unsupported leading dimension: " + boost::lexical_cast<string> (itsLeadingDimension));
	}
}

void compiled_plugin_base::ResetNonLeadingDimension(const info_t& myTargetInfo)
{
	if (itsLeadingDimension == kTimeDimension)
	{
		myTargetInfo->ResetLevel();
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		myTargetInfo->ResetTime();
	}
	else
	{
		throw runtime_error(ClassName() + ": unsupported leading dimension: " + boost::lexical_cast<string> (itsLeadingDimension));
	}
}

bool compiled_plugin_base::SetAB(const info_t& myTargetInfo, const info_t& sourceInfo)
{
	if (myTargetInfo->Level().Type() == kHybrid)
	{
		size_t index = myTargetInfo->ParamIndex();

		myTargetInfo->Grid()->AB(sourceInfo->Grid()->AB());

		myTargetInfo->ParamIndex(index);
	}

	return true;
}

bool compiled_plugin_base::SwapTo(const info_t& myTargetInfo, HPScanningMode targetScanningMode)
{

	if (myTargetInfo->Grid()->ScanningMode() != targetScanningMode)
	{
		HPScanningMode originalMode = myTargetInfo->Grid()->ScanningMode();

		myTargetInfo->Grid()->ScanningMode(targetScanningMode);

		myTargetInfo->Grid()->Swap(originalMode);
	}

	return true;
}

void compiled_plugin_base::WriteToFile(const info& targetInfo) const
{
	auto aWriter = dynamic_pointer_cast <writer> (plugin_factory::Instance()->Plugin("writer"));

	// writing might modify iterator positions --> create a copy

	auto tempInfo = targetInfo;

	if (itsConfiguration->FileWriteOption() == kNeons || itsConfiguration->FileWriteOption() == kMultipleFiles)
	{
		// If info holds multiple parameters, we must loop over them all
		// Note! We only loop over the parameters, not over the times or levels!

		tempInfo.ResetParam();

		while (tempInfo.NextParam())
		{
			aWriter->ToFile(tempInfo, *itsConfiguration);
		}
	}
	else if (itsConfiguration->FileWriteOption() == kSingleFile)
	{
		aWriter->ToFile(tempInfo, *itsConfiguration, itsConfiguration->ConfigurationFile());
	}
}

bool compiled_plugin_base::GetAndSetCuda(int threadIndex)
{
	// This function used to have more logic with regards to thread index, but all that
	// has been removed.

#ifdef HAVE_CUDA
	bool ret = itsConfiguration->UseCuda() && itsConfiguration->CudaDeviceId() < itsConfiguration->CudaDeviceCount();

	if (ret)
	{
		cudaError_t err;

		if ((err = cudaSetDevice(itsConfiguration->CudaDeviceId())) != cudaSuccess)
		{
			cerr << ClassName() << "::Warning Failed to select device #" << itsConfiguration->CudaDeviceId() << ", error: " << cudaGetErrorString(err) << endl;
			cerr << ClassName() << "::Warning Has another CUDA process reserved the card?\n";
			ret = false;
		}
	}
#else
	bool ret = false;
#endif

	return ret;
}

void compiled_plugin_base::ResetCuda() const
{
#ifdef HAVE_CUDA
	CUDA_CHECK(cudaDeviceReset());
#endif
}

void compiled_plugin_base::Start()
{
	if (!itsPluginIsInitialized)
	{
		itsBaseLogger->Error("Start() called before Init()");
		return;
	}

	boost::thread_group g;

	/*
	 * Each thread will have a copy of the target info.
	 */

	for (short i = 0; i < itsThreadCount; i++)
	{

		printf("Info::compiled_plugin: Thread %d starting\n", (i + 1)); // Printf is thread safe

		boost::thread* t = new boost::thread(&compiled_plugin_base::Run,
											 this,
											 make_shared<info> (*itsInfo),
											 i + 1);

		g.add_thread(t);

	}

	g.join_all();

	Finish();
}

void compiled_plugin_base::Init(const shared_ptr<const plugin_configuration> conf)
{

	const short MAX_THREADS = 12; //<! Max number of threads we allow

	itsConfiguration = conf;

	if (itsConfiguration->StatisticsEnabled())
	{
		itsTimer = unique_ptr<timer> (timer_factory::Instance()->GetTimer());
		itsTimer->Start();
		itsConfiguration->Statistics()->UsedGPUCount(conf->CudaDeviceCount());
	}

	// Determine thread count

	short coreCount = static_cast<short> (boost::thread::hardware_concurrency()); // Number of cores

	itsThreadCount = MAX_THREADS;

	// If user has specified thread count, always use that
	if (conf->ThreadCount() > 0)
	{
		itsThreadCount = conf->ThreadCount();
	}
	// we don't want to use all cores in a server by default
	else if (MAX_THREADS > coreCount)
	{
		itsThreadCount = coreCount;
	}

	itsInfo = itsConfiguration->Info();

	itsLeadingDimension = itsConfiguration->LeadingDimension();

	itsPluginIsInitialized = true;
}

void compiled_plugin_base::Run(info_t myTargetInfo, unsigned short threadIndex)
{
	while (AdjustLeadingDimension(myTargetInfo))
	{
		ResetNonLeadingDimension(myTargetInfo);

		while (AdjustNonLeadingDimension(myTargetInfo))
		{
			Calculate(myTargetInfo, threadIndex);

			if (itsConfiguration->FileWriteOption() != kSingleFile)
			{
				WriteToFile(*myTargetInfo);
			}

			if (itsConfiguration->StatisticsEnabled())
			{
				itsConfiguration->Statistics()->AddToMissingCount(myTargetInfo->Data().MissingCount());
				itsConfiguration->Statistics()->AddToValueCount(myTargetInfo->Data().Size());
			}
		}
	}
}

void compiled_plugin_base::Finish() const
{

	if (itsConfiguration->StatisticsEnabled())
	{
		itsTimer->Stop();
		itsConfiguration->Statistics()->AddToProcessingTime(itsTimer->GetTime());
	}

	if (itsConfiguration->FileWriteOption() == kSingleFile)
	{
		WriteToFile(*itsInfo);
	}
}

void compiled_plugin_base::Calculate(info_t myTargetInfo, unsigned short threadIndex)
{
	itsBaseLogger->Fatal("Top level calculate called");
	exit(1);
}

void compiled_plugin_base::SetParams(initializer_list<param> params)
{
	vector<param> paramVec;

	for (auto it = params.begin(); it != params.end(); ++it)
	{
		paramVec.push_back(*it);
	}

	SetParams(paramVec);
}

void compiled_plugin_base::SetParams(std::vector<param>& params)
{
	if (params.empty())
	{
		itsBaseLogger->Fatal("size of target parameter vector is zero");
		exit(1);
	}

	// GRIB 1

	if (itsConfiguration->OutputFileType() == kGRIB1)
	{
		auto n = dynamic_pointer_cast<plugin::neons> (plugin_factory::Instance()->Plugin("neons"));

		for (unsigned int i = 0; i < params.size(); i++)
		{
			long table2Version = itsInfo->Producer().TableVersion();
			long parm_id = n->NeonsDB().GetGridParameterId(table2Version, params[i].Name());

			if (parm_id == -1)
			{
				itsBaseLogger->Warning("Grib1 parameter definitions not found from Neons");
				itsBaseLogger->Warning("table2Version is " + boost::lexical_cast<string> (table2Version) + ", parm_name is " + params[i].Name());
			}

			params[i].GribIndicatorOfParameter(parm_id);
			params[i].GribTableVersion(table2Version);
		}
	}

	itsInfo->Params(params);

	/*
	 * Create data structures.
	 */

	itsInfo->Create();

	/*
	 * Iterators must be reseted since they are at first position after Create()
	 */

	itsInfo->Reset();

	/*
	 * Do not launch more threads than there are things to calculate.
	 */

	if (itsLeadingDimension == kTimeDimension)
	{
		if (itsInfo->SizeTimes() < static_cast<size_t> (itsThreadCount))
		{
			itsThreadCount = static_cast<short> (itsInfo->SizeTimes());
		}
	}
	else if (itsLeadingDimension == kLevelDimension)
	{
		if (itsInfo->SizeLevels() < static_cast<size_t> (itsThreadCount))
		{
			itsThreadCount = static_cast<short> (itsInfo->SizeLevels());
		}
	}

	/*
	 * From the timing perspective at this point plugin initialization is
	 * considered to be done
	 */

	if (itsConfiguration->StatisticsEnabled())
	{
		itsConfiguration->Statistics()->UsedThreadCount(itsThreadCount);
		itsTimer->Stop();
		itsConfiguration->Statistics()->AddToInitTime(itsTimer->GetTime());
		// Start process timing
		itsTimer->Start();
	}

	itsInfo->FirstParam();

}

#ifdef HAVE_CUDA
void compiled_plugin_base::Unpack(initializer_list<info_t> infos)
{
	auto c = dynamic_pointer_cast<plugin::cache> (plugin_factory::Instance()->Plugin("cache"));

	for (auto it = infos.begin(); it != infos.end(); ++it)
	{
		info_t tempInfo = *it;

		if (tempInfo->Grid()->PackedData().packedLength == 0)
		{
			// Safeguard: This particular info does not have packed data
			continue;
		}

		assert(tempInfo->Grid()->PackedData().ClassName() == "simple_packed");

		util::Unpack({ tempInfo->Grid() });

		if (itsConfiguration->UseCache())
		{
			c->Insert(*tempInfo);
		}
	}
}
#endif

bool compiled_plugin_base::CompareGrids(initializer_list<shared_ptr<grid>> grids) const
{
	if (grids.size() <= 1)
	{
		throw kUnknownException;
	}

	auto it = grids.begin();
	auto first = *it;

	for (++it; it != grids.end(); ++it)
	{
		if (!*it)
		{
			continue;
		}

		if (*first != **it)
		{
			return false;
		}
	}

	return true;
}

bool compiled_plugin_base::IsMissingValue(initializer_list<double> values) const
{
	for (auto it = values.begin(); it != values.end(); ++it)
	{
		if (*it == kFloatMissing)
		{
			return true;
		}
	}

	return false;
}

info_t compiled_plugin_base::Fetch(const forecast_time& theTime, const level& theLevel, const params& theParams, bool returnPacked) const
{
	auto f = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	info_t ret;

	try
	{
		ret = f->Fetch(itsConfiguration, theTime, theLevel, theParams, itsConfiguration->UseCudaForPacking());

#ifdef HAVE_CUDA
		if (!returnPacked && ret->Grid()->IsPackedData())
		{
			assert(ret->Grid()->PackedData().ClassName() == "simple_packed");

			util::Unpack({ret->Grid()});
		}
#endif
	}
	catch (HPExceptionType& e)
	{
		if (e != kFileDataNotFound)
		{
			throw runtime_error(ClassName() + ": Unable to proceed");
		}
	}

	return ret;
}

info_t compiled_plugin_base::Fetch(const forecast_time& theTime, const level& theLevel, const param& theParam, bool returnPacked) const
{
	auto f = dynamic_pointer_cast <fetcher> (plugin_factory::Instance()->Plugin("fetcher"));

	info_t ret;

	try
	{
		ret = f->Fetch(itsConfiguration, theTime, theLevel, theParam, itsConfiguration->UseCudaForPacking());

#ifdef HAVE_CUDA
		if (!returnPacked && ret->Grid()->IsPackedData())
		{
			assert(ret->Grid()->PackedData().ClassName() == "simple_packed");

			util::Unpack({ret->Grid()});
		}
#endif
	}
	catch (HPExceptionType& e)
	{
		if (e != kFileDataNotFound)
		{
			throw runtime_error(ClassName() + ": Unable to proceed");
		}
	}

	return ret;
}

info* compiled_plugin_base::FetchRaw(const forecast_time& theTime, const level& theLevel, const param& theParam, bool returnPacked) const
{
	auto r = Fetch(theTime,theLevel,theParam,false);
	assert(r);
	return r.get();
}
<|endoftext|>