<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_DataExchange_OptionsFile_inl_
#define _Stroika_Foundation_DataExchange_OptionsFile_inl_  1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include    "../Characters/Format.h"
#include    "../Streams/BasicBinaryOutputStream.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   DataExchange {

            /*
             ********************************************************************************
             ************************** DataExchange::OptionsFile ***************************
             ********************************************************************************
             */
            template    <typename T>
            Optional<T>   OptionsFile::Read ()
            {
                Optional<VariantValue>  tmp = Read<VariantValue> ();
                if (tmp.IsMissing ()) {
                    return Optional<T> ();
                }
                try {
                    return fMapper_.ToObject<T> (*tmp);
                }
                catch (const BadFormatException& bf) {
                    fLogger_ (Execution::Logger::Priority::eCriticalError, Characters::Format (L"Error analyzing configuration file (bad format) '%s' - using defaults.", GetReadFilePath_ ().c_str ()));
                    return Optional<T> ();
                }
                catch (...) {
                    // if this fails, its probably because somehow the data in the config file was bad.
                    // So at least log that, and continue without reading anything (as if empty file)
                    fLogger_ (Execution::Logger::Priority::eCriticalError, Characters::Format (L"Error analyzing configuration file '%s' - using defaults.", GetReadFilePath_ ().c_str ()));
                    return Optional<T> ();
                }
            }
            template    <typename T>
            T   OptionsFile::Read (const T& defaultObj, ReadFlags readFlags)
            {
                Optional<T> eltRead = Read<T> ();
                Optional<T> elt2Write;              // only if needed
                String      msgAugment;
                if (eltRead.IsMissing ()) {
                    if (readFlags == ReadFlags::eWriteIfChanged) {
                        elt2Write = defaultObj;
                        msgAugment = L"default";
                    }
                }
                else {
                    if (readFlags == ReadFlags::eWriteIfChanged) {
                        try {
                            // See if re-persisting the item would change it.
                            // This is useful if your data model adds or removes fields. It updates the file contents written to the
                            // upgraded/latest form
                            Memory::BLOB    oldData =   ReadRaw (); // @todo could have saved from previous Read<T>
                            Memory::BLOB    newData;
                            {
                                Streams::BasicBinaryOutputStream outStream;
                                fWriter_.Write (fMapper_.FromObject (*eltRead), outStream);
                                // not sure needed? outStream.Flush();
                                newData = outStream.As<Memory::BLOB> ();
                            }
                            if (oldData != newData) {
                                elt2Write = eltRead;
                                msgAugment = L"(because something changed)";
                            }
                        }
                        catch (...) {
                            fLogger_ (Execution::Logger::Priority::eError, Characters::Format (L"Failed to compare configuration file: %s", GetReadFilePath_ ().c_str ()));
                        }
                    }
                }
                if (elt2Write.IsPresent ()) {
                    fLogger_ (Execution::Logger::Priority::eInfo, Characters::Format (L"Writing %s '%s' configuration file.", msgAugment.c_str (), GetWriteFilePath_ ().c_str ()));
                    try {
                        Write (*elt2Write);
                    }
                    catch (...) {
                        fLogger_ (Execution::Logger::Priority::eError, Characters::Format (L"Failed to write default values to file: %s", GetWriteFilePath_ ().c_str ()));
                    }
                    return *elt2Write;
                }
                else if (eltRead.IsPresent ()) {
                    return *eltRead;
                }
                else {
                    return defaultObj;
                }
            }
            template    <typename T>
            void    OptionsFile::Write (const T& optionsObject)
            {
                Write<VariantValue> (fMapper_.FromObject<T> (optionsObject));
            }

        }

    }
}
#endif  /*_Stroika_Foundation_DataExchange_OptionsFile_inl_*/
<commit_msg>OptionsFile - cleanup to Read (and automatic write if changes) code<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_DataExchange_OptionsFile_inl_
#define _Stroika_Foundation_DataExchange_OptionsFile_inl_  1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
#include    "../Characters/Format.h"
#include    "../Streams/BasicBinaryOutputStream.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   DataExchange {

            /*
             ********************************************************************************
             ************************** DataExchange::OptionsFile ***************************
             ********************************************************************************
             */
            template    <typename T>
            Optional<T>   OptionsFile::Read ()
            {
                Optional<VariantValue>  tmp = Read<VariantValue> ();
                if (tmp.IsMissing ()) {
                    return Optional<T> ();
                }
                try {
                    return fMapper_.ToObject<T> (*tmp);
                }
                catch (const BadFormatException& bf) {
                    fLogger_ (Execution::Logger::Priority::eCriticalError, Characters::Format (L"Error analyzing configuration file (bad format) '%s' - using defaults.", GetReadFilePath_ ().c_str ()));
                    return Optional<T> ();
                }
                catch (...) {
                    // if this fails, its probably because somehow the data in the config file was bad.
                    // So at least log that, and continue without reading anything (as if empty file)
                    fLogger_ (Execution::Logger::Priority::eCriticalError, Characters::Format (L"Error analyzing configuration file '%s' - using defaults.", GetReadFilePath_ ().c_str ()));
                    return Optional<T> ();
                }
            }
            template    <typename T>
            T   OptionsFile::Read (const T& defaultObj, ReadFlags readFlags)
            {
                Optional<T> eltRead = Read<T> ();
                Optional<T> elt2Write;              // only if needed
                String      msgAugment;
                if (eltRead.IsMissing ()) {
                    if (readFlags == ReadFlags::eWriteIfChanged) {
                        elt2Write = defaultObj;
                        msgAugment = L" so defaults are more easily editable";
                    }
                }
                else {
                    if (readFlags == ReadFlags::eWriteIfChanged) {
                        if (elt2Write.IsMissing ()) {
                            // if filename differs - upgrading
                            if (GetReadFilePath_ () != GetWriteFilePath_ ()) {
                                elt2Write = eltRead;
                                msgAugment = L" in a new directory because upgrading the software has been upgraded";
                            }
                        }
                        if (elt2Write.IsMissing ()) {
                            try {
                                // See if re-persisting the item would change it.
                                // This is useful if your data model adds or removes fields. It updates the file contents written to the
                                // upgraded/latest form.
                                Memory::BLOB    oldData =   ReadRaw (); // @todo could have saved from previous Read<T>
                                Memory::BLOB    newData;
                                {
                                    Streams::BasicBinaryOutputStream outStream;
                                    fWriter_.Write (fMapper_.FromObject (*eltRead), outStream);
                                    // not sure needed? outStream.Flush();
                                    newData = outStream.As<Memory::BLOB> ();
                                }
                                if (oldData != newData) {
                                    elt2Write = eltRead;
                                    msgAugment = L" because something changed (e.g. a default, or field added/removed).";
                                }
                            }
                            catch (...) {
                                fLogger_ (Execution::Logger::Priority::eError, Characters::Format (L"Failed to compare configuration file: %s", GetReadFilePath_ ().c_str ()));
                            }
                        }
                    }
                }
                if (elt2Write.IsPresent ()) {
                    fLogger_ (Execution::Logger::Priority::eInfo, Characters::Format (L"Writing configuration file '%s'%s.", GetWriteFilePath_ ().c_str (), msgAugment.c_str ()));
                    try {
                        Write (*elt2Write);
                    }
                    catch (...) {
                        fLogger_ (Execution::Logger::Priority::eError, Characters::Format (L"Failed to write default values to file: %s", GetWriteFilePath_ ().c_str ()));
                    }
                    return *elt2Write;
                }
                else if (eltRead.IsPresent ()) {
                    return *eltRead;
                }
                else {
                    return defaultObj;
                }
            }
            template    <typename T>
            void    OptionsFile::Write (const T& optionsObject)
            {
                Write<VariantValue> (fMapper_.FromObject<T> (optionsObject));
            }

        }

    }
}
#endif  /*_Stroika_Foundation_DataExchange_OptionsFile_inl_*/
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/phy/adr32s.C $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] 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 adr32s.C
/// @brief Subroutines for the PHY ADR32S registers
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <lib/phy/adr32s.H>
#include <lib/phy/dcd.H>
#include <lib/workarounds/adr32s_workarounds.H>
#include <generic/memory/lib/utils/find.H>
#include <lib/mss_attribute_accessors_manual.H>

using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_SYSTEM;
using fapi2::FAPI2_RC_SUCCESS;

namespace mss
{

// Definition of the ADR32S DLL Config registers
const std::vector<uint64_t> adr32sTraits<fapi2::TARGET_TYPE_MCA>::DLL_CNFG_REG =
{
    MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0,
    MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S1
};

// Definition of the ADR32S output driver registers
const std::vector<uint64_t> adr32sTraits<fapi2::TARGET_TYPE_MCA>::OUTPUT_DRIVER_REG =
{
    MCA_DDRPHY_ADR_OUTPUT_FORCE_ATEST_CNTL_P0_ADR32S0,
    MCA_DDRPHY_ADR_OUTPUT_FORCE_ATEST_CNTL_P0_ADR32S1,
};

// Definition of the ADR32S duty cycle distortion registers
const std::vector<uint64_t> adr32sTraits<fapi2::TARGET_TYPE_MCA>::DUTY_CYCLE_DISTORTION_REG =
{
    MCA_DDRPHY_ADR_DCD_CONTROL_P0_ADR32S0,
    MCA_DDRPHY_ADR_DCD_CONTROL_P0_ADR32S1,
};

// Definition of the ADR32S write clock static offset registers
const std::vector<uint64_t> adr32sTraits<fapi2::TARGET_TYPE_MCA>::PR_STATIC_OFFSET_REG =
{
    MCA_DDRPHY_ADR_MCCLK_WRCLK_PR_STATIC_OFFSET_P0_ADR32S0,
    MCA_DDRPHY_ADR_MCCLK_WRCLK_PR_STATIC_OFFSET_P0_ADR32S1,
};

namespace adr32s
{

///
/// @brief Perform ADR DCD calibration - Nimbus Only
/// @param[in] i_target the MCBIST (controler) to perform calibration on
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode duty_cycle_distortion_calibration( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target )
{
    const auto l_mca = mss::find_targets<TARGET_TYPE_MCA>(i_target);
    uint8_t l_sim = 0;

    FAPI_TRY( mss::is_simulation( l_sim) );

    // Nothing works here in cycle sim ...
    if (l_sim)
    {
        return FAPI2_RC_SUCCESS;
    }

    if (l_mca.size() == 0)
    {
        FAPI_INF("No MCA, skipping duty cycle distortion calibration");
        return FAPI2_RC_SUCCESS;
    }

    // If we're supposed to skip DCD, just return success
    if (!mss::run_dcd_calibration(i_target))
    {
        FAPI_INF("%s Skipping DCD calibration algorithm per ATTR set", mss::c_str(i_target));
        return FAPI2_RC_SUCCESS;
    }

    // Runs the proper DCD calibration for Nimbus DD1 vs DD2
    if(mss::chip_ec_nimbus_lt_2_0(i_target))
    {
        // Runs the DD1 calibration
        FAPI_TRY(mss::workarounds::adr32s::duty_cycle_distortion_calibration(i_target));
    }

    else
    {
        // Runs the DD2 calibration algorithm
        FAPI_TRY(mss::dcd::execute_hw_calibration(i_target));
    }

fapi_try_exit:
    return fapi2::current_err;
}

} // close namespace adrs32

} // close namespace mss
<commit_msg>L3 support for ddr_phy_reset, termination_control<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/phy/adr32s.C $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] 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 adr32s.C
/// @brief Subroutines for the PHY ADR32S registers
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <lib/phy/adr32s.H>
#include <lib/phy/dcd.H>
#include <lib/workarounds/adr32s_workarounds.H>
#include <generic/memory/lib/utils/find.H>
#include <lib/mss_attribute_accessors_manual.H>

using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_SYSTEM;
using fapi2::FAPI2_RC_SUCCESS;

namespace mss
{

// Definition of the ADR32S DLL Config registers
const std::vector<uint64_t> adr32sTraits<fapi2::TARGET_TYPE_MCA>::DLL_CNFG_REG =
{
    MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0,
    MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S1
};

// Definition of the ADR32S output driver registers
const std::vector<uint64_t> adr32sTraits<fapi2::TARGET_TYPE_MCA>::OUTPUT_DRIVER_REG =
{
    MCA_DDRPHY_ADR_OUTPUT_FORCE_ATEST_CNTL_P0_ADR32S0,
    MCA_DDRPHY_ADR_OUTPUT_FORCE_ATEST_CNTL_P0_ADR32S1,
};

// Definition of the ADR32S duty cycle distortion registers
const std::vector<uint64_t> adr32sTraits<fapi2::TARGET_TYPE_MCA>::DUTY_CYCLE_DISTORTION_REG =
{
    MCA_DDRPHY_ADR_DCD_CONTROL_P0_ADR32S0,
    MCA_DDRPHY_ADR_DCD_CONTROL_P0_ADR32S1,
};

// Definition of the ADR32S write clock static offset registers
const std::vector<uint64_t> adr32sTraits<fapi2::TARGET_TYPE_MCA>::PR_STATIC_OFFSET_REG =
{
    MCA_DDRPHY_ADR_MCCLK_WRCLK_PR_STATIC_OFFSET_P0_ADR32S0,
    MCA_DDRPHY_ADR_MCCLK_WRCLK_PR_STATIC_OFFSET_P0_ADR32S1,
};

namespace adr32s
{

///
/// @brief Perform ADR DCD calibration - Nimbus Only
/// @param[in] i_target the MCBIST (controler) to perform calibration on
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode duty_cycle_distortion_calibration( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target )
{
    const auto l_mca = mss::find_targets<TARGET_TYPE_MCA>(i_target);
    uint8_t l_sim = 0;

    FAPI_TRY( mss::is_simulation( l_sim) );

    // Nothing works here in cycle sim ...
    if (l_sim)
    {
        return FAPI2_RC_SUCCESS;
    }

    if (l_mca.size() == 0)
    {
        FAPI_INF("%s No MCA, skipping duty cycle distortion calibration", mss::c_str(i_target) );
        return FAPI2_RC_SUCCESS;
    }

    // If we're supposed to skip DCD, just return success
    if (!mss::run_dcd_calibration(i_target))
    {
        FAPI_INF("%s Skipping DCD calibration algorithm per ATTR set", mss::c_str(i_target));
        return FAPI2_RC_SUCCESS;
    }

    // Runs the proper DCD calibration for Nimbus DD1 vs DD2
    if(mss::chip_ec_nimbus_lt_2_0(i_target))
    {
        // Runs the DD1 calibration
        FAPI_TRY(mss::workarounds::adr32s::duty_cycle_distortion_calibration(i_target), "%s Failed dcd calibration",
                 mss::c_str(i_target) );
    }

    else
    {
        // Runs the DD2 calibration algorithm
        FAPI_TRY(mss::dcd::execute_hw_calibration(i_target), "%s Failed dcd execute hw calibration", mss::c_str(i_target) );
    }

fapi_try_exit:
    return fapi2::current_err;
}

} // close namespace adrs32

} // close namespace mss
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.C $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] 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 p9_mss_memdiag.C
/// @brief Mainstore pattern testing
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 1
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <p9_mss_memdiag.H>

#include <lib/utils/poll.H>
#include <lib/mcbist/address.H>
#include <lib/mcbist/memdiags.H>
#include <lib/mcbist/mcbist.H>

#include <lib/fir/memdiags_fir.H>

using fapi2::TARGET_TYPE_MCBIST;

extern "C"
{
///
/// @brief Pattern test the DRAM
/// @param[in] i_target the McBIST of the ports of the dram you're training
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_memdiag( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        FAPI_INF("Start memdiag");

        // Unmask the memdiags FIR
        FAPI_TRY( mss::unmask_memdiags_errors(i_target) );

        FAPI_TRY( memdiags::sf_init(i_target, mss::mcbist::PATTERN_0) );

        // TODO RTC:153951
        // Remove the polling when the attention bits are hooked up
        {
            // Poll for the fir bit. We expect this to be set ...
            fapi2::buffer<uint64_t> l_status;

            // A small vector of addresses to poll during the polling loop
            static const std::vector<mss::poll_probe<fapi2::TARGET_TYPE_MCBIST>> l_probes =
            {
                {i_target, "mcbist current address", MCBIST_MCBMCATQ},
            };

            mss::poll_parameters l_poll_parameters;
            bool l_poll_results = mss::poll(i_target, MCBIST_MCBISTFIRQ, l_poll_parameters,
                                            [&l_status](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool
            {
                FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining);
                l_status = stat_reg;
                return l_status.getBit<MCBIST_MCBISTFIRQ_MCBIST_PROGRAM_COMPLETE>() == true;
            },
            l_probes);

            FAPI_ASSERT( l_poll_results == true,
                         fapi2::MSS_MEMDIAGS_SUPERFAST_INIT_FAILED_TO_INIT().set_TARGET(i_target),
                         "p9_mss_memdiags timedout %s", mss::c_str(i_target) );
        }

    fapi_try_exit:
        FAPI_INF("End memdiag");
        return fapi2::current_err;
    }
}
<commit_msg>Change memdiags/mcbist stop conditions to incorporate end, thresholds<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.C $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] 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 p9_mss_memdiag.C
/// @brief Mainstore pattern testing
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <p9_mss_memdiag.H>

#include <lib/utils/poll.H>
#include <lib/mcbist/address.H>
#include <lib/mcbist/memdiags.H>
#include <lib/mcbist/mcbist.H>

#include <lib/fir/memdiags_fir.H>

using fapi2::TARGET_TYPE_MCBIST;

extern "C"
{
///
/// @brief Pattern test the DRAM
/// @param[in] i_target the McBIST of the ports of the dram you're training
/// @return FAPI2_RC_SUCCESS iff ok
///
    fapi2::ReturnCode p9_mss_memdiag( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        FAPI_INF("Start memdiag");

        // Unmask the memdiags FIR
        FAPI_TRY( mss::unmask_memdiags_errors(i_target) );

        FAPI_TRY( memdiags::sf_init(i_target, mss::mcbist::PATTERN_0) );

        // TODO RTC:153951
        // Remove the polling when the attention bits are hooked up
        {
            // Poll for the fir bit. We expect this to be set ...
            fapi2::buffer<uint64_t> l_status;

            // A small vector of addresses to poll during the polling loop
            static const std::vector<mss::poll_probe<fapi2::TARGET_TYPE_MCBIST>> l_probes =
            {
                {i_target, "mcbist current address", MCBIST_MCBMCATQ},
            };

            mss::poll_parameters l_poll_parameters;
            bool l_poll_results = mss::poll(i_target, MCBIST_MCBISTFIRQ, l_poll_parameters,
                                            [&l_status](const size_t poll_remaining,
                                                    const fapi2::buffer<uint64_t>& stat_reg) -> bool
            {
                FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining);
                l_status = stat_reg;
                return l_status.getBit<MCBIST_MCBISTFIRQ_MCBIST_PROGRAM_COMPLETE>() == true;
            },
            l_probes);

            FAPI_ASSERT( l_poll_results == true,
                         fapi2::MSS_MEMDIAGS_SUPERFAST_INIT_FAILED_TO_INIT().set_TARGET(i_target),
                         "p9_mss_memdiags timedout %s", mss::c_str(i_target) );
        }

    fapi_try_exit:
        FAPI_INF("End memdiag");
        return fapi2::current_err;
    }
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/utils/imageProcs/p9_infrastruct_help.H $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] 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                                                     */
#ifndef _P9_INFRASTRUCT_HELP_H_
#define _P9_INFRASTRUCT_HELP_H_

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>     //memcpy()
#include <errno.h>

//
// Various image/ring buffer sizes. Must be used by all users (VBU, FSP, HB, HBI, Cronus)
//
const uint32_t  MAX_REF_IMAGE_SIZE    =     1024 *
        1024; // Max reference image size.
const uint32_t  FIXED_RING_BUF_SIZE   =
    60000; // Fixed ring buf size for _fixed.

#define CHIPLET_ID_MIN            (uint8_t)0x00
#define CHIPLET_ID_MAX            (uint8_t)0x37

#define MY_INF(_fmt_, _args_...) printf(_fmt_, ##_args_)
#define MY_ERR(_fmt_, _args_...) printf(_fmt_, ##_args_)
#define MY_DBG(_fmt_, _args_...) printf(_fmt_, ##_args_)

// N-byte align an address, offset or size (aos)
inline uint64_t myByteAlign( const uint8_t nBytes, const uint64_t aos)
{
    return ((aos + nBytes - 1) / nBytes) * nBytes;
}

#endif //_P9_INFRASTRUCT_HELP_H_
<commit_msg>Replace usage of printf() with FAPI_INF() in p9_tor<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/utils/imageProcs/p9_infrastruct_help.H $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] 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                                                     */
#ifndef _P9_INFRASTRUCT_HELP_H_
#define _P9_INFRASTRUCT_HELP_H_

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>     //memcpy()
#include <errno.h>

//
// Various image/ring buffer sizes. Must be used by all users (VBU, FSP, HB, HBI, Cronus)
//
const uint32_t  MAX_REF_IMAGE_SIZE    =     1024 *
        1024; // Max reference image size.
const uint32_t  FIXED_RING_BUF_SIZE   =
    60000; // Fixed ring buf size for _fixed.

#define CHIPLET_ID_MIN            (uint8_t)0x00
#define CHIPLET_ID_MAX            (uint8_t)0x37

#if defined(__FAPI)
    #define MY_INF(_fmt_, _args_...) FAPI_INF(_fmt_, ##_args_)
    #define MY_ERR(_fmt_, _args_...) FAPI_INF(_fmt_, ##_args_)
    #define MY_DBG(_fmt_, _args_...) FAPI_DBG(_fmt_, ##_args_)
#else
    #define MY_INF(_fmt_, _args_...) printf(_fmt_, ##_args_)
    #define MY_ERR(_fmt_, _args_...) printf(_fmt_, ##_args_)
    #define MY_DBG(_fmt_, _args_...) printf(_fmt_, ##_args_)
#endif

// N-byte align an address, offset or size (aos)
inline uint64_t myByteAlign( const uint8_t nBytes, const uint64_t aos)
{
    return ((aos + nBytes - 1) / nBytes) * nBytes;
}

#endif //_P9_INFRASTRUCT_HELP_H_
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: adc_cmds.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: vg $ $Date: 2007-09-18 14:05:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <precomp.h>
#include "adc_cmds.hxx"

// NOT FULLY DEFINED SERVICES
#include <ary/ary.hxx>
#include <autodoc/displaying.hxx>
#include <autodoc/dsp_html_std.hxx>
#include <display/corframe.hxx>
#include <display/uidldisp.hxx>

namespace autodoc
{
namespace command
{

extern const String C_opt_Include("-I:");

extern const String C_opt_Verbose("-v");

extern const String C_opt_Parse("-parse");
extern const String C_opt_Name("-name");
extern const String C_opt_LangAll("-lg");
extern const String C_opt_ExtensionsAll("-extg");
extern const String C_opt_DevmanFile("-dvgfile");
extern const String C_opt_SinceFile("-sincefile");

extern const String C_arg_Cplusplus("c++");
extern const String C_arg_Idl("idl");
extern const String C_arg_Java("java");

extern const String C_opt_Project("-p");
//extern const String C_opt_Lang;
//extern const String C_opt_Extensions;
extern const String C_opt_SourceDir("-d");
extern const String C_opt_SourceTree("-t");
extern const String C_opt_SourceFile("-f");

extern const String C_opt_CreateHtml("-html");
extern const String C_opt_DevmanRoot("-dvgroot");

//extern const String C_opt_CreateXml("-xml");
//extern const String C_opt_Load("-load");
//extern const String C_opt_Save("-save");

extern const String C_opt_ExternNamespace("-extnsp");
extern const String C_opt_ExternRoot("-extroot");

//**************************        CreateHTML    ***********************//

CreateHtml::CreateHtml()
    :   sOutputRootDirectory(),
        sDevelopersManual_HtmlRoot()
{
}

CreateHtml::~CreateHtml()
{
}

void
CreateHtml::do_Init( opt_iter &          it,
                     opt_iter            itEnd )
{
    ++it;
    CHECKOPT( it != itEnd && (*it).char_at(0) != '-',
              "output directory", C_opt_CreateHtml );
    sOutputRootDirectory = *it;

    for ( ++it;
          it != itEnd AND (*it == C_opt_DevmanRoot);
          ++it )
    {
        if (*it == C_opt_DevmanRoot)
        {
            ++it;
            CHECKOPT( it != itEnd AND (*it).char_at(0) != '-',
                      "HTML root directory of Developers Guide",
                      C_opt_DevmanRoot );
            sDevelopersManual_HtmlRoot = *it;
        }
    }   // end for
}

bool
CreateHtml::do_Run() const
{
    if ( ::ary::n22::Repository::The_().HasIdl() )
        run_Idl();
    if ( ::ary::n22::Repository::The_().HasCpp() )
        run_Cpp();
    return true;
}

int
CreateHtml::inq_RunningRank() const
{
    return static_cast<int>(rank_CreateHtml);
}

void
CreateHtml::run_Idl() const
{
    const ary::idl::Gate &
        rGate = ary::n22::Repository::The_().Gate_Idl();

    Cout() << "Creating HTML-output into the directory "
              << sOutputRootDirectory
              << "."
              << Endl();

    const DisplayToolsFactory_Ifc &
        rToolsFactory = DisplayToolsFactory_Ifc::GetIt_();
    Dyn<autodoc::HtmlDisplay_Idl_Ifc>
        pDisplay( rToolsFactory.Create_HtmlDisplay_Idl() );

    DYN display::CorporateFrame &   // KORR: Remove the need for const_cast in future.
        drFrame = const_cast< display::CorporateFrame& >(rToolsFactory.Create_StdFrame());
    if (NOT DevelopersManual_HtmlRoot().empty())
        drFrame.Set_DevelopersGuideHtmlRoot( DevelopersManual_HtmlRoot() );

    pDisplay->Run( sOutputRootDirectory,
                   rGate,
                   drFrame );
}

void
CreateHtml::run_Cpp() const
{
    const ary::n22::Repository &
        rReposy = ary::n22::Repository::The_();
    const ary::cpp::DisplayGate &
        rGate = rReposy.Gate_Cpp();

    const DisplayToolsFactory_Ifc &
        rToolsFactory = DisplayToolsFactory_Ifc::GetIt_();
    Dyn< autodoc::HtmlDisplay_UdkStd >
        pDisplay( rToolsFactory.Create_HtmlDisplay_UdkStd() );

    pDisplay->Run( sOutputRootDirectory,
                   rGate,
                   rToolsFactory.Create_StdFrame() );
}

}   // namespace command
}   // namespace autodoc
<commit_msg>INTEGRATION: CWS adc18 (1.8.2); FILE MERGED 2007/10/19 10:37:29 np 1.8.2.2: #i81775# 2007/10/18 15:23:15 np 1.8.2.1: #i81775#<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: adc_cmds.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-02 16:43:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <precomp.h>
#include "adc_cmds.hxx"

// NOT FULLY DEFINED SERVICES
#include <ary/ary.hxx>
#include <autodoc/displaying.hxx>
#include <autodoc/dsp_html_std.hxx>
#include <display/corframe.hxx>
#include <adc_cl.hxx>

namespace autodoc
{
namespace command
{

extern const String C_opt_Include("-I:");

extern const String C_opt_Verbose("-v");

extern const String C_opt_Parse("-parse");
extern const String C_opt_Name("-name");
extern const String C_opt_LangAll("-lg");
extern const String C_opt_ExtensionsAll("-extg");
extern const String C_opt_DevmanFile("-dvgfile");
extern const String C_opt_SinceFile("-sincefile");

extern const String C_arg_Cplusplus("c++");
extern const String C_arg_Idl("idl");
extern const String C_arg_Java("java");

extern const String C_opt_Project("-p");
//extern const String C_opt_Lang;
//extern const String C_opt_Extensions;
extern const String C_opt_SourceDir("-d");
extern const String C_opt_SourceTree("-t");
extern const String C_opt_SourceFile("-f");

extern const String C_opt_CreateHtml("-html");
extern const String C_opt_DevmanRoot("-dvgroot");

//extern const String C_opt_CreateXml("-xml");
//extern const String C_opt_Load("-load");
//extern const String C_opt_Save("-save");

extern const String C_opt_ExternNamespace("-extnsp");
extern const String C_opt_ExternRoot("-extroot");

//**************************        CreateHTML    ***********************//

CreateHtml::CreateHtml()
    :   sOutputRootDirectory(),
        sDevelopersManual_HtmlRoot()
{
}

CreateHtml::~CreateHtml()
{
}

void
CreateHtml::do_Init( opt_iter &          it,
                     opt_iter            itEnd )
{
    ++it;
    CHECKOPT( it != itEnd && (*it).char_at(0) != '-',
              "output directory", C_opt_CreateHtml );
    sOutputRootDirectory = *it;

    for ( ++it;
          it != itEnd AND (*it == C_opt_DevmanRoot);
          ++it )
    {
        if (*it == C_opt_DevmanRoot)
        {
            ++it;
            CHECKOPT( it != itEnd AND (*it).char_at(0) != '-',
                      "HTML root directory of Developers Guide",
                      C_opt_DevmanRoot );
            sDevelopersManual_HtmlRoot = *it;
        }
    }   // end for
}

bool
CreateHtml::do_Run() const
{
    if ( CommandLine::Get_().IdlUsed() )
        run_Idl();
    if ( CommandLine::Get_().CppUsed() )
        run_Cpp();
    return true;
}

int
CreateHtml::inq_RunningRank() const
{
    return static_cast<int>(rank_CreateHtml);
}

void
CreateHtml::run_Idl() const
{
    const ary::idl::Gate &
        rGate = CommandLine::Get_().TheRepository().Gate_Idl();

    Cout() << "Creating HTML-output into the directory "
              << sOutputRootDirectory
              << "."
              << Endl();

    const DisplayToolsFactory_Ifc &
        rToolsFactory = DisplayToolsFactory_Ifc::GetIt_();
    Dyn<autodoc::HtmlDisplay_Idl_Ifc>
        pDisplay( rToolsFactory.Create_HtmlDisplay_Idl() );

    DYN display::CorporateFrame &   // KORR_FUTURE: Remove the need for const_cast
        drFrame = const_cast< display::CorporateFrame& >(rToolsFactory.Create_StdFrame());
    if (NOT DevelopersManual_HtmlRoot().empty())
        drFrame.Set_DevelopersGuideHtmlRoot( DevelopersManual_HtmlRoot() );

    pDisplay->Run( sOutputRootDirectory,
                   rGate,
                   drFrame );
}

void
CreateHtml::run_Cpp() const
{
    const ary::Repository &
        rReposy = CommandLine::Get_().TheRepository();
    const ary::cpp::Gate &
        rGate = rReposy.Gate_Cpp();

    const DisplayToolsFactory_Ifc &
        rToolsFactory = DisplayToolsFactory_Ifc::GetIt_();
    Dyn< autodoc::HtmlDisplay_UdkStd >
        pDisplay( rToolsFactory.Create_HtmlDisplay_UdkStd() );

    pDisplay->Run( sOutputRootDirectory,
                   rGate,
                   rToolsFactory.Create_StdFrame() );
}

}   // namespace command
}   // namespace autodoc
<|endoftext|>


<commit_before>// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#include <gtest/gtest.h>
#include <test/Helpers.h>
#include <vw/Core/Settings.h>

#include <boost/filesystem/operations.hpp>
namespace fs = boost::filesystem;

#if VW_HAVE_FENV_H
#include <fenv.h>
#endif

int main(int argc, char **argv) {
  // Disable the user's config file
  vw::vw_settings().set_rc_filename("");
  ::testing::InitGoogleTest(&argc, argv);

  // Default to the "threadsafe" style because we can't delete our singletons
  // yet; this style of test launches a new process, so the singletons are
  // fresh.
  ::testing::FLAGS_gtest_death_test_style = "threadsafe";

#if VW_HAVE_FEENABLEEXCEPT
  if (getenv("VW_CATCH_FP_ERRORS"))
    feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
#endif

  if (getenv("VW_DEBUG")) {
    vw::vw_log().console_log().rule_set().add_rule(vw::VerboseDebugMessage, "*");
  }

  // TODO: Make it so the seed is settable so we can reproduce failures in
  // probabilistic algorithms. This uses clock() instead of time() because
  // clock() (being measured in "processor ticks" instead of seconds) is likely
  // to exhibit more variation when tests are run many times in a short time
  // span.
  std::srand(boost::numeric_cast<unsigned int>((clock())));

  return RUN_ALL_TESTS();
}

namespace vw {
namespace test {

UnlinkName::UnlinkName(const std::string& base, const std::string& directory)
  : std::string(directory + "/" + base) {

  VW_ASSERT(!directory.empty(), ArgumentErr() << "An empty directory path is dangerous");
  fs::remove_all(this->c_str());
}

UnlinkName::UnlinkName(const char *base, const std::string& directory)
  : std::string(directory + "/" + base) {

  VW_ASSERT(!directory.empty(), ArgumentErr() << "An empty directory path is dangerous");
  fs::remove_all(this->c_str());
}

UnlinkName::~UnlinkName() {
  if (!this->empty())
    fs::remove_all(this->c_str());
}

}} // namespace vw::test
<commit_msg>test to make sure nothing changes the working directory<commit_after>// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#include <gtest/gtest.h>
#include <test/Helpers.h>
#include <vw/Core/Settings.h>

#include <boost/filesystem/operations.hpp>
namespace fs = boost::filesystem;

#if VW_HAVE_FENV_H
#include <fenv.h>
#endif

int main(int argc, char **argv) {
  // Disable the user's config file
  vw::vw_settings().set_rc_filename("");
  ::testing::InitGoogleTest(&argc, argv);

  // Default to the "threadsafe" style because we can't delete our singletons
  // yet; this style of test launches a new process, so the singletons are
  // fresh.
  ::testing::FLAGS_gtest_death_test_style = "threadsafe";

#if VW_HAVE_FEENABLEEXCEPT
  if (getenv("VW_CATCH_FP_ERRORS"))
    feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
#endif

  if (getenv("VW_DEBUG")) {
    vw::vw_log().console_log().rule_set().add_rule(vw::VerboseDebugMessage, "*");
  }

  // TODO: Make it so the seed is settable so we can reproduce failures in
  // probabilistic algorithms. This uses clock() instead of time() because
  // clock() (being measured in "processor ticks" instead of seconds) is likely
  // to exhibit more variation when tests are run many times in a short time
  // span.
  std::srand(boost::numeric_cast<unsigned int>((clock())));

  fs::current_path(TEST_SRCDIR);
  int ret = RUN_ALL_TESTS();
  VW_ASSERT( fs::path(TEST_SRCDIR) == fs::current_path(),
             vw::LogicErr() << "Something changed the working directory");
  return ret;
}

namespace vw {
namespace test {

UnlinkName::UnlinkName(const std::string& base, const std::string& directory)
  : std::string(directory + "/" + base) {

  VW_ASSERT(!directory.empty(), ArgumentErr() << "An empty directory path is dangerous");
  fs::remove_all(this->c_str());
}

UnlinkName::UnlinkName(const char *base, const std::string& directory)
  : std::string(directory + "/" + base) {

  VW_ASSERT(!directory.empty(), ArgumentErr() << "An empty directory path is dangerous");
  fs::remove_all(this->c_str());
}

UnlinkName::~UnlinkName() {
  if (!this->empty())
    fs::remove_all(this->c_str());
}

}} // namespace vw::test
<|endoftext|>


<commit_before>#include "c24/communication/stream.h"

#include <chrono>
#include <string>
#include <thread>
#include <glog/logging.h>

namespace c24 {
namespace communication {

Stream::Stream(std::unique_ptr<StreamBackendInterface> stream_backend)
    : stream_backend_(std::move(stream_backend)) {}

bool Stream::Connected() {
  status_ = Status();
  if (stream_backend_ == nullptr) {
    return false;
  }
  return stream_backend_->Connected();
}

bool Stream::MessageAvailable() {
  CheckConnectionAndReconnect();
  status_ = Status();
  CHECK_NE(stream_backend_, nullptr);
  return stream_backend_->MessageAvailable();
}

std::string Stream::GetMessage() {
  CheckConnectionAndReconnect();
  status_ = Status();
  CHECK_NE(stream_backend_, nullptr);
  std::string msg = stream_backend_->GetMessage();
  LOG(INFO) << "Received: \"" << msg << "\"";
  return msg;
}

bool Stream::SendMessage(const std::string& msg, bool newline) {
  CheckConnectionAndReconnect();
  status_ = Status();
  CHECK_NE(stream_backend_, nullptr);
  // Put two spaces after Sending so it is lined up with messages after
  // Received.
  LOG(INFO) << "Sending:  \"" << msg << "\"";
  const std::string& msg_to_send = newline ? msg + '\n' : msg;
  return stream_backend_->SendMessage(msg_to_send);
}

Status Stream::LastStatus() const {
  if (!status_.Ok()) return status_;
  CHECK_NE(stream_backend_, nullptr);
  return stream_backend_->LastStatus();
}

bool Stream::GetMessageWithCheck(const char* expected) {
  std::string msg_ok = GetMessage();
  if (msg_ok != expected) {
    status_ = stream_backend_->LastStatus();
    if (msg_ok.length() >= 11 && msg_ok.substr(0, 5) == "ERROR") {
      int error_code = std::atoi(msg_ok.substr(6, 3).c_str());
      status_.SetServerError(error_code, msg_ok.substr(11));
    }
    LOG(ERROR) << "Expected \"" << expected << "\" but received \"" << msg_ok
               << "\"";
    return false;
  }
  return true;
}

bool Stream::SendMessageWithCheck(const std::string& msg, bool newline,
                                  const char* expected) {
  status_ = Status();
  bool success = SendMessage(msg, newline);
  if (success) {
    success = GetMessageWithCheck(expected);
  }
  return success;
}

void Stream::CheckConnectionAndReconnect() {
  if (Connected()) return;
  stream_backend_->Reconnect();
  while (!Connected()) {
    std::this_thread::sleep_for(
        std::chrono::milliseconds(TIME_BETWEEN_RECONNECT_TRIES_MILLISECONDS));
    stream_backend_->Reconnect();
  }
}

}  // namespace communication
}  // namespace c24
<commit_msg>Change CHECK_NE to CHECK to fix the compilation.<commit_after>#include "c24/communication/stream.h"

#include <chrono>
#include <string>
#include <thread>
#include <glog/logging.h>

namespace c24 {
namespace communication {

Stream::Stream(std::unique_ptr<StreamBackendInterface> stream_backend)
    : stream_backend_(std::move(stream_backend)) {}

bool Stream::Connected() {
  status_ = Status();
  if (stream_backend_ == nullptr) {
    return false;
  }
  return stream_backend_->Connected();
}

bool Stream::MessageAvailable() {
  CheckConnectionAndReconnect();
  status_ = Status();
  CHECK(stream_backend_ != nullptr);
  return stream_backend_->MessageAvailable();
}

std::string Stream::GetMessage() {
  CheckConnectionAndReconnect();
  status_ = Status();
  CHECK(stream_backend_ != nullptr);
  std::string msg = stream_backend_->GetMessage();
  LOG(INFO) << "Received: \"" << msg << "\"";
  return msg;
}

bool Stream::SendMessage(const std::string& msg, bool newline) {
  CheckConnectionAndReconnect();
  status_ = Status();
  CHECK(stream_backend_ != nullptr);
  // Put two spaces after Sending so it is lined up with messages after
  // Received.
  LOG(INFO) << "Sending:  \"" << msg << "\"";
  const std::string& msg_to_send = newline ? msg + '\n' : msg;
  return stream_backend_->SendMessage(msg_to_send);
}

Status Stream::LastStatus() const {
  if (!status_.Ok()) return status_;
  CHECK(stream_backend_ != nullptr);
  return stream_backend_->LastStatus();
}

bool Stream::GetMessageWithCheck(const char* expected) {
  std::string msg_ok = GetMessage();
  if (msg_ok != expected) {
    status_ = stream_backend_->LastStatus();
    if (msg_ok.length() >= 11 && msg_ok.substr(0, 5) == "ERROR") {
      int error_code = std::atoi(msg_ok.substr(6, 3).c_str());
      status_.SetServerError(error_code, msg_ok.substr(11));
    }
    LOG(ERROR) << "Expected \"" << expected << "\" but received \"" << msg_ok
               << "\"";
    return false;
  }
  return true;
}

bool Stream::SendMessageWithCheck(const std::string& msg, bool newline,
                                  const char* expected) {
  status_ = Status();
  bool success = SendMessage(msg, newline);
  if (success) {
    success = GetMessageWithCheck(expected);
  }
  return success;
}

void Stream::CheckConnectionAndReconnect() {
  if (Connected()) return;
  stream_backend_->Reconnect();
  while (!Connected()) {
    std::this_thread::sleep_for(
        std::chrono::milliseconds(TIME_BETWEEN_RECONNECT_TRIES_MILLISECONDS));
    stream_backend_->Reconnect();
  }
}

}  // namespace communication
}  // namespace c24
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "texturebutton.h"

#include <QPushButton>
#include <QImage>
#include <QFileDialog>
#include <QSettings>
#include <QStandardPaths>
#include <QPainter>
#include <QFileInfo>
#include <QMessageBox>

#include "OgreTexture.h"
#include "OgreImage.h"
#include "OgreHlmsPbsDatablock.h"

TextureButton::TextureButton(QPushButton* button, Ogre::PbsTextureTypes texType) : QObject(button)
{
    Q_ASSERT(button);
    mButton = button;
    //mButton->setStyleSheet("Text-align:left");

    mTextureType = texType;

    connect(button, &QPushButton::clicked, this, &TextureButton::buttonClicked);
}

void TextureButton::updateTexImage(Ogre::HlmsPbsDatablock* datablock, Ogre::PbsTextureTypes textureType)
{
    mDatablock = datablock;

    Ogre::HlmsTextureManager::TextureLocation texLocation;
    texLocation.texture = datablock->getTexture(textureType);
    texLocation.xIdx = datablock->_getTextureIdx(textureType);
    texLocation.yIdx = 0;
    texLocation.divisor = 1;

    if (texLocation.texture.isNull())
    {
        clear();
        return;
    }

    //qDebug() << "Type:" << (int)textureType
    //         << ", X index:" << texLocation.xIdx
    //         << ", Pointer:" << texLocation.texture;

    Ogre::Image img;
    texLocation.texture->convertToImage(img, false, 0, texLocation.xIdx, 1);

    int originalWidth = img.getWidth();
    int originalHeight = img.getHeight();
    //img.resize(64, 64);

    QString textureName;
    const Ogre::String* aliasName = getHlmsTexManager()->findAliasName(texLocation);
    if (aliasName)
    {
        textureName = QString::fromStdString(*aliasName);
    }
    setInfoText(textureName, originalWidth, originalHeight);

    QImage qtImg = toQtImage(img);
    if (!qtImg.isNull())
    {
        QPixmap pixmap = QPixmap::fromImage(qtImg);
        mButton->setIconSize(QSize(64, 64));
        mButton->setIcon(QIcon(pixmap));
    }
    else
    {
        // TODO: show unknown format
        mButton->setIcon(QIcon());
        mButton->setIconSize(QSize(1, 1));
    }
}

void TextureButton::buttonClicked()
{
    QSettings settings("OgreV2ModelViewer", "OgreV2ModelViewer");
    QString myDocument = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation)[0];
    QString defaultFolder = settings.value("textureLocation", myDocument).toString();

    QString fileName = QFileDialog::getOpenFileName(mButton, "Load textures", defaultFolder, "Images (*.png *.jpg *.dds *.bmp *.tga *.hdr)");
    if (fileName.isEmpty()) { return; }

    if (mDatablock)
    {
        Ogre::HlmsTextureManager::TextureLocation loc;
        bool ok = LoadImage(fileName, loc);
        if (ok)
        {
            mDatablock->setTexture(mTextureType, loc.xIdx, loc.texture);
            updateTexImage(mDatablock, mTextureType);

            settings.setValue("textureLocation", QFileInfo(fileName).absolutePath());
        }
        else
        {
            QMessageBox::information(mButton, "Error", "Ogre3D cannot load this texture");
        }
    }
}

void TextureButton::setInfoText(const QString& texName, int width, int height)
{
    QString texInfo = QString("%1\n%2x%3")
        .arg(texName)
        .arg(width)
        .arg(height);
    mButton->setText(texInfo);
}

Ogre::HlmsTextureManager* TextureButton::getHlmsTexManager()
{
    if (mHlmsTexManager == nullptr)
        mHlmsTexManager = Ogre::Root::getSingleton().getHlmsManager()->getTextureManager();
    return mHlmsTexManager;
}

void TextureButton::clear()
{
    mButton->setIcon(QIcon());
    mButton->setIconSize(QSize(1, 1));
    mButton->setText("No Texture");
}

QImage::Format TextureButton::toQtImageFormat(Ogre::PixelFormat ogreFormat)
{
    switch (ogreFormat)
    {
    case Ogre::PF_A8R8G8B8: return QImage::Format_ARGB32;
    case Ogre::PF_A8: return QImage::Format_Alpha8;
    case Ogre::PF_L8: return QImage::Format_Grayscale8;
    //case Ogre::PF_A8B8G8R8: return QImage::Format_Invalid;
    default:
        qDebug() << "Unknown tex format:" << ogreFormat;
        break;
    }
    return QImage::Format_Invalid;
}

QImage TextureButton::toQtImage(const Ogre::Image& img)
{
    QImage::Format qtFormat = toQtImageFormat(img.getFormat());
    if (qtFormat != QImage::Format_Invalid)
    {
        QImage qImg(img.getData(), img.getWidth(), img.getHeight(), qtFormat);
        return qImg;
    }

    switch(img.getFormat())
    {
    case Ogre::PF_R8G8_SNORM:
    {
        QImage qtImg(img.getWidth(), img.getHeight(), QImage::Format_RGBA8888_Premultiplied);

        char* src = (char*)img.getData();
        for (size_t x = 0; x < img.getWidth(); ++x)
        {
            for (size_t y = 0; y < img.getHeight(); ++y)
            {
                size_t src_byte_offset = x * y * 2;
                int r = src[src_byte_offset + 0] + 128;
                int g = src[src_byte_offset + 1] + 128;
                qtImg.setPixel((int)x, (int)y, qRgb(r, g, 255));
            }
        }
        //qtImg.save("C:/Temp/normal.png");
        return qtImg;
        break;
    }
    case Ogre::PF_A8B8G8R8:
    {
        QImage qtImg(img.getWidth(), img.getHeight(), QImage::Format_RGBA8888_Premultiplied);
        break;
    }
    default:
        break;
    }

    static QImage emptyImg(64, 64, QImage::Format_RGBA8888_Premultiplied);
    QPainter painter(&emptyImg);
    painter.fillRect(QRect(0, 0, 64, 64), Qt::white);
    painter.drawText(13, 30, "Preview");
    painter.drawText(6, 42, "Unavailable");
    return emptyImg;
}

bool TextureButton::LoadImage(const QString& texturePath, Ogre::HlmsTextureManager::TextureLocation& loc)
{
    bool ok = false;
    std::ifstream ifs(texturePath.toStdWString(), std::ios::binary | std::ios::in);
    ON_SCOPE_EXIT(ifs.close());
    if (!ifs.is_open()) { return false; }

    QString fileExt = QFileInfo(texturePath).suffix();
    if (fileExt.isEmpty()) { return false; }

    std::string texName = texturePath.toStdString();
    Ogre::DataStreamPtr dataStream(new Ogre::FileStreamDataStream(texName, &ifs, false));

    try
    {
        Ogre::Image img;
        img.load(dataStream, fileExt.toStdString());

        if (img.getWidth() == 0) { return false; }

        Ogre::HlmsTextureManager::TextureMapType mapType;
        switch (mTextureType) {
        case Ogre::PBSM_DIFFUSE:
        case Ogre::PBSM_EMISSIVE:
            mapType = Ogre::HlmsTextureManager::TEXTURE_TYPE_DIFFUSE;
            break;
        case Ogre::PBSM_METALLIC:
        case Ogre::PBSM_ROUGHNESS:
            mapType = Ogre::HlmsTextureManager::TEXTURE_TYPE_MONOCHROME;
            break;
        case Ogre::PBSM_NORMAL:
            mapType = Ogre::HlmsTextureManager::TEXTURE_TYPE_NORMALS;
            break;
        case Ogre::PBSM_REFLECTION:
            mapType = Ogre::HlmsTextureManager::TEXTURE_TYPE_ENV_MAP;
            break;
        default:
            Ogre::HlmsTextureManager::TEXTURE_TYPE_DETAIL;
            Ogre::HlmsTextureManager::TEXTURE_TYPE_DETAIL_NORMAL_MAP;
            Ogre::HlmsTextureManager::TEXTURE_TYPE_NON_COLOR_DATA;
            break;
        }
        loc = mHlmsTexManager->createOrRetrieveTexture(texName, texName, mapType, 0, &img);
        ok = true;
    }
    catch(Ogre::Exception& e)
    {
        qDebug() << e.what();
        ok = false;
    }
    return ok;
}<commit_msg>Fix a crash on loading textures<commit_after>#include "stdafx.h"
#include "texturebutton.h"

#include <QPushButton>
#include <QImage>
#include <QFileDialog>
#include <QSettings>
#include <QStandardPaths>
#include <QPainter>
#include <QFileInfo>
#include <QMessageBox>

#include "OgreTexture.h"
#include "OgreImage.h"
#include "OgreHlmsPbsDatablock.h"

TextureButton::TextureButton(QPushButton* button, Ogre::PbsTextureTypes texType) : QObject(button)
{
    Q_ASSERT(button);
    mButton = button;
    //mButton->setStyleSheet("Text-align:left");

    mTextureType = texType;

    connect(button, &QPushButton::clicked, this, &TextureButton::buttonClicked);
}

void TextureButton::updateTexImage(Ogre::HlmsPbsDatablock* datablock, Ogre::PbsTextureTypes textureType)
{
    mDatablock = datablock;

    Ogre::HlmsTextureManager::TextureLocation texLocation;
    texLocation.texture = datablock->getTexture(textureType);
    texLocation.xIdx = datablock->_getTextureIdx(textureType);
    texLocation.yIdx = 0;
    texLocation.divisor = 1;

    if (texLocation.texture.isNull())
    {
        clear();
        return;
    }

    //qDebug() << "Type:" << (int)textureType
    //         << ", X index:" << texLocation.xIdx
    //         << ", Pointer:" << texLocation.texture;

    Ogre::Image img;
    texLocation.texture->convertToImage(img, false, 0, texLocation.xIdx, 1);

    int originalWidth = img.getWidth();
    int originalHeight = img.getHeight();
    //img.resize(64, 64);

    QString textureName;
    const Ogre::String* aliasName = getHlmsTexManager()->findAliasName(texLocation);
    if (aliasName)
    {
        textureName = QString::fromStdString(*aliasName);
    }
    setInfoText(textureName, originalWidth, originalHeight);

    QImage qtImg = toQtImage(img);
    if (!qtImg.isNull())
    {
        QPixmap pixmap = QPixmap::fromImage(qtImg);
        mButton->setIconSize(QSize(64, 64));
        mButton->setIcon(QIcon(pixmap));
    }
    else
    {
        // TODO: show unknown format
        mButton->setIcon(QIcon());
        mButton->setIconSize(QSize(1, 1));
    }
}

void TextureButton::buttonClicked()
{
    QSettings settings("OgreV2ModelViewer", "OgreV2ModelViewer");
    QString myDocument = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation)[0];
    QString defaultFolder = settings.value("textureLocation", myDocument).toString();

    QString fileName = QFileDialog::getOpenFileName(mButton, "Load textures", defaultFolder, "Images (*.png *.jpg *.dds *.bmp *.tga *.hdr)");
    if (fileName.isEmpty()) { return; }

    if (mDatablock)
    {
        Ogre::HlmsTextureManager::TextureLocation loc;
        bool ok = LoadImage(fileName, loc);
        if (ok)
        {
            mDatablock->setTexture(mTextureType, loc.xIdx, loc.texture);
            updateTexImage(mDatablock, mTextureType);

            settings.setValue("textureLocation", QFileInfo(fileName).absolutePath());
        }
        else
        {
            QMessageBox::information(mButton, "Error", "Ogre3D cannot load this texture");
        }
    }
}

void TextureButton::setInfoText(const QString& texName, int width, int height)
{
    QString texInfo = QString("%1\n%2x%3")
        .arg(texName)
        .arg(width)
        .arg(height);
    mButton->setText(texInfo);
}

Ogre::HlmsTextureManager* TextureButton::getHlmsTexManager()
{
    if (mHlmsTexManager == nullptr)
        mHlmsTexManager = Ogre::Root::getSingleton().getHlmsManager()->getTextureManager();
    return mHlmsTexManager;
}

void TextureButton::clear()
{
    mButton->setIcon(QIcon());
    mButton->setIconSize(QSize(1, 1));
    mButton->setText("No Texture");
}

QImage::Format TextureButton::toQtImageFormat(Ogre::PixelFormat ogreFormat)
{
    switch (ogreFormat)
    {
    case Ogre::PF_A8R8G8B8: return QImage::Format_ARGB32;
    case Ogre::PF_A8: return QImage::Format_Alpha8;
    case Ogre::PF_L8: return QImage::Format_Grayscale8;
    //case Ogre::PF_A8B8G8R8: return QImage::Format_Invalid;
    default:
        qDebug() << "Unknown tex format:" << ogreFormat;
        break;
    }
    return QImage::Format_Invalid;
}

QImage TextureButton::toQtImage(const Ogre::Image& img)
{
    QImage::Format qtFormat = toQtImageFormat(img.getFormat());
    if (qtFormat != QImage::Format_Invalid)
    {
        QImage qImg(img.getData(), img.getWidth(), img.getHeight(), qtFormat);
        return qImg;
    }

    switch(img.getFormat())
    {
    case Ogre::PF_R8G8_SNORM:
    {
        QImage qtImg(img.getWidth(), img.getHeight(), QImage::Format_RGBA8888_Premultiplied);

        char* src = (char*)img.getData();
        for (size_t x = 0; x < img.getWidth(); ++x)
        {
            for (size_t y = 0; y < img.getHeight(); ++y)
            {
                size_t src_byte_offset = x * y * 2;
                int r = src[src_byte_offset + 0] + 128;
                int g = src[src_byte_offset + 1] + 128;
                qtImg.setPixel((int)x, (int)y, qRgb(r, g, 255));
            }
        }
        //qtImg.save("C:/Temp/normal.png");
        return qtImg;
        break;
    }
    case Ogre::PF_A8B8G8R8:
    {
        QImage qtImg(img.getWidth(), img.getHeight(), QImage::Format_RGBA8888_Premultiplied);
        break;
    }
    default:
        break;
    }

    static QImage emptyImg(64, 64, QImage::Format_RGBA8888_Premultiplied);
    QPainter painter(&emptyImg);
    painter.fillRect(QRect(0, 0, 64, 64), Qt::white);
    painter.drawText(13, 30, "Preview");
    painter.drawText(6, 42, "Unavailable");
    return emptyImg;
}

bool TextureButton::LoadImage(const QString& texturePath, Ogre::HlmsTextureManager::TextureLocation& loc)
{
    bool ok = false;
    std::ifstream ifs(texturePath.toStdWString(), std::ios::binary | std::ios::in);
    ON_SCOPE_EXIT(ifs.close());
    if (!ifs.is_open()) { return false; }

    QString fileExt = QFileInfo(texturePath).suffix();
    if (fileExt.isEmpty()) { return false; }

    std::string texName = texturePath.toStdString();
    Ogre::DataStreamPtr dataStream(new Ogre::FileStreamDataStream(texName, &ifs, false));

    try
    {
        Ogre::Image img;
        img.load(dataStream, fileExt.toStdString());

        if (img.getWidth() == 0) { return false; }

        Ogre::HlmsTextureManager::TextureMapType mapType;
        switch (mTextureType) {
        case Ogre::PBSM_DIFFUSE:
        case Ogre::PBSM_EMISSIVE:
            mapType = Ogre::HlmsTextureManager::TEXTURE_TYPE_DIFFUSE;
            break;
        case Ogre::PBSM_METALLIC:
        case Ogre::PBSM_ROUGHNESS:
            mapType = Ogre::HlmsTextureManager::TEXTURE_TYPE_MONOCHROME;
            break;
        case Ogre::PBSM_NORMAL:
            mapType = Ogre::HlmsTextureManager::TEXTURE_TYPE_NORMALS;
            break;
        case Ogre::PBSM_REFLECTION:
            mapType = Ogre::HlmsTextureManager::TEXTURE_TYPE_ENV_MAP;
            break;
        default:
            Ogre::HlmsTextureManager::TEXTURE_TYPE_DETAIL;
            Ogre::HlmsTextureManager::TEXTURE_TYPE_DETAIL_NORMAL_MAP;
            Ogre::HlmsTextureManager::TEXTURE_TYPE_NON_COLOR_DATA;
            break;
        }
        loc = getHlmsTexManager()->createOrRetrieveTexture(texName, texName, mapType, 0, &img);
        ok = true;
    }
    catch(Ogre::Exception& e)
    {
        qDebug() << e.what();
        ok = false;
    }
    return ok;
}<|endoftext|>


<commit_before>// Copyright (c) 2016 Mirants Lu. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "voyager/core/tcp_connection.h"

#include <unistd.h>
#include <errno.h>

#include "voyager/core/dispatch.h"
#include "voyager/core/eventloop.h"
#include "voyager/util/logging.h"
#include "voyager/util/slice.h"

namespace voyager {

TcpConnection::TcpConnection(const std::string& name,
                             EventLoop* ev, int fd)
    : name_(name),
      eventloop_(CHECK_NOTNULL(ev)),
      socket_(fd),
      state_(kConnecting),
      dispatch_(new Dispatch(ev, fd)),
      high_water_mark_(64 * 1024 * 1024) {
  dispatch_->SetReadCallback(
      std::bind(&TcpConnection::HandleRead, this));
  dispatch_->SetWriteCallback(
      std::bind(&TcpConnection::HandleWrite, this));
  dispatch_->SetCloseCallback(
      std::bind(&TcpConnection::HandleClose, this));
  dispatch_->SetErrorCallback(
      std::bind(&TcpConnection::HandleError, this));
  socket_.SetNonBlockAndCloseOnExec(true);
  socket_.SetKeepAlive(true);
  socket_.SetTcpNoDelay(true);
  VOYAGER_LOG(DEBUG) << "TcpConnection::TcpConnection [" << name_
                     << "] at " << this << " fd=" << fd;
}

TcpConnection::~TcpConnection() {
  VOYAGER_LOG(DEBUG) << "TcpConnection::~TcpConnection [" << name_
                     << "] at " << this << " fd=" << dispatch_->Fd()
                     << " ConnectState=" << StateToString();
}

void TcpConnection::StartWorking() {
  eventloop_->AssertInMyLoop();
  assert(state_ == kConnecting);
  state_ = kConnected;
  TcpConnectionPtr ptr(shared_from_this());
  dispatch_->Tie(ptr);
  dispatch_->EnableRead();
  eventloop_->AddConnection(ptr);
  if (connection_cb_) {
    connection_cb_(ptr);
  }
}

void TcpConnection::StartRead() {
  TcpConnectionPtr ptr(shared_from_this());
  eventloop_->RunInLoop([ptr]() {
    if (!ptr->dispatch_->IsReading()) {
      ptr->dispatch_->EnableRead();
    }
  });
}

void TcpConnection::StopRead() {
  TcpConnectionPtr ptr(shared_from_this());
  eventloop_->RunInLoop([ptr]() {
    if (ptr->dispatch_->IsReading()) {
      ptr->dispatch_->DisableRead();
    }
  });
}

void TcpConnection::ShutDown() {
  ConnectState expected = kConnected;
  if (state_.compare_exchange_weak(expected, kDisconnecting)) {
    TcpConnectionPtr ptr(shared_from_this());
    eventloop_->RunInLoop([ptr]() {
      if (!ptr->dispatch_->IsWriting()) {
        ptr->socket_.ShutDownWrite();
      }
    });
  }
}

void TcpConnection::ForceClose() {
  ConnectState expected = kConnected;
  if (state_.compare_exchange_weak(expected, kDisconnecting) ||
      state_ == kDisconnecting) {
    TcpConnectionPtr ptr(shared_from_this());
    eventloop_->QueueInLoop([ptr]() {
      if (ptr->state_ == kConnected || ptr->state_ == kDisconnecting) {
        ptr->HandleClose();
      }
    });
  }
}

void TcpConnection::HandleRead() {
  eventloop_->AssertInMyLoop();
  ssize_t n = readbuf_.ReadV(dispatch_->Fd());
  if (n > 0) {
    if (message_cb_) {
      message_cb_(shared_from_this(), &readbuf_);
    }
  } else if (n == 0) {
    HandleClose();
  } else {
    if (errno == EPIPE || errno == ECONNRESET) {
      HandleClose();
    }
    if (errno != EWOULDBLOCK && errno != EAGAIN) {
      VOYAGER_LOG(ERROR) << "TcpConnection::HandleRead [" << name_
                         <<"] - readv: " << strerror(errno);
    }
  }
}

void TcpConnection::HandleWrite() {
  eventloop_->AssertInMyLoop();
  if (dispatch_->IsWriting()) {
    ssize_t n = ::write(dispatch_->Fd(),
                        writebuf_.Peek(),
                        writebuf_.ReadableSize());
    if (n >= 0) {
      writebuf_.Retrieve(static_cast<size_t>(n));
      if (writebuf_.ReadableSize() == 0) {
        dispatch_->DisableWrite();
        if (writecomplete_cb_) {
          writecomplete_cb_(shared_from_this());
        }
        if (state_ == kDisconnecting) {
          HandleClose();
        }
      }
    } else {
      if (errno == EPIPE || errno == ECONNRESET) {
        HandleClose();
      }
      if (errno != EWOULDBLOCK && errno != EAGAIN) {
        VOYAGER_LOG(ERROR) << "TcpConnection::HandleWrite [" << name_
                           << "] - write: " << strerror(errno);
      }
    }
  } else {
    VOYAGER_LOG(INFO) << "TcpConnection::HandleWrite [" << name_
                      << "] - fd=" << dispatch_->Fd()
                      << " is down, no more writing";
  }
}

void TcpConnection::HandleClose() {
  eventloop_->AssertInMyLoop();
  assert(state_ == kConnected || state_ == kDisconnecting);
  state_ = kDisconnected;
  dispatch_->DisableAll();
  dispatch_->RemoveEvents();
  eventloop_->RemoveCnnection(shared_from_this());
  if (close_cb_) {
    close_cb_(shared_from_this());
  }
}

void TcpConnection::HandleError() {
  Status st = socket_.CheckSocketError();
  if (!st.ok()) {
    VOYAGER_LOG(ERROR) << "TcpConnection::HandleError [" << name_
                       << "] - " << st;
  }
}

void TcpConnection::SendMessage(std::string&& message) {
  if (state_ == kConnected) {
    if (eventloop_->IsInMyLoop()) {
      SendInLoop(message.data(), message.size());
    } else {
      eventloop_->RunInLoop(
          std::bind(&TcpConnection::Send,
                    shared_from_this(),
                    std::move(message)));
    }
  }
}

void TcpConnection::SendMessage(const Slice& message) {
  if (state_ == kConnected) {
    if (eventloop_->IsInMyLoop()) {
      SendInLoop(message.data(), message.size());
    } else {
      eventloop_->RunInLoop(
          std::bind(&TcpConnection::Send,
                    shared_from_this(),
                    message.ToString()));
    }
  }
}

void TcpConnection::SendMessage(Buffer* message) {
  CHECK_NOTNULL(message);
  if (state_ == kConnected) {
    if (eventloop_->IsInMyLoop()) {
      SendInLoop(message->Peek(), message->ReadableSize());
      message->RetrieveAll();
    } else {
      std::shared_ptr<std::string> s(
          new std::string(message->Peek(), message->ReadableSize()));
      message->RetrieveAll();
      eventloop_->RunInLoop(
          std::bind(&TcpConnection::Send,
                    shared_from_this(),
                    message->RetrieveAllAsString()));
    }
  }
}

void TcpConnection::Send(const std::string& s) {
  SendInLoop(s.data(), s.size());
}

void TcpConnection::SendInLoop(const void* data, size_t size) {
  eventloop_->AssertInMyLoop();
  if (state_ == kDisconnected) {
    VOYAGER_LOG(WARN) << "TcpConnection::SendInLoop[" << name_ << "]"
                      << "has disconnected, give up writing.";
    return;
  }

  ssize_t nwrote = 0;
  size_t  remaining = size;
  bool fault = false;

  if (!dispatch_->IsWriting() && writebuf_.ReadableSize() == 0) {
    nwrote = ::write(dispatch_->Fd(), data, size);
    if (nwrote >= 0) {
      remaining = size - static_cast<size_t>(nwrote);
      if (remaining == 0 && writecomplete_cb_) {
        writecomplete_cb_(shared_from_this());
      }
    } else {
      nwrote = 0;
      if (errno == EPIPE || errno == ECONNRESET) {
        HandleClose();
        fault = true;
      }
      if (errno != EWOULDBLOCK && errno != EAGAIN) {
        VOYAGER_LOG(ERROR) << "TcpConnection::SendInLoop [" << name_
                           << "] - write: " << strerror(errno);
      }
    }
  }

  assert(remaining <= size);
  if (!fault && remaining > 0) {
    size_t old = writebuf_.ReadableSize();
    if (high_water_mark_cb_ &&
        old < high_water_mark_ &&
        (old + remaining) >= high_water_mark_) {
      eventloop_->QueueInLoop(
          std::bind(high_water_mark_cb_, shared_from_this(), old + remaining));
    }
    writebuf_.Append(static_cast<const char*>(data)+nwrote, remaining);
    if (!dispatch_->IsWriting()) {
      dispatch_->EnableWrite();
    }
  }
}

std::string TcpConnection::StateToString() const {
  const char *type;
  switch (state_.load(std::memory_order_relaxed)) {
    case kDisconnected:
      type = "Disconnected";
      break;
    case kDisconnecting:
      type = "Disconnecting";
      break;
    case kConnected:
      type = "Connected";
      break;
    case kConnecting:
      type = "Connecting";
      break;
    default:
      type = "Unknown State";
      break;
  }
  std::string result(type);
  return result;
}

}  // namespace voyager
<commit_msg>fix sendmessage bug<commit_after>// Copyright (c) 2016 Mirants Lu. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "voyager/core/tcp_connection.h"

#include <unistd.h>
#include <errno.h>

#include "voyager/core/dispatch.h"
#include "voyager/core/eventloop.h"
#include "voyager/util/logging.h"
#include "voyager/util/slice.h"

namespace voyager {

TcpConnection::TcpConnection(const std::string& name,
                             EventLoop* ev, int fd)
    : name_(name),
      eventloop_(CHECK_NOTNULL(ev)),
      socket_(fd),
      state_(kConnecting),
      dispatch_(new Dispatch(ev, fd)),
      high_water_mark_(64 * 1024 * 1024) {
  dispatch_->SetReadCallback(
      std::bind(&TcpConnection::HandleRead, this));
  dispatch_->SetWriteCallback(
      std::bind(&TcpConnection::HandleWrite, this));
  dispatch_->SetCloseCallback(
      std::bind(&TcpConnection::HandleClose, this));
  dispatch_->SetErrorCallback(
      std::bind(&TcpConnection::HandleError, this));
  socket_.SetNonBlockAndCloseOnExec(true);
  socket_.SetKeepAlive(true);
  socket_.SetTcpNoDelay(true);
  VOYAGER_LOG(DEBUG) << "TcpConnection::TcpConnection [" << name_
                     << "] at " << this << " fd=" << fd;
}

TcpConnection::~TcpConnection() {
  VOYAGER_LOG(DEBUG) << "TcpConnection::~TcpConnection [" << name_
                     << "] at " << this << " fd=" << dispatch_->Fd()
                     << " ConnectState=" << StateToString();
}

void TcpConnection::StartWorking() {
  eventloop_->AssertInMyLoop();
  assert(state_ == kConnecting);
  state_ = kConnected;
  TcpConnectionPtr ptr(shared_from_this());
  dispatch_->Tie(ptr);
  dispatch_->EnableRead();
  eventloop_->AddConnection(ptr);
  if (connection_cb_) {
    connection_cb_(ptr);
  }
}

void TcpConnection::StartRead() {
  TcpConnectionPtr ptr(shared_from_this());
  eventloop_->RunInLoop([ptr]() {
    if (!ptr->dispatch_->IsReading()) {
      ptr->dispatch_->EnableRead();
    }
  });
}

void TcpConnection::StopRead() {
  TcpConnectionPtr ptr(shared_from_this());
  eventloop_->RunInLoop([ptr]() {
    if (ptr->dispatch_->IsReading()) {
      ptr->dispatch_->DisableRead();
    }
  });
}

void TcpConnection::ShutDown() {
  ConnectState expected = kConnected;
  if (state_.compare_exchange_weak(expected, kDisconnecting)) {
    TcpConnectionPtr ptr(shared_from_this());
    eventloop_->RunInLoop([ptr]() {
      if (!ptr->dispatch_->IsWriting()) {
        ptr->socket_.ShutDownWrite();
      }
    });
  }
}

void TcpConnection::ForceClose() {
  ConnectState expected = kConnected;
  if (state_.compare_exchange_weak(expected, kDisconnecting) ||
      state_ == kDisconnecting) {
    TcpConnectionPtr ptr(shared_from_this());
    eventloop_->QueueInLoop([ptr]() {
      if (ptr->state_ == kConnected || ptr->state_ == kDisconnecting) {
        ptr->HandleClose();
      }
    });
  }
}

void TcpConnection::HandleRead() {
  eventloop_->AssertInMyLoop();
  ssize_t n = readbuf_.ReadV(dispatch_->Fd());
  if (n > 0) {
    if (message_cb_) {
      message_cb_(shared_from_this(), &readbuf_);
    }
  } else if (n == 0) {
    HandleClose();
  } else {
    if (errno == EPIPE || errno == ECONNRESET) {
      HandleClose();
    }
    if (errno != EWOULDBLOCK && errno != EAGAIN) {
      VOYAGER_LOG(ERROR) << "TcpConnection::HandleRead [" << name_
                         <<"] - readv: " << strerror(errno);
    }
  }
}

void TcpConnection::HandleWrite() {
  eventloop_->AssertInMyLoop();
  if (dispatch_->IsWriting()) {
    ssize_t n = ::write(dispatch_->Fd(),
                        writebuf_.Peek(),
                        writebuf_.ReadableSize());
    if (n >= 0) {
      writebuf_.Retrieve(static_cast<size_t>(n));
      if (writebuf_.ReadableSize() == 0) {
        dispatch_->DisableWrite();
        if (writecomplete_cb_) {
          writecomplete_cb_(shared_from_this());
        }
        if (state_ == kDisconnecting) {
          HandleClose();
        }
      }
    } else {
      if (errno == EPIPE || errno == ECONNRESET) {
        HandleClose();
      }
      if (errno != EWOULDBLOCK && errno != EAGAIN) {
        VOYAGER_LOG(ERROR) << "TcpConnection::HandleWrite [" << name_
                           << "] - write: " << strerror(errno);
      }
    }
  } else {
    VOYAGER_LOG(INFO) << "TcpConnection::HandleWrite [" << name_
                      << "] - fd=" << dispatch_->Fd()
                      << " is down, no more writing";
  }
}

void TcpConnection::HandleClose() {
  eventloop_->AssertInMyLoop();
  assert(state_ == kConnected || state_ == kDisconnecting);
  state_ = kDisconnected;
  dispatch_->DisableAll();
  dispatch_->RemoveEvents();
  eventloop_->RemoveCnnection(shared_from_this());
  if (close_cb_) {
    close_cb_(shared_from_this());
  }
}

void TcpConnection::HandleError() {
  Status st = socket_.CheckSocketError();
  if (!st.ok()) {
    VOYAGER_LOG(ERROR) << "TcpConnection::HandleError [" << name_
                       << "] - " << st;
  }
}

void TcpConnection::SendMessage(std::string&& message) {
  if (state_ == kConnected) {
    if (eventloop_->IsInMyLoop()) {
      SendInLoop(message.data(), message.size());
    } else {
      eventloop_->RunInLoop(
          std::bind(&TcpConnection::Send,
                    shared_from_this(),
                    std::move(message)));
    }
  }
}

void TcpConnection::SendMessage(const Slice& message) {
  if (state_ == kConnected) {
    if (eventloop_->IsInMyLoop()) {
      SendInLoop(message.data(), message.size());
    } else {
      eventloop_->RunInLoop(
          std::bind(&TcpConnection::Send,
                    shared_from_this(),
                    message.ToString()));
    }
  }
}

void TcpConnection::SendMessage(Buffer* message) {
  CHECK_NOTNULL(message);
  if (state_ == kConnected) {
    if (eventloop_->IsInMyLoop()) {
      SendInLoop(message->Peek(), message->ReadableSize());
      message->RetrieveAll();
    } else {
      eventloop_->RunInLoop(
          std::bind(&TcpConnection::Send,
                    shared_from_this(),
                    message->RetrieveAllAsString()));
    }
  }
}

void TcpConnection::Send(const std::string& s) {
  SendInLoop(s.data(), s.size());
}

void TcpConnection::SendInLoop(const void* data, size_t size) {
  eventloop_->AssertInMyLoop();
  if (state_ == kDisconnected) {
    VOYAGER_LOG(WARN) << "TcpConnection::SendInLoop[" << name_ << "]"
                      << "has disconnected, give up writing.";
    return;
  }

  ssize_t nwrote = 0;
  size_t  remaining = size;
  bool fault = false;

  if (!dispatch_->IsWriting() && writebuf_.ReadableSize() == 0) {
    nwrote = ::write(dispatch_->Fd(), data, size);
    if (nwrote >= 0) {
      remaining = size - static_cast<size_t>(nwrote);
      if (remaining == 0 && writecomplete_cb_) {
        writecomplete_cb_(shared_from_this());
      }
    } else {
      nwrote = 0;
      if (errno == EPIPE || errno == ECONNRESET) {
        HandleClose();
        fault = true;
      }
      if (errno != EWOULDBLOCK && errno != EAGAIN) {
        VOYAGER_LOG(ERROR) << "TcpConnection::SendInLoop [" << name_
                           << "] - write: " << strerror(errno);
      }
    }
  }

  assert(remaining <= size);
  if (!fault && remaining > 0) {
    size_t old = writebuf_.ReadableSize();
    if (high_water_mark_cb_ &&
        old < high_water_mark_ &&
        (old + remaining) >= high_water_mark_) {
      eventloop_->QueueInLoop(
          std::bind(high_water_mark_cb_, shared_from_this(), old + remaining));
    }
    writebuf_.Append(static_cast<const char*>(data)+nwrote, remaining);
    if (!dispatch_->IsWriting()) {
      dispatch_->EnableWrite();
    }
  }
}

std::string TcpConnection::StateToString() const {
  const char *type;
  switch (state_.load(std::memory_order_relaxed)) {
    case kDisconnected:
      type = "Disconnected";
      break;
    case kDisconnecting:
      type = "Disconnecting";
      break;
    case kConnected:
      type = "Connected";
      break;
    case kConnecting:
      type = "Connecting";
      break;
    default:
      type = "Unknown State";
      break;
  }
  std::string result(type);
  return result;
}

}  // namespace voyager
<|endoftext|>


<commit_before>#include <string>
using std::string;
class Sales_data{
public:
    Sales_data() = default;
    ~Sales_data() = default;
    Sales_data(int i):a(i){}
    Sales_data(const Sales_data &rhs):a(rhs.a){}
    Sales_data& operator=(const Sales_data&rhs){
        a = rhs.a;
        return *this;
    }
private:
    int a = 0;
};

class Token{
public:
    Token():tok(INT),ival(0){}
    Token(const Token&t): tok(t.tok){copyUnion(t);}
    ~Token(){
        if(tok == STR) sval.~string();
        if(tok == SAL) item.~Sales_data();
    }
    Token& operator=(Token &&);
    Token(Token&&);
    Token& operator=(const Token&);
    Token& operator=(const string&);
    Token& operator=(const int&);
    Token& operator=(const char&);
    Token& operator=(const Sales_data&);
private:
    enum { INT, CHAR, STR, SAL} tok;
    union{
        char cval;
        int ival;
        std::string sval;
        Sales_data item;
    };
    void copyUnion(const Token&);
    //move edition
    void copyUnion(Token&&);
};
void Token::copyUnion(Token&& t){
    switch (t.tok) {
        case INT  : ival = t.ival; break;
        case CHAR : cval = t.cval; break;
        case STR  : std::move(t.sval);break;
        case SAL  : std::move(t.item); break;
    }
}
void Token::copyUnion(const Token &t){
    switch (t.tok) {
        case INT  : ival = t.ival; break;
        case CHAR : cval = t.cval; break;
        case STR  : new(&sval) string(t.sval);break;
        case SAL  : new(&item) Sales_data(t.item); break;
    }
}

Token& Token::operator=(const Token&t){
    if(tok == STR && t.tok != STR) sval.~string();
    if(tok == SAL && t.tok != SAL) item.~Sales_data();
    if(tok == STR && t.tok == STR) sval = t.sval;
    if(tok == SAL && t.tok == SAL) item = t.item;
    else copyUnion(t);
    tok = t.tok;
    return *this;
}

//move constructor
Token& Token::operator=(Token&& t){
    if(this != &t){
        this->~Token();
        copyUnion(t);
        tok = std::move(t.tok);
    }
    return *this;
}
Token::Token(Token &&t){
    copyUnion(t);
    tok = std::move(t.tok);
}

Token& Token::operator=(const Sales_data& rhs){
    if(tok == STR) sval.~string();
    if(tok == SAL)
        item = rhs;
    else
        new(&item) Sales_data(rhs);
    tok = SAL;
    return *this;
}
Token& Token::operator=(const int& i){
    if(tok == STR) sval.~string();
    if(tok == SAL) item.~Sales_data();
    ival = i;
    tok = INT;
    return *this;
}

int main(int argc, char const *argv[]) {
    Token s;
    Sales_data sal(5);
    s =  sal;
    return 0;
}
<commit_msg>Add i<commit_after>#include <iostream>
#include <string>
using std::string;
class Sales_data{
public:
    Sales_data() = default;
    ~Sales_data() = default;
    Sales_data(int i):a(i){}
    Sales_data(const Sales_data &rhs):a(rhs.a){}
    Sales_data& operator=(const Sales_data&rhs){
        a = rhs.a;
        return *this;
    }
private:
    int a = 0;
};

class Token{
public:
    Token():tok(INT),ival(0){}
    Token(const Token&t): tok(t.tok){copyUnion(t);}
    ~Token(){
        if(tok == STR) sval.~string();
        if(tok == SAL) item.~Sales_data();
    }
    Token& operator=(Token &&);
    Token(Token&&);
    Token& operator=(const Token&);
    Token& operator=(const string&);
    Token& operator=(const int&);
    Token& operator=(const char&);
    Token& operator=(const Sales_data&);
private:
    enum { INT, CHAR, STR, SAL} tok;
    union{
        char cval;
        int ival;
        std::string sval;
        Sales_data item;
    };
    void copyUnion(const Token&);
    //move edition
    void copyUnion(Token&&);
};
void Token::copyUnion(Token&& t){
    switch (t.tok) {
        case INT  : ival = t.ival; break;
        case CHAR : cval = t.cval; break;
        case STR  : std::move(t.sval);break;
        case SAL  : std::move(t.item); break;
    }
}
void Token::copyUnion(const Token &t){
    switch (t.tok) {
        case INT  : ival = t.ival; break;
        case CHAR : cval = t.cval; break;
        case STR  : new(&sval) string(t.sval);break;
        case SAL  : new(&item) Sales_data(t.item); break;
    }
}

Token& Token::operator=(const Token&t){
    if(tok == STR && t.tok != STR) sval.~string();
    if(tok == SAL && t.tok != SAL) item.~Sales_data();
    if(tok == STR && t.tok == STR) sval = t.sval;
    if(tok == SAL && t.tok == SAL) item = t.item;
    else copyUnion(t);
    tok = t.tok;
    return *this;
}

//move constructor
Token& Token::operator=(Token&& t){
    if(this != &t){
        this->~Token();
        copyUnion(t);
        tok = std::move(t.tok);
    }
    return *this;
}
Token::Token(Token &&t){
    copyUnion(t);
    tok = std::move(t.tok);
}

Token& Token::operator=(const Sales_data& rhs){
    if(tok == STR) sval.~string();
    if(tok == SAL)
        item = rhs;
    else
        new(&item) Sales_data(rhs);
    tok = SAL;
    return *this;
}
Token& Token::operator=(const int& i){
    if(tok == STR) sval.~string();
    if(tok == SAL) item.~Sales_data();
    ival = i;
    tok = INT;
    return *this;
}

int main(int argc, char const *argv[]) {
    Token s;
    Sales_data sal(5);
    s =  sal;
    int i = 5;
    std::cout << i << std::endl;
    return 0;
}
<|endoftext|>