<commit_before>//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "ClBackendContext.hpp"
#include "ClContextControl.hpp"

#include <armnn/Logging.hpp>
#include <armnn/utility/Assert.hpp>
#include <armnn/utility/PolymorphicDowncast.hpp>

#include <arm_compute/core/CL/OpenCL.h>
#include <arm_compute/core/CL/CLKernelLibrary.h>
#include <arm_compute/runtime/CL/CLScheduler.h>
#include <arm_compute/runtime/CL/CLTunerTypes.h>

namespace armnn
{

struct ClBackendContext::ClContextControlWrapper
{
    ClContextControlWrapper(arm_compute::CLTuner* tuner,
                            arm_compute::CLGEMMHeuristicsHandle* heuristicsHandle,
                            bool profilingEnabled)
        : m_ClContextControl(tuner, heuristicsHandle, profilingEnabled)
    {}

    bool Sync()
    {
        if (arm_compute::CLScheduler::get().context()() != NULL)
        {
            // Waits for all queued CL requests to finish before unloading the network they may be using.
            try
            {
                // Coverity fix: arm_compute::CLScheduler::sync() may throw an exception of type cl::Error.
                arm_compute::CLScheduler::get().sync();
            }
            catch (const cl::Error&)
            {
                ARMNN_LOG(warning) << "Runtime::UnloadNetwork(): an error occurred while waiting for "
                                      "the queued CL requests to finish";
                return false;
            }
        }

        return true;
    }

    void ClearClCache()
    {
        if (arm_compute::CLScheduler::get().context()() != NULL)
        {
            // There are no loaded networks left, so clear the CL cache to free up memory
            m_ClContextControl.ClearClCache();
        }
    }

    ClContextControl m_ClContextControl;
};

std::string LowerString(std::string value)
{
    std::transform(value.begin(), value.end(), value.begin(),
                   [](unsigned char c){ return std::tolower(c); });

    return value;
}

enum class TuningLevel
{
    None,
    Rapid,
    Normal,
    Exhaustive
};

TuningLevel ParseTuningLevel(const BackendOptions::Var& value, TuningLevel defaultValue)
{
    if (value.IsInt())
    {
        int v = value.AsInt();
        if (v > static_cast<int>(TuningLevel::Exhaustive) ||
            v < static_cast<int>(TuningLevel::None))
        {
            ARMNN_LOG(warning) << "Invalid GpuAcc tuning level ("<< v << ") selected. "
                                  "Using default(" << static_cast<int>(defaultValue) << ")";
        } else
        {
            return static_cast<TuningLevel>(v);
        }
    }
    return defaultValue;
}

bool ParseBoolean(const BackendOptions::Var& value, bool defaultValue)
{
    if (value.IsBool())
    {
        return value.AsBool();
    }
    return defaultValue;
}

std::string ParseFile(const BackendOptions::Var& value, std::string defaultValue)
{
    if (value.IsString())
    {
        return value.AsString();
    }
    return defaultValue;
}

void ConfigureTuner(arm_compute::CLTuner &tuner, TuningLevel level)
{
    tuner.set_tune_new_kernels(true); // Turn on tuning initially.

    switch (level)
    {
        case TuningLevel::Rapid:
            ARMNN_LOG(info) << "Gpu tuning is activated. TuningLevel: Rapid (1)";
            tuner.set_tuner_mode(arm_compute::CLTunerMode::RAPID);
            break;
        case TuningLevel::Normal:
            ARMNN_LOG(info) << "Gpu tuning is activated. TuningLevel: Normal (2)";
            tuner.set_tuner_mode(arm_compute::CLTunerMode::NORMAL);
            break;
        case TuningLevel::Exhaustive:
            ARMNN_LOG(info) << "Gpu tuning is activated. TuningLevel: Exhaustive (3)";
            tuner.set_tuner_mode(arm_compute::CLTunerMode::EXHAUSTIVE);
            break;
        case TuningLevel::None:
        default:
            tuner.set_tune_new_kernels(false); // Turn off tuning. Set to "use" only mode.
            break;
    }
}

ClBackendContext::ClBackendContext(const IRuntime::CreationOptions& options)
    : IBackendContext(options)
    , m_TuningFile()
{
    bool kernelProfiling = options.m_EnableGpuProfiling;

    arm_compute::CLTuner* tuner = nullptr;
    arm_compute::CLGEMMHeuristicsHandle* mlgoTuner = nullptr;
    bool useLegacyTunerAPI = options.m_GpuAccTunedParameters.get() != nullptr;
    if (useLegacyTunerAPI)
    {
        auto clTunerParams = PolymorphicDowncast<ClTunedParameters*>(
                                options.m_GpuAccTunedParameters.get());
        tuner = &clTunerParams->m_Tuner;

        if (tuner)
        {
            auto ConvertTuningLevel = [](IGpuAccTunedParameters::TuningLevel level,
                                         armnn::IGpuAccTunedParameters::Mode mode)
                {
                    if (mode == armnn::IGpuAccTunedParameters::Mode::UseTunedParameters)
                    {
                        return TuningLevel::None;
                    }

                    switch(level)
                    {
                        case IGpuAccTunedParameters::TuningLevel::Rapid:
                            return TuningLevel::Rapid;
                        case IGpuAccTunedParameters::TuningLevel::Normal:
                            return TuningLevel::Normal;
                        case IGpuAccTunedParameters::TuningLevel::Exhaustive:
                            return TuningLevel::Exhaustive;
                        default:
                        {
                            ARMNN_ASSERT_MSG(false, "Tuning level not recognised.");
                            return TuningLevel::None;
                        }
                    }
                };

            TuningLevel tuningLevel = ConvertTuningLevel(clTunerParams->m_TuningLevel, clTunerParams->m_Mode);
            ConfigureTuner(*tuner, tuningLevel);
        }
    }
    else //New backend options API
    {
        const TuningLevel defaultTuningLevel = TuningLevel::None;
        auto tuningLevel = defaultTuningLevel;

        ParseOptions(options.m_BackendOptions, "GpuAcc", [&](std::string name, const BackendOptions::Var& value)
            {
                if (name == "KernelProfilingEnabled")
                {
                    kernelProfiling |= ParseBoolean(value, false);
                } else if (name == "TuningFile")
                {
                    m_TuningFile = ParseFile(value, "");
                } else if (name == "TuningLevel")
                {
                    tuningLevel = ParseTuningLevel(value, defaultTuningLevel);
                }
                else if (name == "MLGOTuningFilePath")
                {
                    m_MLGOTuningFile = ParseFile(value, "");
                }
            });

        // Create the tuner, in tuning mode initially.
        m_Tuner = std::make_unique<arm_compute::CLTuner>(true);

        ConfigureTuner(*(m_Tuner.get()), tuningLevel);

        if (!m_TuningFile.empty() && tuningLevel == TuningLevel::None)
        {
            try
            {
                ARMNN_LOG(info) << "Loading Gpu tuning data from file: " << m_TuningFile;
                m_Tuner->load_from_file(m_TuningFile.c_str());
            }
            catch (const std::exception& e)
            {
                ARMNN_LOG(warning) << "Could not load GpuAcc tuner data file.";
            }
        }

        if (!m_MLGOTuningFile.empty())
        {
            try
            {
                ARMNN_LOG(info) << "Loading Gpu MLGO tuning data from file: " << m_TuningFile;
                if(m_MLGOTuner.reload_from_file(m_MLGOTuningFile.c_str()))
                {
                    mlgoTuner = &m_MLGOTuner;
                }
            }
            catch (const std::exception& e)
            {
                ARMNN_LOG(warning) << "Could not load GpuAcc MLGO tuner data file.";
            }
        }

        tuner = m_Tuner.get();
    }

    m_ClContextControlWrapper = std::make_unique<ClContextControlWrapper>(
            tuner,
            mlgoTuner,
            kernelProfiling
    );
}

bool ClBackendContext::BeforeLoadNetwork(NetworkId)
{
    return true;
}

bool ClBackendContext::AfterLoadNetwork(NetworkId networkId)
{
    {
        std::lock_guard<std::mutex> lockGuard(m_Mutex);
        m_NetworkIds.insert(networkId);
    }
    return true;
}

bool ClBackendContext::BeforeUnloadNetwork(NetworkId)
{
    return m_ClContextControlWrapper->Sync();
}

bool ClBackendContext::AfterUnloadNetwork(NetworkId networkId)
{
    bool clearCache = false;
    {
        std::lock_guard<std::mutex> lockGuard(m_Mutex);
        m_NetworkIds.erase(networkId);
        clearCache = m_NetworkIds.empty();
    }

    if (clearCache)
    {
        m_ClContextControlWrapper->ClearClCache();
    }

    return true;
}

bool ClBackendContext::AfterEnqueueWorkload(NetworkId)
{
    return m_ClContextControlWrapper->Sync();
}

ClBackendContext::~ClBackendContext()
{
    if (m_Tuner && !m_TuningFile.empty())
    {
        try
        {
            m_Tuner->save_to_file(m_TuningFile.c_str());
        }
        catch(const std::exception& e)
        {
            ARMNN_LOG(warning) << "Could not save GpuAcc tuner data to file " << m_TuningFile;
        }
    }
}

} // namespace armnn<commit_msg>Support incremental CL tuning<commit_after>//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "ClBackendContext.hpp"
#include "ClContextControl.hpp"

#include <armnn/Logging.hpp>
#include <armnn/utility/Assert.hpp>
#include <armnn/utility/PolymorphicDowncast.hpp>

#include <arm_compute/core/CL/OpenCL.h>
#include <arm_compute/core/CL/CLKernelLibrary.h>
#include <arm_compute/runtime/CL/CLScheduler.h>
#include <arm_compute/runtime/CL/CLTunerTypes.h>

namespace armnn
{

struct ClBackendContext::ClContextControlWrapper
{
    ClContextControlWrapper(arm_compute::CLTuner* tuner,
                            arm_compute::CLGEMMHeuristicsHandle* heuristicsHandle,
                            bool profilingEnabled)
        : m_ClContextControl(tuner, heuristicsHandle, profilingEnabled)
    {}

    bool Sync()
    {
        if (arm_compute::CLScheduler::get().context()() != NULL)
        {
            // Waits for all queued CL requests to finish before unloading the network they may be using.
            try
            {
                // Coverity fix: arm_compute::CLScheduler::sync() may throw an exception of type cl::Error.
                arm_compute::CLScheduler::get().sync();
            }
            catch (const cl::Error&)
            {
                ARMNN_LOG(warning) << "Runtime::UnloadNetwork(): an error occurred while waiting for "
                                      "the queued CL requests to finish";
                return false;
            }
        }

        return true;
    }

    void ClearClCache()
    {
        if (arm_compute::CLScheduler::get().context()() != NULL)
        {
            // There are no loaded networks left, so clear the CL cache to free up memory
            m_ClContextControl.ClearClCache();
        }
    }

    ClContextControl m_ClContextControl;
};

std::string LowerString(std::string value)
{
    std::transform(value.begin(), value.end(), value.begin(),
                   [](unsigned char c){ return std::tolower(c); });

    return value;
}

enum class TuningLevel
{
    None,
    Rapid,
    Normal,
    Exhaustive
};

TuningLevel ParseTuningLevel(const BackendOptions::Var& value, TuningLevel defaultValue)
{
    if (value.IsInt())
    {
        int v = value.AsInt();
        if (v > static_cast<int>(TuningLevel::Exhaustive) ||
            v < static_cast<int>(TuningLevel::None))
        {
            ARMNN_LOG(warning) << "Invalid GpuAcc tuning level ("<< v << ") selected. "
                                  "Using default(" << static_cast<int>(defaultValue) << ")";
        } else
        {
            return static_cast<TuningLevel>(v);
        }
    }
    return defaultValue;
}

bool ParseBoolean(const BackendOptions::Var& value, bool defaultValue)
{
    if (value.IsBool())
    {
        return value.AsBool();
    }
    return defaultValue;
}

std::string ParseFile(const BackendOptions::Var& value, std::string defaultValue)
{
    if (value.IsString())
    {
        return value.AsString();
    }
    return defaultValue;
}

void ConfigureTuner(arm_compute::CLTuner &tuner, TuningLevel level)
{
    tuner.set_tune_new_kernels(true); // Turn on tuning initially.

    switch (level)
    {
        case TuningLevel::Rapid:
            ARMNN_LOG(info) << "Gpu tuning is activated. TuningLevel: Rapid (1)";
            tuner.set_tuner_mode(arm_compute::CLTunerMode::RAPID);
            break;
        case TuningLevel::Normal:
            ARMNN_LOG(info) << "Gpu tuning is activated. TuningLevel: Normal (2)";
            tuner.set_tuner_mode(arm_compute::CLTunerMode::NORMAL);
            break;
        case TuningLevel::Exhaustive:
            ARMNN_LOG(info) << "Gpu tuning is activated. TuningLevel: Exhaustive (3)";
            tuner.set_tuner_mode(arm_compute::CLTunerMode::EXHAUSTIVE);
            break;
        case TuningLevel::None:
        default:
            tuner.set_tune_new_kernels(false); // Turn off tuning. Set to "use" only mode.
            break;
    }
}

ClBackendContext::ClBackendContext(const IRuntime::CreationOptions& options)
    : IBackendContext(options)
    , m_TuningFile()
{
    bool kernelProfiling = options.m_EnableGpuProfiling;

    arm_compute::CLTuner* tuner = nullptr;
    arm_compute::CLGEMMHeuristicsHandle* mlgoTuner = nullptr;
    bool useLegacyTunerAPI = options.m_GpuAccTunedParameters.get() != nullptr;
    if (useLegacyTunerAPI)
    {
        auto clTunerParams = PolymorphicDowncast<ClTunedParameters*>(
                                options.m_GpuAccTunedParameters.get());
        tuner = &clTunerParams->m_Tuner;

        if (tuner)
        {
            auto ConvertTuningLevel = [](IGpuAccTunedParameters::TuningLevel level,
                                         armnn::IGpuAccTunedParameters::Mode mode)
                {
                    if (mode == armnn::IGpuAccTunedParameters::Mode::UseTunedParameters)
                    {
                        return TuningLevel::None;
                    }

                    switch(level)
                    {
                        case IGpuAccTunedParameters::TuningLevel::Rapid:
                            return TuningLevel::Rapid;
                        case IGpuAccTunedParameters::TuningLevel::Normal:
                            return TuningLevel::Normal;
                        case IGpuAccTunedParameters::TuningLevel::Exhaustive:
                            return TuningLevel::Exhaustive;
                        default:
                        {
                            ARMNN_ASSERT_MSG(false, "Tuning level not recognised.");
                            return TuningLevel::None;
                        }
                    }
                };

            TuningLevel tuningLevel = ConvertTuningLevel(clTunerParams->m_TuningLevel, clTunerParams->m_Mode);
            ConfigureTuner(*tuner, tuningLevel);
        }
    }
    else //New backend options API
    {
        const TuningLevel defaultTuningLevel = TuningLevel::None;
        auto tuningLevel = defaultTuningLevel;

        ParseOptions(options.m_BackendOptions, "GpuAcc", [&](std::string name, const BackendOptions::Var& value)
            {
                if (name == "KernelProfilingEnabled")
                {
                    kernelProfiling |= ParseBoolean(value, false);
                } else if (name == "TuningFile")
                {
                    m_TuningFile = ParseFile(value, "");
                } else if (name == "TuningLevel")
                {
                    tuningLevel = ParseTuningLevel(value, defaultTuningLevel);
                }
                else if (name == "MLGOTuningFilePath")
                {
                    m_MLGOTuningFile = ParseFile(value, "");
                }
            });

        // Create the tuner, in tuning mode initially.
        m_Tuner = std::make_unique<arm_compute::CLTuner>(true);

        ConfigureTuner(*(m_Tuner.get()), tuningLevel);

        if (!m_TuningFile.empty())
        {
            try
            {
                ARMNN_LOG(info) << "Loading Gpu tuning data from file: " << m_TuningFile;
                m_Tuner->load_from_file(m_TuningFile.c_str());
            }
            catch (const std::exception& e)
            {
                // Warn if not tuning, otherwise tuning will generate new params
                if (tuningLevel == TuningLevel::None)
                {
                    ARMNN_LOG(warning) << "Could not load GpuAcc tuner data file.";
                }
            }
        }

        if (!m_MLGOTuningFile.empty())
        {
            try
            {
                ARMNN_LOG(info) << "Loading Gpu MLGO tuning data from file: " << m_TuningFile;
                if(m_MLGOTuner.reload_from_file(m_MLGOTuningFile.c_str()))
                {
                    mlgoTuner = &m_MLGOTuner;
                }
            }
            catch (const std::exception& e)
            {
                ARMNN_LOG(warning) << "Could not load GpuAcc MLGO tuner data file.";
            }
        }

        tuner = m_Tuner.get();
    }

    m_ClContextControlWrapper = std::make_unique<ClContextControlWrapper>(
            tuner,
            mlgoTuner,
            kernelProfiling
    );
}

bool ClBackendContext::BeforeLoadNetwork(NetworkId)
{
    return true;
}

bool ClBackendContext::AfterLoadNetwork(NetworkId networkId)
{
    {
        std::lock_guard<std::mutex> lockGuard(m_Mutex);
        m_NetworkIds.insert(networkId);
    }
    return true;
}

bool ClBackendContext::BeforeUnloadNetwork(NetworkId)
{
    return m_ClContextControlWrapper->Sync();
}

bool ClBackendContext::AfterUnloadNetwork(NetworkId networkId)
{
    bool clearCache = false;
    {
        std::lock_guard<std::mutex> lockGuard(m_Mutex);
        m_NetworkIds.erase(networkId);
        clearCache = m_NetworkIds.empty();
    }

    if (clearCache)
    {
        m_ClContextControlWrapper->ClearClCache();
    }

    return true;
}

bool ClBackendContext::AfterEnqueueWorkload(NetworkId)
{
    return m_ClContextControlWrapper->Sync();
}

ClBackendContext::~ClBackendContext()
{
    if (m_Tuner && !m_TuningFile.empty())
    {
        try
        {
            m_Tuner->save_to_file(m_TuningFile.c_str());
        }
        catch(const std::exception& e)
        {
            ARMNN_LOG(warning) << "Could not save GpuAcc tuner data to file " << m_TuningFile;
        }
    }
}

} // namespace armnn<|endoftext|>


<commit_before>// Copyright (c) 2018 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "blockrelay/blockrelay_common.h"
#include "net.h"
#include "random.h"
#include "requestManager.h"
#include "sync.h"
#include "util.h"

bool IsThinBlockEnabled();
bool IsGrapheneBlockEnabled();

// Update the counters for how many peers we have connected.
void ThinTypeRelay::AddThinTypePeers(CNode *pfrom)
{
    if (pfrom)
    {
        if (pfrom->nServices & NODE_XTHIN)
            nThinBlockPeers++;
        if (pfrom->nServices & NODE_GRAPHENE)
            nGraphenePeers++;
    }
}
void ThinTypeRelay::AddCompactBlockPeer(CNode *pfrom)
{
    if (pfrom && pfrom->fSupportsCompactBlocks)
        nCompactBlockPeers++;
}
void ThinTypeRelay::RemoveThinTypePeers(CNode *pfrom)
{
    if (pfrom)
    {
        if (pfrom->nServices & NODE_XTHIN)
            nThinBlockPeers--;
        if (pfrom->nServices & NODE_GRAPHENE)
            nGraphenePeers--;
        if (pfrom->fSupportsCompactBlocks)
            nCompactBlockPeers--;

        DbgAssert(nThinBlockPeers >= 0, nThinBlockPeers = 0);
        DbgAssert(nGraphenePeers >= 0, nGraphenePeers = 0);
        DbgAssert(nCompactBlockPeers >= 0, nCompactBlockPeers = 0);
    }
}

// Preferential Block Relay Timer:
// The purpose of the timer is to ensure that we more often download an XTHIN/GRAPHENE/CMPCT blocks
// rather than full blocks.  Once a block announcement arrives the timer is started.  If there are no
// peers that support one of the thin blocks types then timer continues until either an announcement
// arrives from a comaptible peer, or the timer expires. If the timer expires, then and only then we
// download a full block.
bool ThinTypeRelay::HasBlockRelayTimerExpired(const uint256 &hash)
{
    // Base time used to calculate the random timeout value.
    static uint64_t nTimeToWait = GetArg("-preferential-timer", DEFAULT_PREFERENTIAL_TIMER);
    if (nTimeToWait == 0)
        return true;

    LOCK(cs_blockrelaytimer);
    if (!mapBlockRelayTimer.count(hash))
    {
        // The timeout limit is a random number belonging to graphene-timer +/- 20%
        // This way a node connected to this one may download the block
        // before the other node and thus be able to serve the other with
        // a graphene block, rather than both nodes timing out and downloading
        // a thinblock instead. This can happen at the margins of the BU network
        // where we receive full blocks from peers that don't support graphene.
        //
        // To make the timeout random we adjust the start time of the timer forward
        // or backward by a random amount plus or minus 20% of preferential timer in milliseconds.
        FastRandomContext insecure_rand(false);
        uint64_t nStartInterval = nTimeToWait * 0.8;
        uint64_t nIntervalLen = 2 * (nTimeToWait * 0.2);
        int64_t nOffset = nTimeToWait - (nStartInterval + (insecure_rand.rand64() % nIntervalLen) + 1);
        mapBlockRelayTimer.emplace(hash, std::make_pair(GetTimeMillis() + nOffset, false));
        LOG(GRAPHENE, "Starting Preferential block relay timer (%d millis)\n", nTimeToWait + nOffset);
    }
    else
    {
        // Check that we have not exceeded time limit.
        // If we have then we want to return false so that we can
        // proceed to download a regular block instead.
        auto iter = mapBlockRelayTimer.find(hash);
        if (iter != mapBlockRelayTimer.end())
        {
            int64_t elapsed = GetTimeMillis() - iter->second.first;
            if (elapsed > (int64_t)nTimeToWait)
            {
                // Only print out the log entry once.  Because the graphene timer will be hit
                // many times when requesting a block we don't want to fill up the log file.
                if (!iter->second.second)
                {
                    iter->second.second = true;
                    LOG(GRAPHENE | THIN, "Preferential block relay timer exceeded\n");
                }
                return true;
            }
        }
    }
    return false;
}

bool ThinTypeRelay::IsBlockRelayTimerEnabled()
{
    // Only engage the timer if at least one thin type relay is active.
    if (!IsThinBlocksEnabled() && !IsGrapheneBlockEnabled())
        return false;

    // Under certain conditions the thin relay timer is not relevant.
    bool fHaveThinBlockPeers = false;
    bool fHaveGraphenePeers = false;
    if (nThinBlockPeers > 0)
        fHaveThinBlockPeers = true;
    if (nGraphenePeers > 0)
        fHaveGraphenePeers = true;

    if (!fHaveGraphenePeers && !fHaveThinBlockPeers)
        return false;
    else if (IsGrapheneBlockEnabled() && !fHaveGraphenePeers && !IsThinBlocksEnabled() && fHaveThinBlockPeers)
        return false;
    else if (!IsGrapheneBlockEnabled() && fHaveGraphenePeers && IsThinBlocksEnabled() && !fHaveThinBlockPeers)
        return false;

    return true;
}
// The timer is cleared as soon as we request a block or thinblock.
void ThinTypeRelay::ClearBlockRelayTimer(const uint256 &hash)
{
    LOCK(cs_blockrelaytimer);
    if (mapBlockRelayTimer.count(hash))
    {
        mapBlockRelayTimer.erase(hash);
        LOG(THIN | GRAPHENE, "Clearing Preferential BlockRelay timer\n");
    }
}

bool ThinTypeRelay::IsThinTypeBlockInFlight(CNode *pfrom, const std::string thinType)
{
    LOCK(cs_inflight);
    // first check that we are in bounds.
    if (mapThinTypeBlocksInFlight.size() >= MAX_THINTYPE_BLOCKS_IN_FLIGHT)
        return true;

    // check if this node already has this thinType of block in flight.
    std::pair<std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator,
        std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator>
        range = mapThinTypeBlocksInFlight.equal_range(pfrom->GetId());
    while (range.first != range.second)
    {
        if (range.first->second.thinType == thinType)
            return true;

        range.first++;
    }
    return false;
}

unsigned int ThinTypeRelay::TotalThinTypeBlocksInFlight()
{
    LOCK(cs_inflight);
    return mapThinTypeBlocksInFlight.size();
}

void ThinTypeRelay::ThinTypeBlockWasReceived(CNode *pfrom, const uint256 &hash)
{
    LOCK(cs_inflight);
    std::pair<std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator,
        std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator>
        range = mapThinTypeBlocksInFlight.equal_range(pfrom->GetId());
    while (range.first != range.second)
    {
        if (range.first->second.hash == hash)
            range.first->second.fReceived = true;

        range.first++;
    }
}

bool ThinTypeRelay::AddThinTypeBlockInFlight(CNode *pfrom, const uint256 &hash, const std::string thinType)
{
    LOCK(cs_inflight);
    if (IsThinTypeBlockInFlight(pfrom, thinType))
        return false;

    mapThinTypeBlocksInFlight.insert(
        std::pair<const NodeId, CThinTypeBlockInFlight>(pfrom->GetId(), {hash, GetTime(), false, thinType}));
    return true;
}

void ThinTypeRelay::ClearThinTypeBlockInFlight(CNode *pfrom, const uint256 &hash)
{
    LOCK(cs_inflight);
    std::pair<std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator,
        std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator>
        range = mapThinTypeBlocksInFlight.equal_range(pfrom->GetId());
    while (range.first != range.second)
    {
        if (range.first->second.hash == hash)
        {
            range.first = mapThinTypeBlocksInFlight.erase(range.first);
        }
        else
        {
            range.first++;
        }
    }
}

void ThinTypeRelay::CheckForThinTypeDownloadTimeout(CNode *pfrom)
{
    LOCK(cs_inflight);
    if (mapThinTypeBlocksInFlight.size() == 0)
        return;

    std::pair<std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator,
        std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator>
        range = mapThinTypeBlocksInFlight.equal_range(pfrom->GetId());
    while (range.first != range.second)
    {
        // Use a timeout of 6 times the retry inverval before disconnecting.  This way only a max of 6
        // re-requested thinblocks or graphene blocks could be in memory at any one time.
        if (!range.first->second.fReceived &&
            (GetTime() - range.first->second.nRequestTime) >
                (int)MAX_THINTYPE_BLOCKS_IN_FLIGHT * blkReqRetryInterval / 1000000)
        {
            if (!pfrom->fWhitelisted && Params().NetworkIDString() != "regtest")
            {
                LOG(THIN | GRAPHENE,
                    "ERROR: Disconnecting peer %s due to thinblock download timeout exceeded (%d secs)\n",
                    pfrom->GetLogName(), (GetTime() - range.first->second.nRequestTime));
                pfrom->fDisconnect = true;
                return;
            }
        }

        range.first++;
    }
}
<commit_msg>Minor text modification to thin timer.<commit_after>// Copyright (c) 2018 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "blockrelay/blockrelay_common.h"
#include "net.h"
#include "random.h"
#include "requestManager.h"
#include "sync.h"
#include "util.h"

bool IsThinBlockEnabled();
bool IsGrapheneBlockEnabled();

// Update the counters for how many peers we have connected.
void ThinTypeRelay::AddThinTypePeers(CNode *pfrom)
{
    if (pfrom)
    {
        if (pfrom->nServices & NODE_XTHIN)
            nThinBlockPeers++;
        if (pfrom->nServices & NODE_GRAPHENE)
            nGraphenePeers++;
    }
}
void ThinTypeRelay::AddCompactBlockPeer(CNode *pfrom)
{
    if (pfrom && pfrom->fSupportsCompactBlocks)
        nCompactBlockPeers++;
}
void ThinTypeRelay::RemoveThinTypePeers(CNode *pfrom)
{
    if (pfrom)
    {
        if (pfrom->nServices & NODE_XTHIN)
            nThinBlockPeers--;
        if (pfrom->nServices & NODE_GRAPHENE)
            nGraphenePeers--;
        if (pfrom->fSupportsCompactBlocks)
            nCompactBlockPeers--;

        DbgAssert(nThinBlockPeers >= 0, nThinBlockPeers = 0);
        DbgAssert(nGraphenePeers >= 0, nGraphenePeers = 0);
        DbgAssert(nCompactBlockPeers >= 0, nCompactBlockPeers = 0);
    }
}

// Preferential Block Relay Timer:
// The purpose of the timer is to ensure that we more often download an XTHIN/GRAPHENE/CMPCT blocks
// rather than full blocks.  Once a block announcement arrives the timer is started.  If there are no
// peers that support one of the thin blocks types then timer continues until either an announcement
// arrives from a comaptible peer, or the timer expires. If the timer expires, then and only then we
// download a full block.
bool ThinTypeRelay::HasBlockRelayTimerExpired(const uint256 &hash)
{
    // Base time used to calculate the random timeout value.
    static uint64_t nTimeToWait = GetArg("-preferential-timer", DEFAULT_PREFERENTIAL_TIMER);
    if (nTimeToWait == 0)
        return true;

    LOCK(cs_blockrelaytimer);
    if (!mapBlockRelayTimer.count(hash))
    {
        // The timeout limit is a random number +/- 20%.
        // This way a node connected to this one may download the block
        // before the other node and thus be able to serve the other with
        // a graphene block, rather than both nodes timing out and downloading
        // a thinblock instead. This can happen at the margins of the BU network
        // where we receive full blocks from peers that don't support graphene.
        //
        // To make the timeout random we adjust the start time of the timer forward
        // or backward by a random amount plus or minus 20% of preferential timer in milliseconds.
        FastRandomContext insecure_rand(false);
        uint64_t nStartInterval = nTimeToWait * 0.8;
        uint64_t nIntervalLen = 2 * (nTimeToWait * 0.2);
        int64_t nOffset = nTimeToWait - (nStartInterval + (insecure_rand.rand64() % nIntervalLen) + 1);
        mapBlockRelayTimer.emplace(hash, std::make_pair(GetTimeMillis() + nOffset, false));
        LOG(GRAPHENE, "Starting Preferential block relay timer (%d millis)\n", nTimeToWait + nOffset);
    }
    else
    {
        // Check that we have not exceeded time limit.
        // If we have then we want to return false so that we can
        // proceed to download a regular block instead.
        auto iter = mapBlockRelayTimer.find(hash);
        if (iter != mapBlockRelayTimer.end())
        {
            int64_t elapsed = GetTimeMillis() - iter->second.first;
            if (elapsed > (int64_t)nTimeToWait)
            {
                // Only print out the log entry once.  Because the thinblock timer will be hit
                // many times when requesting a block we don't want to fill up the log file.
                if (!iter->second.second)
                {
                    iter->second.second = true;
                    LOG(THIN | GRAPHENE,
                        "Preferential BlockRelay timer exceeded - downloading regular block instead\n");
                }
                return true;
            }
        }
    }
    return false;
}

bool ThinTypeRelay::IsBlockRelayTimerEnabled()
{
    // Only engage the timer if at least one thin type relay is active.
    if (!IsThinBlocksEnabled() && !IsGrapheneBlockEnabled())
        return false;

    // Under certain conditions the thin relay timer is not relevant.
    bool fHaveThinBlockPeers = false;
    bool fHaveGraphenePeers = false;
    if (nThinBlockPeers > 0)
        fHaveThinBlockPeers = true;
    if (nGraphenePeers > 0)
        fHaveGraphenePeers = true;

    if (!fHaveGraphenePeers && !fHaveThinBlockPeers)
        return false;
    else if (IsGrapheneBlockEnabled() && !fHaveGraphenePeers && !IsThinBlocksEnabled() && fHaveThinBlockPeers)
        return false;
    else if (!IsGrapheneBlockEnabled() && fHaveGraphenePeers && IsThinBlocksEnabled() && !fHaveThinBlockPeers)
        return false;

    return true;
}
// The timer is cleared as soon as we request a block or thinblock.
void ThinTypeRelay::ClearBlockRelayTimer(const uint256 &hash)
{
    LOCK(cs_blockrelaytimer);
    if (mapBlockRelayTimer.count(hash))
    {
        mapBlockRelayTimer.erase(hash);
        LOG(THIN | GRAPHENE, "Clearing Preferential BlockRelay timer\n");
    }
}

bool ThinTypeRelay::IsThinTypeBlockInFlight(CNode *pfrom, const std::string thinType)
{
    LOCK(cs_inflight);
    // first check that we are in bounds.
    if (mapThinTypeBlocksInFlight.size() >= MAX_THINTYPE_BLOCKS_IN_FLIGHT)
        return true;

    // check if this node already has this thinType of block in flight.
    std::pair<std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator,
        std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator>
        range = mapThinTypeBlocksInFlight.equal_range(pfrom->GetId());
    while (range.first != range.second)
    {
        if (range.first->second.thinType == thinType)
            return true;

        range.first++;
    }
    return false;
}

unsigned int ThinTypeRelay::TotalThinTypeBlocksInFlight()
{
    LOCK(cs_inflight);
    return mapThinTypeBlocksInFlight.size();
}

void ThinTypeRelay::ThinTypeBlockWasReceived(CNode *pfrom, const uint256 &hash)
{
    LOCK(cs_inflight);
    std::pair<std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator,
        std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator>
        range = mapThinTypeBlocksInFlight.equal_range(pfrom->GetId());
    while (range.first != range.second)
    {
        if (range.first->second.hash == hash)
            range.first->second.fReceived = true;

        range.first++;
    }
}

bool ThinTypeRelay::AddThinTypeBlockInFlight(CNode *pfrom, const uint256 &hash, const std::string thinType)
{
    LOCK(cs_inflight);
    if (IsThinTypeBlockInFlight(pfrom, thinType))
        return false;

    mapThinTypeBlocksInFlight.insert(
        std::pair<const NodeId, CThinTypeBlockInFlight>(pfrom->GetId(), {hash, GetTime(), false, thinType}));
    return true;
}

void ThinTypeRelay::ClearThinTypeBlockInFlight(CNode *pfrom, const uint256 &hash)
{
    LOCK(cs_inflight);
    std::pair<std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator,
        std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator>
        range = mapThinTypeBlocksInFlight.equal_range(pfrom->GetId());
    while (range.first != range.second)
    {
        if (range.first->second.hash == hash)
        {
            range.first = mapThinTypeBlocksInFlight.erase(range.first);
        }
        else
        {
            range.first++;
        }
    }
}

void ThinTypeRelay::CheckForThinTypeDownloadTimeout(CNode *pfrom)
{
    LOCK(cs_inflight);
    if (mapThinTypeBlocksInFlight.size() == 0)
        return;

    std::pair<std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator,
        std::multimap<const NodeId, CThinTypeBlockInFlight>::iterator>
        range = mapThinTypeBlocksInFlight.equal_range(pfrom->GetId());
    while (range.first != range.second)
    {
        // Use a timeout of 6 times the retry inverval before disconnecting.  This way only a max of 6
        // re-requested thinblocks or graphene blocks could be in memory at any one time.
        if (!range.first->second.fReceived &&
            (GetTime() - range.first->second.nRequestTime) >
                (int)MAX_THINTYPE_BLOCKS_IN_FLIGHT * blkReqRetryInterval / 1000000)
        {
            if (!pfrom->fWhitelisted && Params().NetworkIDString() != "regtest")
            {
                LOG(THIN | GRAPHENE,
                    "ERROR: Disconnecting peer %s due to thinblock download timeout exceeded (%d secs)\n",
                    pfrom->GetLogName(), (GetTime() - range.first->second.nRequestTime));
                pfrom->fDisconnect = true;
                return;
            }
        }

        range.first++;
    }
}
<|endoftext|>


<commit_before>#include "chrono_matlab/ChMatlabEngine.h"

using namespace chrono;
using namespace std;

ChMatlabEngine::ChMatlabEngine() {
#ifdef __APPLE__
    if (!(ep = matlabengine::engOpen("matlab -automation -nosplash \0"))) {
        throw ChException("Can't start MATLAB engine");
    }
#else
    if (!(ep = matlabengine::engOpen("-automation \0"))) {
        throw ChException("Can't start MATLAB engine");
    }
#endif
}

ChMatlabEngine::~ChMatlabEngine() {
    if (ep)
        matlabengine::engClose(ep);
    ep = 0;
}
/// Return pointer to internal Matlab engine (avoid using it directly,
/// if you can use other functions of this class that 'wrap' it.)
matlabengine::Engine* ChMatlabEngine::GetEngine() {
    return ep;
}

/// Evaluate a Matlab instruction (as a string). If error happens while executing, returns false.
bool ChMatlabEngine::Eval(string mstring) {
    if (matlabengine::engEvalString(ep, mstring.c_str()) == 0)
        return true;
    else
        return false;
}

/// Set visibility of GUI matlab window.
bool ChMatlabEngine::SetVisible(bool mvis) {
    if (matlabengine::engSetVisible(ep, mvis) == 0)
        return true;
    else
        return false;
}

/// Put a matrix in Matlab environment, specifying its name as variable.
/// If a variable with the same name already exist, it is overwritten.
bool ChMatlabEngine::PutVariable(const ChMatrix<double>& mmatr, string varname) {
    ChMatrixDynamic<> transfer;  // elements in Matlab are column-major
    transfer.CopyFromMatrixT(mmatr);

    matlabengine::mxArray* T = NULL;
    T = matlabengine::mxCreateDoubleMatrix(mmatr.GetRows(), mmatr.GetColumns(), matlabengine::mxREAL);
    memcpy((char*)mxGetPr(T), (char*)transfer.GetAddress(), mmatr.GetRows() * mmatr.GetColumns() * sizeof(double));
    matlabengine::engPutVariable(ep, varname.c_str(), T);
    matlabengine::mxDestroyArray(T);
    return true;
}

/// Put a sparse matrix in Matlab environment, specifying its name as variable.
/// If a variable with the same name already exist, it is overwritten.
bool ChMatlabEngine::PutSparseMatrix(const ChLinkedListMatrix& mmatr, string varname) {
    int nels = 0;
    for (int ii = 0; ii < mmatr.GetRows(); ii++)
        for (int jj = 0; jj < mmatr.GetColumns(); jj++) {
            double elVal = ((ChLinkedListMatrix&)mmatr).GetElement(ii, jj);
            if (elVal ||
                (ii + 1 == ((ChLinkedListMatrix&)mmatr).GetRows() && jj + 1 == ((ChLinkedListMatrix&)mmatr).GetColumns()))
                ++nels;
        }

    ChMatrixDynamic<> transfer(nels, 3);

    int eln = 0;
    for (int ii = 0; ii < mmatr.GetRows(); ii++)
        for (int jj = 0; jj < mmatr.GetColumns(); jj++) {
            double elVal = ((ChLinkedListMatrix&)mmatr).GetElement(ii, jj);
            if (elVal ||
                (ii + 1 == ((ChLinkedListMatrix&)mmatr).GetRows() && jj + 1 == ((ChLinkedListMatrix&)mmatr).GetColumns())) {
                transfer(eln, 0) = ii + 1;
                transfer(eln, 1) = jj + 1;
                transfer(eln, 2) = elVal;
                ++eln;
            }
        }

    this->PutVariable(transfer, varname.c_str());

    char buff[100];
    sprintf(buff, "%s=spconvert(%s)", varname.c_str(), varname.c_str());
    this->Eval(buff);

    return true;
}

/// Fetch a matrix from Matlab environment, specifying its name as variable.
/// The used matrix must be of ChMatrixDynamic<double> type because
/// it might undergo resizing.
bool ChMatlabEngine::GetVariable(ChMatrixDynamic<double>& mmatr, string varname) {
    ChMatrixDynamic<> transfer;  // elements in Matlab are column-major

    matlabengine::mxArray* T = matlabengine::engGetVariable(ep, varname.c_str());
    if (T) {
        matlabengine::mwSize ndi = mxGetNumberOfDimensions(T);
        if (ndi != 2) {
            matlabengine::mxDestroyArray(T);
            return false;
        }
        const matlabengine::mwSize* siz = mxGetDimensions(T);
        transfer.Resize((int)siz[1], (int)siz[0]);
        memcpy((char*)transfer.GetAddress(), (char*)mxGetPr(T),
               transfer.GetRows() * transfer.GetColumns() * sizeof(double));
        matlabengine::mxDestroyArray(T);

        mmatr.CopyFromMatrixT(transfer);

        return true;
    }
    matlabengine::mxDestroyArray(T);
    return false;
}
<commit_msg>Fix MATLAB module compatibility with ChLinkedListMatrix API (since GetColumns() etc. were renamed GetNumColumns() etc.)<commit_after>#include "chrono_matlab/ChMatlabEngine.h"

using namespace chrono;
using namespace std;

ChMatlabEngine::ChMatlabEngine() {
#ifdef __APPLE__
    if (!(ep = matlabengine::engOpen("matlab -automation -nosplash \0"))) {
        throw ChException("Can't start MATLAB engine");
    }
#else
    if (!(ep = matlabengine::engOpen("-automation \0"))) {
        throw ChException("Can't start MATLAB engine");
    }
#endif
}

ChMatlabEngine::~ChMatlabEngine() {
    if (ep)
        matlabengine::engClose(ep);
    ep = 0;
}
/// Return pointer to internal Matlab engine (avoid using it directly,
/// if you can use other functions of this class that 'wrap' it.)
matlabengine::Engine* ChMatlabEngine::GetEngine() {
    return ep;
}

/// Evaluate a Matlab instruction (as a string). If error happens while executing, returns false.
bool ChMatlabEngine::Eval(string mstring) {
    if (matlabengine::engEvalString(ep, mstring.c_str()) == 0)
        return true;
    else
        return false;
}

/// Set visibility of GUI matlab window.
bool ChMatlabEngine::SetVisible(bool mvis) {
    if (matlabengine::engSetVisible(ep, mvis) == 0)
        return true;
    else
        return false;
}

/// Put a matrix in Matlab environment, specifying its name as variable.
/// If a variable with the same name already exist, it is overwritten.
bool ChMatlabEngine::PutVariable(const ChMatrix<double>& mmatr, string varname) {
    ChMatrixDynamic<> transfer;  // elements in Matlab are column-major
    transfer.CopyFromMatrixT(mmatr);

    matlabengine::mxArray* T = NULL;
    T = matlabengine::mxCreateDoubleMatrix(mmatr.GetRows(), mmatr.GetColumns(), matlabengine::mxREAL);
    memcpy((char*)mxGetPr(T), (char*)transfer.GetAddress(), mmatr.GetRows() * mmatr.GetColumns() * sizeof(double));
    matlabengine::engPutVariable(ep, varname.c_str(), T);
    matlabengine::mxDestroyArray(T);
    return true;
}

/// Put a sparse matrix in Matlab environment, specifying its name as variable.
/// If a variable with the same name already exist, it is overwritten.
bool ChMatlabEngine::PutSparseMatrix(const ChLinkedListMatrix& mmatr, string varname) {
    int nels = 0;
    for (int ii = 0; ii < mmatr.GetNumRows(); ii++)
        for (int jj = 0; jj < mmatr.GetNumColumns(); jj++) {
            double elVal = ((ChLinkedListMatrix&)mmatr).GetElement(ii, jj);
            if (elVal ||
                (ii + 1 == ((ChLinkedListMatrix&)mmatr).GetNumRows() && jj + 1 == ((ChLinkedListMatrix&)mmatr).GetNumColumns()))
                ++nels;
        }

    ChMatrixDynamic<> transfer(nels, 3);

    int eln = 0;
    for (int ii = 0; ii < mmatr.GetNumRows(); ii++)
        for (int jj = 0; jj < mmatr.GetNumColumns(); jj++) {
            double elVal = ((ChLinkedListMatrix&)mmatr).GetElement(ii, jj);
            if (elVal ||
                (ii + 1 == ((ChLinkedListMatrix&)mmatr).GetNumRows() && jj + 1 == ((ChLinkedListMatrix&)mmatr).GetNumColumns())) {
                transfer(eln, 0) = ii + 1;
                transfer(eln, 1) = jj + 1;
                transfer(eln, 2) = elVal;
                ++eln;
            }
        }

    this->PutVariable(transfer, varname.c_str());

    char buff[100];
    sprintf(buff, "%s=spconvert(%s)", varname.c_str(), varname.c_str());
    this->Eval(buff);

    return true;
}

/// Fetch a matrix from Matlab environment, specifying its name as variable.
/// The used matrix must be of ChMatrixDynamic<double> type because
/// it might undergo resizing.
bool ChMatlabEngine::GetVariable(ChMatrixDynamic<double>& mmatr, string varname) {
    ChMatrixDynamic<> transfer;  // elements in Matlab are column-major

    matlabengine::mxArray* T = matlabengine::engGetVariable(ep, varname.c_str());
    if (T) {
        matlabengine::mwSize ndi = mxGetNumberOfDimensions(T);
        if (ndi != 2) {
            matlabengine::mxDestroyArray(T);
            return false;
        }
        const matlabengine::mwSize* siz = mxGetDimensions(T);
        transfer.Resize((int)siz[1], (int)siz[0]);
        memcpy((char*)transfer.GetAddress(), (char*)mxGetPr(T),
               transfer.GetRows() * transfer.GetColumns() * sizeof(double));
        matlabengine::mxDestroyArray(T);

        mmatr.CopyFromMatrixT(transfer);

        return true;
    }
    matlabengine::mxDestroyArray(T);
    return false;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkHardConnectedComponentImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkHardConnectedComponentImageFilter.h"
#include "itkImageRegionIterator.h"

const int HEIGHT = 20;
const int WIDTH = 20;

main()
{
  typedef itk::Image<bool,2> InputImageType;
  typedef itk::Image<unsigned short,2> OutputImageType;
  typedef InputImageType::IndexType IndexType;

  itk::HardConnectedComponentImageFilter<InputImageType, OutputImageType>::Pointer
        filter = itk::HardConnectedComponentImageFilter<InputImageType, OutputImageType>::New();
  InputImageType::Pointer inputimg = InputImageType::New();
  IndexType index = InputImageType::IndexType::ZeroIndex;
  InputImageType::RegionType region;

  itk::Size<2> sz;
  sz[0] = WIDTH;
  sz[1] = HEIGHT;

  region.SetSize(sz);
  region.SetIndex(index);

  inputimg->SetLargestPossibleRegion( region );
  inputimg->SetBufferedRegion( region );
  inputimg->SetRequestedRegion( region );
  inputimg->Allocate();

  int row, col;
  IndexType myIndex;
  for(row = 0;row<20;row++)
    for(col = 0;col < 20;col++)
      {
        myIndex[1] = row;
        myIndex[0] = col;
        inputimg->SetPixel(myIndex,false);
      }
  for(row = 0;row<15;row++)
    for(col = 0;col<20;col++)
      {
        myIndex[1] = row;
        myIndex[0] = col;
        inputimg->SetPixel(myIndex,true);
      }

  for(row = 0;row<10;row++)
    for(col = 5;col<15;col++)
      {
        myIndex[1] = row;
        myIndex[0] = col;
        inputimg->SetPixel(myIndex,false);
      }

  for(row = 0;row<7;row++)
    for(col = 7;col<12;col++)
      {
        myIndex[1] = row;
        myIndex[0] = col;
        inputimg->SetPixel(myIndex,true);
      }

  //InputImageType::IndexType Seed = {10,2};

  filter->SetInput(inputimg);
  //filter->SetObjectSeed(Seed);
  filter->Update();

  typedef itk::ImageRegionIterator<OutputImageType> outputIterator;
  outputIterator ot = outputIterator(filter->GetOutput(), region);

  ot.GoToBegin();
  for(int i = 0;i < HEIGHT*WIDTH; i++)
  {
    if((i%WIDTH) == 0)
      std::cout<<std::endl;
      std::cout<<ot.Get();
      ++ot;
  }

  std::cout<<std::endl;

  return 0;
}
<commit_msg>ERR: new test format.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkHardConnectedComponentImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkHardConnectedComponentImageFilter.h"
#include "itkImageRegionIterator.h"

const int HEIGHT = 20;
const int WIDTH = 20;

int itkHardConnectedComponentImageFilterTest(int, char**)
{
  typedef itk::Image<bool,2> InputImageType;
  typedef itk::Image<unsigned short,2> OutputImageType;
  typedef InputImageType::IndexType IndexType;

  itk::HardConnectedComponentImageFilter<InputImageType, OutputImageType>::Pointer
        filter = itk::HardConnectedComponentImageFilter<InputImageType, OutputImageType>::New();
  InputImageType::Pointer inputimg = InputImageType::New();
  IndexType index = InputImageType::IndexType::ZeroIndex;
  InputImageType::RegionType region;

  itk::Size<2> sz;
  sz[0] = WIDTH;
  sz[1] = HEIGHT;

  region.SetSize(sz);
  region.SetIndex(index);

  inputimg->SetLargestPossibleRegion( region );
  inputimg->SetBufferedRegion( region );
  inputimg->SetRequestedRegion( region );
  inputimg->Allocate();

  int row, col;
  IndexType myIndex;
  for(row = 0;row<20;row++)
    for(col = 0;col < 20;col++)
      {
        myIndex[1] = row;
        myIndex[0] = col;
        inputimg->SetPixel(myIndex,false);
      }
  for(row = 0;row<15;row++)
    for(col = 0;col<20;col++)
      {
        myIndex[1] = row;
        myIndex[0] = col;
        inputimg->SetPixel(myIndex,true);
      }

  for(row = 0;row<10;row++)
    for(col = 5;col<15;col++)
      {
        myIndex[1] = row;
        myIndex[0] = col;
        inputimg->SetPixel(myIndex,false);
      }

  for(row = 0;row<7;row++)
    for(col = 7;col<12;col++)
      {
        myIndex[1] = row;
        myIndex[0] = col;
        inputimg->SetPixel(myIndex,true);
      }

  //InputImageType::IndexType Seed = {10,2};

  filter->SetInput(inputimg);
  //filter->SetObjectSeed(Seed);
  filter->Update();

  typedef itk::ImageRegionIterator<OutputImageType> outputIterator;
  outputIterator ot = outputIterator(filter->GetOutput(), region);

  ot.GoToBegin();
  for(int i = 0;i < HEIGHT*WIDTH; i++)
  {
    if((i%WIDTH) == 0)
      std::cout<<std::endl;
      std::cout<<ot.Get();
      ++ot;
  }

  std::cout<<std::endl;

  return 0;
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>

#include "otbLabelizeConnectedThresholdImageFilter.h"
#include "otbImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "otbMultiplyByScalarImageFilter.h"

int otbLabelizeConnectedThresholdImageFilter( int argc, char * argv[] )
{
  // Arguments
  char* inputImageName = argv[1];
  char* outputImageName = argv[2];

  typedef unsigned char InputPixelType;
  typedef unsigned char OutputPixelType;
  const unsigned int Dimension = 2;

  typedef otb::Image< InputPixelType, Dimension > InputImageType;
  typedef otb::Image< OutputPixelType, Dimension > OutputImageType;

  InputPixelType lowerThreshold( (InputPixelType)::atoi(argv[3]) );
  InputPixelType upperThreshold( (InputPixelType)::atoi(argv[4]) );
  InputPixelType deltaLower( (InputPixelType)::atoi(argv[5]) );
  InputPixelType deltaUpper( (InputPixelType)::atoi(argv[6]) );

  // Reader
  typedef otb::ImageFileReader<InputImageType> ReaderType;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(inputImageName);

  // Writer
  typedef otb::ImageFileWriter<OutputImageType> WriterType;
  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(outputImageName);

  // Labelize filter
  typedef otb::LabelizeConnectedThresholdImageFilter<InputImageType, OutputImageType> LabelizeFilterType;
  LabelizeFilterType::Pointer filter = LabelizeFilterType::New();

  filter->SetLowerThreshold(lowerThreshold);
  filter->SetUpperThreshold(upperThreshold);
  filter->SetLowerThresholdDelta(deltaLower);
  filter->SetUpperThresholdDelta(deltaUpper);

  filter->SetInput(reader->GetOutput());
  writer->SetInput(filter->GetOutput());
  writer->Update();

  return EXIT_SUCCESS;
}
<commit_msg>*suppression include<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>

#include "otbLabelizeConnectedThresholdImageFilter.h"
#include "otbImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"

int otbLabelizeConnectedThresholdImageFilter( int argc, char * argv[] )
{
  // Arguments
  char* inputImageName = argv[1];
  char* outputImageName = argv[2];

  typedef unsigned char InputPixelType;
  typedef unsigned char OutputPixelType;
  const unsigned int Dimension = 2;

  typedef otb::Image< InputPixelType, Dimension > InputImageType;
  typedef otb::Image< OutputPixelType, Dimension > OutputImageType;

  InputPixelType lowerThreshold( (InputPixelType)::atoi(argv[3]) );
  InputPixelType upperThreshold( (InputPixelType)::atoi(argv[4]) );
  InputPixelType deltaLower( (InputPixelType)::atoi(argv[5]) );
  InputPixelType deltaUpper( (InputPixelType)::atoi(argv[6]) );

  // Reader
  typedef otb::ImageFileReader<InputImageType> ReaderType;
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(inputImageName);

  // Writer
  typedef otb::ImageFileWriter<OutputImageType> WriterType;
  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(outputImageName);

  // Labelize filter
  typedef otb::LabelizeConnectedThresholdImageFilter<InputImageType, OutputImageType> LabelizeFilterType;
  LabelizeFilterType::Pointer filter = LabelizeFilterType::New();

  filter->SetLowerThreshold(lowerThreshold);
  filter->SetUpperThreshold(upperThreshold);
  filter->SetLowerThresholdDelta(deltaLower);
  filter->SetUpperThresholdDelta(deltaUpper);

  filter->SetInput(reader->GetOutput());
  writer->SetInput(filter->GetOutput());
  writer->Update();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: PolarCoordinateSystem.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: vg $ $Date: 2007-05-22 18:40:20 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"
#include "PolarCoordinateSystem.hxx"
#include "macros.hxx"
#include "servicenames_coosystems.hxx"

using namespace ::com::sun::star;

using ::com::sun::star::uno::RuntimeException;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::rtl::OUString;

namespace
{

static const ::rtl::OUString lcl_aServiceNamePolar2d(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.PolarCoordinateSystem2d" ));
static const ::rtl::OUString lcl_aServiceNamePolar3d(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.PolarCoordinateSystem3d" ));

static const ::rtl::OUString lcl_aImplementationNamePolar2d(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.PolarCoordinateSystem2d" ));
static const ::rtl::OUString lcl_aImplementationNamePolar3d(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.PolarCoordinateSystem3d" ));
}

namespace chart
{

// explicit
PolarCoordinateSystem::PolarCoordinateSystem(
    const uno::Reference< uno::XComponentContext > & xContext,
    sal_Int32 nDimensionCount /* = 2 */,
    sal_Bool bSwapXAndYAxis /* = sal_False */ ) :
        BaseCoordinateSystem( xContext, nDimensionCount, bSwapXAndYAxis )
{}

PolarCoordinateSystem::PolarCoordinateSystem(
    const PolarCoordinateSystem & rSource ) :
        BaseCoordinateSystem( rSource )
{}

PolarCoordinateSystem::~PolarCoordinateSystem()
{}

// ____ XCoordinateSystem ____
::rtl::OUString SAL_CALL PolarCoordinateSystem::getCoordinateSystemType()
    throw (RuntimeException)
{
    return CHART2_COOSYSTEM_POLAR_SERVICE_NAME;
}

::rtl::OUString SAL_CALL PolarCoordinateSystem::getViewServiceName()
    throw (RuntimeException)
{
    return CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME;
}

// ____ XCloneable ____
uno::Reference< util::XCloneable > SAL_CALL PolarCoordinateSystem::createClone()
    throw (RuntimeException)
{
    return Reference< util::XCloneable >( new PolarCoordinateSystem( *this ));
}

// ____ XServiceInfo ____
Sequence< OUString > PolarCoordinateSystem::getSupportedServiceNames_Static()
{
    Sequence< OUString > aServices( 1 );
    aServices[ 0 ] = CHART2_COOSYSTEM_POLAR_SERVICE_NAME;
    return aServices;
}

// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL( PolarCoordinateSystem,
                             C2U( "com.sun.star.comp.chart.PolarCoordinateSystem" ))

// =================================
// ==== PolarCoordinateSystem2d ====
// =================================

PolarCoordinateSystem2d::PolarCoordinateSystem2d(
    const uno::Reference< uno::XComponentContext > & xContext ) :
        PolarCoordinateSystem( xContext, 2, sal_False )
{}

PolarCoordinateSystem2d::~PolarCoordinateSystem2d()
{}

// ____ XServiceInfo ____
Sequence< OUString > PolarCoordinateSystem2d::getSupportedServiceNames_Static()
{
    Sequence< OUString > aServices( 2 );
    aServices[ 0 ] = CHART2_COOSYSTEM_POLAR_SERVICE_NAME;
    aServices[ 1 ] = lcl_aServiceNamePolar2d;
    return aServices;
}

// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL( PolarCoordinateSystem2d, lcl_aImplementationNamePolar2d )

// =================================
// ==== PolarCoordinateSystem3d ====
// =================================

PolarCoordinateSystem3d::PolarCoordinateSystem3d(
    const uno::Reference< uno::XComponentContext > & xContext ) :
        PolarCoordinateSystem( xContext, 3, sal_False )
{}

PolarCoordinateSystem3d::~PolarCoordinateSystem3d()
{}

// ____ XServiceInfo ____
Sequence< OUString > PolarCoordinateSystem3d::getSupportedServiceNames_Static()
{
    Sequence< OUString > aServices( 2 );
    aServices[ 0 ] = CHART2_COOSYSTEM_POLAR_SERVICE_NAME;
    aServices[ 1 ] = lcl_aServiceNamePolar3d;
    return aServices;
}

// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL( PolarCoordinateSystem3d, lcl_aImplementationNamePolar3d )

}  // namespace chart
<commit_msg>INTEGRATION: CWS changefileheader (1.6.126); FILE MERGED 2008/03/28 16:44:09 rt 1.6.126.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: PolarCoordinateSystem.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"
#include "PolarCoordinateSystem.hxx"
#include "macros.hxx"
#include "servicenames_coosystems.hxx"

using namespace ::com::sun::star;

using ::com::sun::star::uno::RuntimeException;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Sequence;
using ::rtl::OUString;

namespace
{

static const ::rtl::OUString lcl_aServiceNamePolar2d(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.PolarCoordinateSystem2d" ));
static const ::rtl::OUString lcl_aServiceNamePolar3d(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.PolarCoordinateSystem3d" ));

static const ::rtl::OUString lcl_aImplementationNamePolar2d(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.PolarCoordinateSystem2d" ));
static const ::rtl::OUString lcl_aImplementationNamePolar3d(
    RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.PolarCoordinateSystem3d" ));
}

namespace chart
{

// explicit
PolarCoordinateSystem::PolarCoordinateSystem(
    const uno::Reference< uno::XComponentContext > & xContext,
    sal_Int32 nDimensionCount /* = 2 */,
    sal_Bool bSwapXAndYAxis /* = sal_False */ ) :
        BaseCoordinateSystem( xContext, nDimensionCount, bSwapXAndYAxis )
{}

PolarCoordinateSystem::PolarCoordinateSystem(
    const PolarCoordinateSystem & rSource ) :
        BaseCoordinateSystem( rSource )
{}

PolarCoordinateSystem::~PolarCoordinateSystem()
{}

// ____ XCoordinateSystem ____
::rtl::OUString SAL_CALL PolarCoordinateSystem::getCoordinateSystemType()
    throw (RuntimeException)
{
    return CHART2_COOSYSTEM_POLAR_SERVICE_NAME;
}

::rtl::OUString SAL_CALL PolarCoordinateSystem::getViewServiceName()
    throw (RuntimeException)
{
    return CHART2_COOSYSTEM_POLAR_VIEW_SERVICE_NAME;
}

// ____ XCloneable ____
uno::Reference< util::XCloneable > SAL_CALL PolarCoordinateSystem::createClone()
    throw (RuntimeException)
{
    return Reference< util::XCloneable >( new PolarCoordinateSystem( *this ));
}

// ____ XServiceInfo ____
Sequence< OUString > PolarCoordinateSystem::getSupportedServiceNames_Static()
{
    Sequence< OUString > aServices( 1 );
    aServices[ 0 ] = CHART2_COOSYSTEM_POLAR_SERVICE_NAME;
    return aServices;
}

// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL( PolarCoordinateSystem,
                             C2U( "com.sun.star.comp.chart.PolarCoordinateSystem" ))

// =================================
// ==== PolarCoordinateSystem2d ====
// =================================

PolarCoordinateSystem2d::PolarCoordinateSystem2d(
    const uno::Reference< uno::XComponentContext > & xContext ) :
        PolarCoordinateSystem( xContext, 2, sal_False )
{}

PolarCoordinateSystem2d::~PolarCoordinateSystem2d()
{}

// ____ XServiceInfo ____
Sequence< OUString > PolarCoordinateSystem2d::getSupportedServiceNames_Static()
{
    Sequence< OUString > aServices( 2 );
    aServices[ 0 ] = CHART2_COOSYSTEM_POLAR_SERVICE_NAME;
    aServices[ 1 ] = lcl_aServiceNamePolar2d;
    return aServices;
}

// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL( PolarCoordinateSystem2d, lcl_aImplementationNamePolar2d )

// =================================
// ==== PolarCoordinateSystem3d ====
// =================================

PolarCoordinateSystem3d::PolarCoordinateSystem3d(
    const uno::Reference< uno::XComponentContext > & xContext ) :
        PolarCoordinateSystem( xContext, 3, sal_False )
{}

PolarCoordinateSystem3d::~PolarCoordinateSystem3d()
{}

// ____ XServiceInfo ____
Sequence< OUString > PolarCoordinateSystem3d::getSupportedServiceNames_Static()
{
    Sequence< OUString > aServices( 2 );
    aServices[ 0 ] = CHART2_COOSYSTEM_POLAR_SERVICE_NAME;
    aServices[ 1 ] = lcl_aServiceNamePolar3d;
    return aServices;
}

// implement XServiceInfo methods basing upon getSupportedServiceNames_Static
APPHELPER_XSERVICEINFO_IMPL( PolarCoordinateSystem3d, lcl_aImplementationNamePolar3d )

}  // namespace chart
<|endoftext|>


<commit_before>#include "BoundingBox.hpp"
#include "entities/Node.hpp"
#include "entities/Way.hpp"
#include "entities/Area.hpp"
#include "index/PersistentElementStore.hpp"

using namespace utymap;
using namespace utymap::index;
using namespace utymap::entities;

class PersistentElementStore::PersistentElementStoreImpl : public ElementVisitor
{
public:
    PersistentElementStoreImpl(const std::string& path) :
        path_(path),
        currentQuadKey_()
    {
    }

    void visitNode(const utymap::entities::Node& node) { }

    void visitWay(const utymap::entities::Way& way) { }

    void visitArea(const utymap::entities::Area& area) { }

    virtual void visitRelation(const utymap::entities::Relation& relation) { }

    void setQuadKey(const QuadKey& quadKey) { currentQuadKey_ = quadKey; }

private:
    std::string path_;
    QuadKey currentQuadKey_;
};

PersistentElementStore::PersistentElementStore(const std::string& path, StringTable& stringTable) :
    ElementStore(stringTable), pimpl_(new PersistentElementStore::PersistentElementStoreImpl(path))
{
}

PersistentElementStore::~PersistentElementStore()
{
}

void PersistentElementStore::storeImpl(const utymap::entities::Element& element, const QuadKey& quadKey)
{
    pimpl_->setQuadKey(quadKey);
    element.accept(*pimpl_);
}

void PersistentElementStore::search(const utymap::QuadKey& quadKey, utymap::entities::ElementVisitor& visitor)
{
    // TODO
}

bool PersistentElementStore::hasData(const utymap::QuadKey& quadKey) const
{
    // TODO
    return false;
}

void PersistentElementStore::commit()
{
}<commit_msg>core: commit intermediate progress on persistent storage<commit_after>#include "BoundingBox.hpp"
#include "entities/Node.hpp"
#include "entities/Way.hpp"
#include "entities/Area.hpp"
#include "entities/Relation.hpp"
#include "index/PersistentElementStore.hpp"

#include <fstream>
#include <sstream>

using namespace utymap;
using namespace utymap::index;
using namespace utymap::entities;
using namespace utymap::mapcss;
using namespace utymap::utils;

namespace {
    //                                      Index file format
    //   DESCRIPTION    |                       DETAILS                                                     |
    //------------------------------------------------------------------------------------------------------|
    //     Element      |  List of entries, each is represented by element id (8b) and file offset (4b)     |
    //------------------------------------------------------------------------------------------------------|
    const std::string IdOffsetFileExtension = ".idf";

    //                                      Data file format
    //------------------------------------------------------------------------------------------------------|
    //   DESCRIPTION    |                       DETAILS                                                     |
    //------------------------------------------------------------------------------------------------------|
    //  (1b) Flags      |  00 00 00 AA, where:                                                              |
    //                  |    AA - Element type (00 - Node, 01 - Way, 10 - Area, 11 - Relation)              |
    //------------------------------------------------------------------------------------------------------|
    //  (2b) Tags Size  |  Size of tag list where each tag represented by key-value pair (4b + 4b)          |
    //------------------------------------------------------------------------------------------------------|
    //      Tags        |               Tags data with size (2b)                                            |
    //------------------------------------------------------------------------------------------------------|
    //    Geometry      |             Geometry for Node, Way or Area                                        |
    //       or         |                                                                                |
    //    Element List  |             Element list in the same format + id                                  |
    //                  |                                                                                |
    //------------------------------------------------------------------------------------------------------|
    const std::string DataFileExtension = ".dat";

    // Writes element to file stream.
    class ElementWriter : public ElementVisitor
    {
    public:
        ElementWriter(std::fstream& dataFile) : dataFile_(dataFile)
        {
        }

        void visitNode(const Node& node)
        {
            writeFlags(0);
            writeTags(node.tags);
            writeCoordinate(node.coordinate);
        }

        void visitWay(const Way& way)
        {
            writeFlags(1);
            writeTags(way.tags);
            std::uint16_t size = static_cast<std::uint16_t>(way.coordinates.size());
            for (const auto& coord : way.coordinates) {
                writeCoordinate(coord);
            }
        }

        void visitArea(const Area& area)
        {
            writeFlags(2);
            writeTags(area.tags);
            // NOTE do not write the last one
            auto coordSize = area.coordinates.size() - 1;
            std::uint16_t size = static_cast<std::uint16_t>(coordSize);
            for (std::size_t i = 0; i < coordSize; ++i) {
                writeCoordinate(area.coordinates[i]);
            }
        }

        void visitRelation(const Relation& relation)
        {
            writeFlags(3);
            writeTags(relation.tags);
            for (const auto& element : relation.elements) {
                dataFile_.write(reinterpret_cast<const char*>(&element->id), sizeof(element->id));
                element->accept(*this);
            }
        }

    private:

        void writeFlags(const std::uint8_t flags)
        {
            dataFile_.write(reinterpret_cast<const char*>(&flags), sizeof(flags));
        }

        void writeTags(const std::vector<Tag>& tags)
        {
            std::uint16_t size = static_cast<std::uint16_t>(tags.size());
            dataFile_.write(reinterpret_cast<const char*>(&size), sizeof(size));
            for (const auto& tag : tags) {
                dataFile_.write(reinterpret_cast<const char*>(&tag.key), sizeof(tag.key));
                dataFile_.write(reinterpret_cast<const char*>(&tag.value), sizeof(tag.value));
            }
        }

        void writeCoordinate(const GeoCoordinate& coord)
        {
            dataFile_.write(reinterpret_cast<const char*>(&coord.latitude), sizeof(coord.latitude));
            dataFile_.write(reinterpret_cast<const char*>(&coord.longitude), sizeof(coord.longitude));
        }

        std::fstream& dataFile_;
    };

    // Reads element from file stream.
    class ElementReader
    {
    public:
        ElementReader(std::fstream& dataFile) : dataFile_(dataFile)
        {
        }

        std::shared_ptr<Element> readElement(std::uint64_t id, std::uint32_t offset)
        {
            dataFile_.seekg(offset, std::ios::beg);
            auto element = readElement();
            element->id = id;
            return element;
        }

    private:

        std::shared_ptr<Element> readElement()
        {
            std::uint8_t flags;
            dataFile_.read(reinterpret_cast<char*>(&flags), sizeof(flags));
            std::uint8_t elementType = flags && 0x3;

            switch (elementType) {
            case 0:
                return readNode();
            case 1:
                return readWay();
            case 2:
                return readArea();
            default:
                return readRelation();
            }
        }

        std::shared_ptr<Node> readNode()
        {
            auto node = std::make_shared<Node>();
            node->coordinate = readCoordinate();
            node->tags = readTags();
            return node;
        }

        std::shared_ptr<Way> readWay()
        {
            auto way = std::make_shared<Way>();
            way->tags = readTags();
            way->coordinates = readCoordinates(false);
            return way;
        }

        std::shared_ptr<Area> readArea()
        {
            auto area = std::make_shared<Area>();
            area->tags = readTags();
            area->coordinates = readCoordinates(true);
            return area;
        }

        std::shared_ptr<Relation> readRelation()
        {
            auto relation = std::make_shared<Relation>();
            relation->tags = readTags();
            std::uint16_t elementSize;
            dataFile_.read(reinterpret_cast<char*>(&elementSize), sizeof(elementSize));

            for (std::uint16_t i = 0; i < elementSize; ++i) {
                std::uint8_t elementType;
                relation->elements.push_back(readElement());
            }
            return relation;
        }

        inline GeoCoordinate readCoordinate()
        {
            GeoCoordinate coord;
            dataFile_.read(reinterpret_cast<char*>(&coord.latitude), sizeof(coord.latitude));
            dataFile_.read(reinterpret_cast<char*>(&coord.longitude), sizeof(coord.longitude));
            return coord;
        }

        inline std::vector<GeoCoordinate> readCoordinates(bool hasExtraElement)
        {
            std::uint16_t coordSize;
            dataFile_.read(reinterpret_cast<char*>(&coordSize), sizeof(coordSize));
            if (hasExtraElement)
                ++coordSize;

            std::vector<GeoCoordinate> coordinates;
            coordinates.reserve(coordSize);
            for (std::size_t i = 0; i < coordSize; ++i) {
                coordinates.push_back(readCoordinate());
            }

            return std::move(coordinates);
        }

        inline std::vector<Tag> readTags()
        {
            std::uint16_t tagSize;
            dataFile_.read(reinterpret_cast<char*>(&tagSize), sizeof(tagSize));

            std::vector<Tag> tags;
            for (std::size_t i = 0; i < tagSize; ++i) {
                Tag tag;
                dataFile_.read(reinterpret_cast<char*>(&tag.key), sizeof(tag.key));
                dataFile_.read(reinterpret_cast<char*>(&tag.value), sizeof(tag.value));
                tags.push_back(tag);
            }

            return std::move(tags);
        }

        std::fstream& dataFile_;
    };
}

class PersistentElementStore::PersistentElementStoreImpl
{
public:
    PersistentElementStoreImpl(const std::string& dataPath)
            : dataPath_(dataPath)
    {
    }

    void store(const Element& element, const QuadKey& quadKey)
    {
        // TODO ensure dataFile_

        ElementWriter visitor(dataFile_);
        element.accept(visitor);
    }

    void search(const QuadKey& quadKey, ElementVisitor& visitor)
    {
        // TODO ensure indexFile_ and dataFile_
        std::uint32_t count = static_cast<std::uint32_t>(indexFile_.tellg() /
                (sizeof(std::uint64_t) + sizeof(std::uint32_t)));

        ElementReader reader(dataFile_);

        indexFile_.seekg(0, std::ios::beg);
        for (std::uint32_t i = 0; i < count; ++i) {
            std::uint64_t id;
            std::uint32_t offset;
            indexFile_.read(reinterpret_cast<char*>(&id), sizeof(id));
            indexFile_.read(reinterpret_cast<char*>(&offset), sizeof(offset));

            reader.readElement(id, offset)->accept(visitor);
        }
    }

    bool hasData(const QuadKey& quadKey) const
    {
        std::ifstream file(getFilePath(quadKey, DataFileExtension));
        return file.good();
    }

private:
    // gets full file path for given quadkey
    inline std::string getFilePath(const QuadKey& quadKey, const std::string& extension) const
    {
        std::stringstream ss;
        ss << dataPath_ << "/" << quadKey.levelOfDetail << "/" << GeoUtils::quadKeyToString(quadKey) << extension;
        return ss.str();
    }

    const std::string dataPath_;
    const QuadKey currentQuadKey_;

    std::fstream indexFile_;
    std::fstream dataFile_;
};

PersistentElementStore::PersistentElementStore(const std::string& dataPath, StringTable& stringTable) :
        ElementStore(stringTable), pimpl_(new PersistentElementStore::PersistentElementStoreImpl(dataPath))
{
}

PersistentElementStore::~PersistentElementStore()
{
}

void PersistentElementStore::storeImpl(const Element& element, const QuadKey& quadKey)
{
    pimpl_->store(element, quadKey);
}

void PersistentElementStore::search(const QuadKey& quadKey, ElementVisitor& visitor)
{
    pimpl_->search(quadKey, visitor);
}

bool PersistentElementStore::hasData(const QuadKey& quadKey) const
{
    return pimpl_->hasData(quadKey);
}

void PersistentElementStore::commit()
{
}
<|endoftext|>


<commit_before>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#pragma once

#include <Object/Object.hh>

namespace Tadpole::Object {

class StringObject final : public BaseObject {
  sz_t size_{};
  char* data_{};
  u32_t hash_{};
public:
  StringObject(const char* s, sz_t n, u32_t h, bool move_owner = false) noexcept;
  virtual ~StringObject();

  inline sz_t size() const noexcept { return size_; }
  inline const char* data() const noexcept { return data_; }
  inline const char* cstr() const noexcept { return data_; }

  virtual bool is_truthy() const override;
  virtual str_t stringify() const override;

  static StringObject* create(const char* s, sz_t n);
  static StringObject* concat(StringObject* s1, StringObject* s2);

  template <typename N> static StringObject* create(const char* s, N n) {
    return create(s, Common::as_type<sz_t>(n));
  }

  static StringObject* create(const str_t& s) { return create(s.data(), s.size()); }
  static StringObject* create(strv_t s) { return create(s.data(), s.size()); }
};

}
<commit_msg>:construction: chore(string-object): add export methods for string-object<commit_after>// Copyright (c) 2021 ASMlover. All rights reserved.
//
//  ______             __                  ___
// /\__  _\           /\ \                /\_ \
// \/_/\ \/    __     \_\ \  _____     ___\//\ \      __
//    \ \ \  /'__`\   /'_` \/\ '__`\  / __`\\ \ \   /'__`\
//     \ \ \/\ \L\.\_/\ \L\ \ \ \L\ \/\ \L\ \\_\ \_/\  __/
//      \ \_\ \__/.\_\ \___,_\ \ ,__/\ \____//\____\ \____\
//       \/_/\/__/\/_/\/__,_ /\ \ \/  \/___/ \/____/\/____/
//                             \ \_\
//                              \/_/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#pragma once

#include <Object/Object.hh>

namespace Tadpole::Object {

class StringObject final : public BaseObject {
  sz_t size_{};
  char* data_{};
  u32_t hash_{};
public:
  StringObject(const char* s, sz_t n, u32_t h, bool move_owner = false) noexcept;
  virtual ~StringObject();

  inline sz_t size() const noexcept { return size_; }
  inline const char* data() const noexcept { return data_; }
  inline const char* cstr() const noexcept { return data_; }

  inline bool is_equal(StringObject* s) const noexcept { return this == s || is_equal(s->data_); }
  inline bool is_equal(const str_t& s) const noexcept { return s.compare(data_) == 0; }
  inline bool is_equal(strv_t s) const noexcept { return s.compare(data_) == 0; }
  inline bool is_equal(const char* s) const noexcept { return std::memcmp(data_, s, size_) == 0; }

  virtual bool is_truthy() const override;
  virtual str_t stringify() const override;

  static StringObject* create(const char* s, sz_t n);
  static StringObject* concat(StringObject* s1, StringObject* s2);

  template <typename N> static StringObject* create(const char* s, N n) {
    return create(s, Common::as_type<sz_t>(n));
  }

  static StringObject* create(const str_t& s) { return create(s.data(), s.size()); }
  static StringObject* create(strv_t s) { return create(s.data(), s.size()); }
};

}
<|endoftext|>


<commit_before><commit_msg>307. Range Sum Query - Mutable<commit_after><|endoftext|>