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

#include <activemasternode.h>
#include <masternode.h>
#include <masternode-sync.h>
#include <masternodeman.h>
#include <netbase.h>
#include <protocol.h>

// Keep track of the active Masternode
CActiveMasternode activeMasternode;

void CActiveMasternode::ManageState(CConnman* connman)
{
    LogPrint(BCLog::MNODE, "CActiveMasternode::ManageState -- Start\n");
    if(!fMasternodeMode) {
        LogPrint(BCLog::MNODE, "CActiveMasternode::ManageState -- Not a masternode, returning\n");
        return;
    }

    if(Params().NetworkIDString() != CBaseChainParams::REGTEST && !masternodeSync.IsBlockchainSynced()) {
        nState = ACTIVE_MASTERNODE_SYNC_IN_PROCESS;
        LogPrintf("CActiveMasternode::ManageState -- %s: %s\n", GetStateString(), GetStatus());
        return;
    }

    if(nState == ACTIVE_MASTERNODE_SYNC_IN_PROCESS) {
        nState = ACTIVE_MASTERNODE_INITIAL;
    }

    LogPrint(BCLog::MNODE, "CActiveMasternode::ManageState -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);

    if(eType == MASTERNODE_UNKNOWN) {
        ManageStateInitial(connman);
    }

    if(eType == MASTERNODE_REMOTE) {
        ManageStateRemote();
    }

    SendMasternodePing(connman);
}

std::string CActiveMasternode::GetStateString() const
{
    switch (nState) {
        case ACTIVE_MASTERNODE_INITIAL:         return "INITIAL";
        case ACTIVE_MASTERNODE_SYNC_IN_PROCESS: return "SYNC_IN_PROCESS";
        case ACTIVE_MASTERNODE_INPUT_TOO_NEW:   return "INPUT_TOO_NEW";
        case ACTIVE_MASTERNODE_NOT_CAPABLE:     return "NOT_CAPABLE";
        case ACTIVE_MASTERNODE_STARTED:         return "STARTED";
        default:                                return "UNKNOWN";
    }
}

std::string CActiveMasternode::GetStatus() const
{
    switch (nState) {
        case ACTIVE_MASTERNODE_INITIAL:         return "Node just started, not yet activated";
        case ACTIVE_MASTERNODE_SYNC_IN_PROCESS: return "Sync in progress. Must wait until sync is complete to start Masternode";
        case ACTIVE_MASTERNODE_INPUT_TOO_NEW:   return strprintf("Masternode input must have at least %d confirmations", Params().GetConsensus().nMasternodeMinimumConfirmations);
        case ACTIVE_MASTERNODE_NOT_CAPABLE:     return "Not capable masternode: " + strNotCapableReason;
        case ACTIVE_MASTERNODE_STARTED:         return "Masternode successfully started";
        default:                                return "Unknown";
    }
}

std::string CActiveMasternode::GetTypeString() const
{
    std::string strType;
    switch(eType) {
    case MASTERNODE_REMOTE:
        strType = "REMOTE";
        break;
    default:
        strType = "UNKNOWN";
        break;
    }
    return strType;
}

bool CActiveMasternode::SendMasternodePing(CConnman* connman)
{
    if(!fPingerEnabled) {
        LogPrint(BCLog::MNODE, "CActiveMasternode::SendMasternodePing -- %s: masternode ping service is disabled, skipping...\n", GetStateString());
        return false;
    }

    if(!mnodeman.Has(outpoint)) {
        strNotCapableReason = "Masternode not in masternode list";
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        LogPrintf("CActiveMasternode::SendMasternodePing -- %s: %s\n", GetStateString(), strNotCapableReason);
        return false;
    }

    CMasternodePing mnp(outpoint);
    mnp.nSentinelVersion = nSentinelVersion;
    mnp.fSentinelIsCurrent =
            (abs(GetAdjustedTime() - nSentinelPingTime) < MASTERNODE_WATCHDOG_MAX_SECONDS);
    if(!mnp.Sign(keyMasternode, pubKeyMasternode)) {
        LogPrintf("CActiveMasternode::SendMasternodePing -- ERROR: Couldn't sign Masternode Ping\n");
        return false;
    }

    // Update lastPing for our masternode in Masternode list
    if(mnodeman.IsMasternodePingedWithin(outpoint, MASTERNODE_MIN_MNP_SECONDS, mnp.sigTime)) {
        LogPrintf("CActiveMasternode::SendMasternodePing -- Too early to send Masternode Ping\n");
        return false;
    }

    mnodeman.SetMasternodeLastPing(outpoint, mnp);

    LogPrintf("CActiveMasternode::SendMasternodePing -- Relaying ping, collateral=%s\n", outpoint.ToStringShort());
    mnp.Relay(connman);

    return true;
}

bool CActiveMasternode::UpdateSentinelPing(int version)
{
    nSentinelVersion = version;
    nSentinelPingTime = GetAdjustedTime();

    return true;
}

void CActiveMasternode::ManageStateInitial(CConnman* connman)
{
    const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN);
    LogPrint(BCLog::MNODE, "CActiveMasternode::ManageStateInitial -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);

    // Check that our local network configuration is correct
    if (!fListen) {
        // listen option is probably overwritten by smth else, no good
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        strNotCapableReason = "Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter.";
        LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
        return;
    }

    // First try to find whatever local address is specified by externalip option
    bool fFoundLocal = GetLocal(service) && CMasternode::IsValidNetAddr(service);
    if(!fFoundLocal) {
        bool empty = true;
        // If we have some peers, let's try to find our local address from one of them
        connman->ForEachNodeContinueIf([&fFoundLocal, &empty, this](CNode* pnode) {
            empty = false;
            if (pnode->addr.IsIPv4())
                fFoundLocal = GetLocal(service, &pnode->addr) && CMasternode::IsValidNetAddr(service);
            return !fFoundLocal;
        });
        // nothing and no live connections, can't do anything for now
        if (empty) {
            nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
            strNotCapableReason = "Can't detect valid external address. Will retry when there are some connections available.";
            LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
            return;
        }
    }

    if(!fFoundLocal) {
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        strNotCapableReason = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only.";
        LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
        return;
    }

    int mainnetDefaultPort = defaultChainParams->GetDefaultPort();
    if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
        if(service.GetPort() != mainnetDefaultPort) {
            nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
            strNotCapableReason = strprintf("Invalid port: %u - only %d is supported on mainnet.", service.GetPort(), mainnetDefaultPort);
            LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
            return;
        }
    } else if(service.GetPort() == mainnetDefaultPort) {
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        strNotCapableReason = strprintf("Invalid port: %u - %d is only supported on mainnet.", service.GetPort(), mainnetDefaultPort);
        LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
        return;
    }

    // Check socket connectivity
    LogPrintf("CActiveMasternode::ManageStateInitial -- Checking inbound connection to '%s'\n", service.ToString());
    SOCKET hSocket;
    bool fConnected = ConnectSocketDirectly(service, hSocket, nConnectTimeout) && IsSelectableSocket(hSocket);
    CloseSocket(hSocket);

    if (!fConnected) {
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        strNotCapableReason = "Could not connect to " + service.ToString();
        LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
        return;
    }

    // Default to REMOTE
    eType = MASTERNODE_REMOTE;

    LogPrint(BCLog::MNODE, "CActiveMasternode::ManageStateInitial -- End status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
}

void CActiveMasternode::ManageStateRemote()
{
    LogPrint(BCLog::MNODE, "CActiveMasternode::ManageStateRemote -- Start status = %s, type = %s, pinger enabled = %d, pubKeyMasternode.GetID() = %s\n",
             GetStatus(), GetTypeString(), fPingerEnabled, pubKeyMasternode.GetID().ToString());

    mnodeman.CheckMasternode(pubKeyMasternode, true);
    masternode_info_t infoMn;
    if(mnodeman.GetMasternodeInfo(pubKeyMasternode, infoMn)) {
        if(infoMn.nProtocolVersion != PROTOCOL_VERSION) {
            nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
            strNotCapableReason = "Invalid protocol version";
            LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
            return;
        }
        if(service != infoMn.addr) {
            nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
            strNotCapableReason = "Broadcasted IP doesn't match our external address. Make sure you issued a new broadcast if IP of this masternode changed recently.";
            LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
            return;
        }
        if(!CMasternode::IsValidStateForAutoStart(infoMn.nActiveState)) {
            nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
            strNotCapableReason = strprintf("Masternode in %s state", CMasternode::StateToString(infoMn.nActiveState));
            LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
            return;
        }
        if(nState != ACTIVE_MASTERNODE_STARTED) {
            LogPrintf("CActiveMasternode::ManageStateRemote -- STARTED!\n");
            outpoint = infoMn.outpoint;
            service = infoMn.addr;
            fPingerEnabled = true;
            nState = ACTIVE_MASTERNODE_STARTED;
        }
    }
    else {
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        strNotCapableReason = "Masternode not in masternode list";
        LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
    }
}
<commit_msg>Masternode connection check: use newly introduced SOCKET create/connect<commit_after>// Copyright (c) 2014-2017 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <activemasternode.h>
#include <masternode.h>
#include <masternode-sync.h>
#include <masternodeman.h>
#include <netbase.h>
#include <protocol.h>

// Keep track of the active Masternode
CActiveMasternode activeMasternode;

void CActiveMasternode::ManageState(CConnman* connman)
{
    LogPrint(BCLog::MNODE, "CActiveMasternode::ManageState -- Start\n");
    if(!fMasternodeMode) {
        LogPrint(BCLog::MNODE, "CActiveMasternode::ManageState -- Not a masternode, returning\n");
        return;
    }

    if(Params().NetworkIDString() != CBaseChainParams::REGTEST && !masternodeSync.IsBlockchainSynced()) {
        nState = ACTIVE_MASTERNODE_SYNC_IN_PROCESS;
        LogPrintf("CActiveMasternode::ManageState -- %s: %s\n", GetStateString(), GetStatus());
        return;
    }

    if(nState == ACTIVE_MASTERNODE_SYNC_IN_PROCESS) {
        nState = ACTIVE_MASTERNODE_INITIAL;
    }

    LogPrint(BCLog::MNODE, "CActiveMasternode::ManageState -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);

    if(eType == MASTERNODE_UNKNOWN) {
        ManageStateInitial(connman);
    }

    if(eType == MASTERNODE_REMOTE) {
        ManageStateRemote();
    }

    SendMasternodePing(connman);
}

std::string CActiveMasternode::GetStateString() const
{
    switch (nState) {
        case ACTIVE_MASTERNODE_INITIAL:         return "INITIAL";
        case ACTIVE_MASTERNODE_SYNC_IN_PROCESS: return "SYNC_IN_PROCESS";
        case ACTIVE_MASTERNODE_INPUT_TOO_NEW:   return "INPUT_TOO_NEW";
        case ACTIVE_MASTERNODE_NOT_CAPABLE:     return "NOT_CAPABLE";
        case ACTIVE_MASTERNODE_STARTED:         return "STARTED";
        default:                                return "UNKNOWN";
    }
}

std::string CActiveMasternode::GetStatus() const
{
    switch (nState) {
        case ACTIVE_MASTERNODE_INITIAL:         return "Node just started, not yet activated";
        case ACTIVE_MASTERNODE_SYNC_IN_PROCESS: return "Sync in progress. Must wait until sync is complete to start Masternode";
        case ACTIVE_MASTERNODE_INPUT_TOO_NEW:   return strprintf("Masternode input must have at least %d confirmations", Params().GetConsensus().nMasternodeMinimumConfirmations);
        case ACTIVE_MASTERNODE_NOT_CAPABLE:     return "Not capable masternode: " + strNotCapableReason;
        case ACTIVE_MASTERNODE_STARTED:         return "Masternode successfully started";
        default:                                return "Unknown";
    }
}

std::string CActiveMasternode::GetTypeString() const
{
    std::string strType;
    switch(eType) {
    case MASTERNODE_REMOTE:
        strType = "REMOTE";
        break;
    default:
        strType = "UNKNOWN";
        break;
    }
    return strType;
}

bool CActiveMasternode::SendMasternodePing(CConnman* connman)
{
    if(!fPingerEnabled) {
        LogPrint(BCLog::MNODE, "CActiveMasternode::SendMasternodePing -- %s: masternode ping service is disabled, skipping...\n", GetStateString());
        return false;
    }

    if(!mnodeman.Has(outpoint)) {
        strNotCapableReason = "Masternode not in masternode list";
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        LogPrintf("CActiveMasternode::SendMasternodePing -- %s: %s\n", GetStateString(), strNotCapableReason);
        return false;
    }

    CMasternodePing mnp(outpoint);
    mnp.nSentinelVersion = nSentinelVersion;
    mnp.fSentinelIsCurrent =
            (abs(GetAdjustedTime() - nSentinelPingTime) < MASTERNODE_WATCHDOG_MAX_SECONDS);
    if(!mnp.Sign(keyMasternode, pubKeyMasternode)) {
        LogPrintf("CActiveMasternode::SendMasternodePing -- ERROR: Couldn't sign Masternode Ping\n");
        return false;
    }

    // Update lastPing for our masternode in Masternode list
    if(mnodeman.IsMasternodePingedWithin(outpoint, MASTERNODE_MIN_MNP_SECONDS, mnp.sigTime)) {
        LogPrintf("CActiveMasternode::SendMasternodePing -- Too early to send Masternode Ping\n");
        return false;
    }

    mnodeman.SetMasternodeLastPing(outpoint, mnp);

    LogPrintf("CActiveMasternode::SendMasternodePing -- Relaying ping, collateral=%s\n", outpoint.ToStringShort());
    mnp.Relay(connman);

    return true;
}

bool CActiveMasternode::UpdateSentinelPing(int version)
{
    nSentinelVersion = version;
    nSentinelPingTime = GetAdjustedTime();

    return true;
}

void CActiveMasternode::ManageStateInitial(CConnman* connman)
{
    const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN);
    LogPrint(BCLog::MNODE, "CActiveMasternode::ManageStateInitial -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);

    // Check that our local network configuration is correct
    if (!fListen) {
        // listen option is probably overwritten by smth else, no good
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        strNotCapableReason = "Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter.";
        LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
        return;
    }

    // First try to find whatever local address is specified by externalip option
    bool fFoundLocal = GetLocal(service) && CMasternode::IsValidNetAddr(service);
    if(!fFoundLocal) {
        bool empty = true;
        // If we have some peers, let's try to find our local address from one of them
        connman->ForEachNodeContinueIf([&fFoundLocal, &empty, this](CNode* pnode) {
            empty = false;
            if (pnode->addr.IsIPv4())
                fFoundLocal = GetLocal(service, &pnode->addr) && CMasternode::IsValidNetAddr(service);
            return !fFoundLocal;
        });
        // nothing and no live connections, can't do anything for now
        if (empty) {
            nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
            strNotCapableReason = "Can't detect valid external address. Will retry when there are some connections available.";
            LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
            return;
        }
    }

    if(!fFoundLocal) {
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        strNotCapableReason = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only.";
        LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
        return;
    }

    int mainnetDefaultPort = defaultChainParams->GetDefaultPort();
    if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
        if(service.GetPort() != mainnetDefaultPort) {
            nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
            strNotCapableReason = strprintf("Invalid port: %u - only %d is supported on mainnet.", service.GetPort(), mainnetDefaultPort);
            LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
            return;
        }
    } else if(service.GetPort() == mainnetDefaultPort) {
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        strNotCapableReason = strprintf("Invalid port: %u - %d is only supported on mainnet.", service.GetPort(), mainnetDefaultPort);
        LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
        return;
    }

    // Check socket connectivity
    LogPrintf("CActiveMasternode::ManageStateInitial -- Checking inbound connection to '%s'\n", service.ToString());
    SOCKET hSocket = CreateSocket(service);
    if (hSocket == INVALID_SOCKET) {
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        strNotCapableReason = "Could open connection to " + service.ToString();
        LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
        return;
    }

    bool fConnected = ConnectSocketDirectly(service, hSocket, nConnectTimeout);

    if (!fConnected) {
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        strNotCapableReason = "Could not connect to " + service.ToString();
        LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
        return;
    }

    CloseSocket(hSocket);
    // Default to REMOTE
    eType = MASTERNODE_REMOTE;

    LogPrint(BCLog::MNODE, "CActiveMasternode::ManageStateInitial -- End status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
}

void CActiveMasternode::ManageStateRemote()
{
    LogPrint(BCLog::MNODE, "CActiveMasternode::ManageStateRemote -- Start status = %s, type = %s, pinger enabled = %d, pubKeyMasternode.GetID() = %s\n",
             GetStatus(), GetTypeString(), fPingerEnabled, pubKeyMasternode.GetID().ToString());

    mnodeman.CheckMasternode(pubKeyMasternode, true);
    masternode_info_t infoMn;
    if(mnodeman.GetMasternodeInfo(pubKeyMasternode, infoMn)) {
        if(infoMn.nProtocolVersion != PROTOCOL_VERSION) {
            nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
            strNotCapableReason = "Invalid protocol version";
            LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
            return;
        }
        if(service != infoMn.addr) {
            nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
            strNotCapableReason = "Broadcasted IP doesn't match our external address. Make sure you issued a new broadcast if IP of this masternode changed recently.";
            LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
            return;
        }
        if(!CMasternode::IsValidStateForAutoStart(infoMn.nActiveState)) {
            nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
            strNotCapableReason = strprintf("Masternode in %s state", CMasternode::StateToString(infoMn.nActiveState));
            LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
            return;
        }
        if(nState != ACTIVE_MASTERNODE_STARTED) {
            LogPrintf("CActiveMasternode::ManageStateRemote -- STARTED!\n");
            outpoint = infoMn.outpoint;
            service = infoMn.addr;
            fPingerEnabled = true;
            nState = ACTIVE_MASTERNODE_STARTED;
        }
    }
    else {
        nState = ACTIVE_MASTERNODE_NOT_CAPABLE;
        strNotCapableReason = "Masternode not in masternode list";
        LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
    }
}
<|endoftext|>


<commit_before>#ifndef ___INANITY_WINDOWS_HPP___
#define ___INANITY_WINDOWS_HPP___

#ifndef ___INANITY_WINDOWS
#error This is not windows!
#endif

#define STRICT
#ifndef NOMINMAX
#define NOMINMAX
#endif
#define UNICODE
#define _UNICODE
#include <windows.h>

#endif
<commit_msg>added windows version targeting in windows.hpp<commit_after>#ifndef ___INANITY_WINDOWS_HPP___
#define ___INANITY_WINDOWS_HPP___

#ifndef ___INANITY_WINDOWS
#error This is not windows!
#endif

#define STRICT
#ifndef NOMINMAX
#define NOMINMAX
#endif
#define UNICODE
#define _UNICODE
#define _WIN32_WINNT _WIN32_WINNT_VISTA
#include <windows.h>

#endif
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * http://lxqt.org
 *
 * Copyright: 2014 LXQt team
 * Authors:
 *   Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "ossengine.h"
#include "audiodevice.h"
#include <QDebug>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>

#ifdef __FreeBSD__
#include <sys/soundcard.h>
#elif defined(__linux__) || defined(__Linux__)
#include <linux/soundcard.h>
#else
#error "Not supported platform"
#endif

OssEngine::OssEngine(QObject *parent) :
    AudioEngine(parent),
    m_mixer(-1),
    m_device(NULL),
    m_leftVolume(0),
    m_rightVolume(0)
{
    qDebug() << "OssEngine";
    initMixer();
}

OssEngine::~OssEngine()
{
    if(m_mixer >= 0)
        close(m_mixer);
}

void OssEngine::initMixer() {
    m_mixer = open ("/dev/mixer", O_RDWR, 0);
    if (m_mixer < 0) {
      qDebug() << "/dev/mixer cannot be opened";
      return;
    }
    qDebug() << "InitMixer:" << m_mixer;

    m_device = new AudioDevice(Sink, this);
    m_device->setName("Master");
    m_device->setIndex(0);
    m_device->setDescription("Master Volume");
    m_device->setMuteNoCommit(false);
    updateVolume();

    m_sinks.append(m_device);
    emit sinkListChanged();
}

void OssEngine::updateVolume() {
    if(m_mixer < 0 || !m_device)
        return;
    int volumes;
    if(ioctl(m_mixer, MIXER_READ(SOUND_MIXER_VOLUME), &volumes) < 0) {
        qDebug() << "updateVolume() failed" << errno;
    }
    m_leftVolume = volumes & 0xff; // left
    m_rightVolume = (volumes >> 8) & 0xff; // right
    qDebug() << "volume:" << m_leftVolume << m_rightVolume;

    m_device->setVolumeNoCommit(m_leftVolume);
}

void OssEngine::setVolume(int volume) {
    if(m_mixer < 0)
        return;
    int volumes = (volume << 8) + volume;
    if(ioctl(m_mixer, MIXER_WRITE(SOUND_MIXER_VOLUME), &volumes) < 0) {
        qDebug() << "setVolume() failed" << errno;
    }
    else {
        qDebug() << "setVolume()" << volume;
    }
}

void OssEngine::commitDeviceVolume(AudioDevice *device)
{
    if (!device)
        return;
    setVolume(device->volume());
}

void OssEngine::setMute(AudioDevice *device, bool state)
{
  if(state)
      setVolume(0);
  else
      setVolume(m_leftVolume);
}

void OssEngine::setIgnoreMaxVolume(bool ignore)
{
  // TODO
}
<commit_msg>Fix NetBSD build<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * http://lxqt.org
 *
 * Copyright: 2014 LXQt team
 * Authors:
 *   Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "ossengine.h"
#include "audiodevice.h"
#include <QDebug>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>

#if defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/soundcard.h>
#elif defined(__linux__) || defined(__Linux__)
#include <linux/soundcard.h>
#else
#error "Not supported platform"
#endif

OssEngine::OssEngine(QObject *parent) :
    AudioEngine(parent),
    m_mixer(-1),
    m_device(NULL),
    m_leftVolume(0),
    m_rightVolume(0)
{
    qDebug() << "OssEngine";
    initMixer();
}

OssEngine::~OssEngine()
{
    if(m_mixer >= 0)
        close(m_mixer);
}

void OssEngine::initMixer() {
    m_mixer = open ("/dev/mixer", O_RDWR, 0);
    if (m_mixer < 0) {
      qDebug() << "/dev/mixer cannot be opened";
      return;
    }
    qDebug() << "InitMixer:" << m_mixer;

    m_device = new AudioDevice(Sink, this);
    m_device->setName("Master");
    m_device->setIndex(0);
    m_device->setDescription("Master Volume");
    m_device->setMuteNoCommit(false);
    updateVolume();

    m_sinks.append(m_device);
    emit sinkListChanged();
}

void OssEngine::updateVolume() {
    if(m_mixer < 0 || !m_device)
        return;
    int volumes;
    if(ioctl(m_mixer, MIXER_READ(SOUND_MIXER_VOLUME), &volumes) < 0) {
        qDebug() << "updateVolume() failed" << errno;
    }
    m_leftVolume = volumes & 0xff; // left
    m_rightVolume = (volumes >> 8) & 0xff; // right
    qDebug() << "volume:" << m_leftVolume << m_rightVolume;

    m_device->setVolumeNoCommit(m_leftVolume);
}

void OssEngine::setVolume(int volume) {
    if(m_mixer < 0)
        return;
    int volumes = (volume << 8) + volume;
    if(ioctl(m_mixer, MIXER_WRITE(SOUND_MIXER_VOLUME), &volumes) < 0) {
        qDebug() << "setVolume() failed" << errno;
    }
    else {
        qDebug() << "setVolume()" << volume;
    }
}

void OssEngine::commitDeviceVolume(AudioDevice *device)
{
    if (!device)
        return;
    setVolume(device->volume());
}

void OssEngine::setMute(AudioDevice *device, bool state)
{
  if(state)
      setVolume(0);
  else
      setVolume(m_leftVolume);
}

void OssEngine::setIgnoreMaxVolume(bool ignore)
{
  // TODO
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// bwtree_index.cpp
//
// Identification: src/backend/index/bwtree_index.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//
#include "index/bwtree_index.h"

#include "common/logger.h"
#include "index/index_key.h"
#include "index/scan_optimizer.h"
#include "statistics/stats_aggregator.h"
#include "storage/tuple.h"

namespace peloton {
namespace index {

BWTREE_TEMPLATE_ARGUMENTS
BWTREE_INDEX_TYPE::BWTreeIndex(IndexMetadata *metadata)
    :  // Base class
      Index{metadata},
      // Key "less than" relation comparator
      comparator{},
      // Key equality checker
      equals{},
      // Key hash function
      hash_func{},
      // NOTE: These two arguments need to be constructed in advance
      // and do not have trivial constructor
      //
      // NOTE 2: We set the first parameter to false to disable automatic GC
      //
      container{false, comparator, equals, hash_func} {
  return;
}

BWTREE_TEMPLATE_ARGUMENTS
BWTREE_INDEX_TYPE::~BWTreeIndex() {}

/*
 * InsertEntry() - insert a key-value pair into the map
 *
 * If the key value pair already exists in the map, just return false
 */
BWTREE_TEMPLATE_ARGUMENTS
bool BWTREE_INDEX_TYPE::InsertEntry(const storage::Tuple *key,
                                    ItemPointer *value) {
  KeyType index_key;
  index_key.SetFromKey(key);

  bool ret = container.Insert(index_key, value);

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance()->IncrementIndexInserts(metadata);
  }

  return ret;
}

/*
 * DeleteEntry() - Removes a key-value pair
 *
 * If the key-value pair does not exists yet in the map return false
 */
BWTREE_TEMPLATE_ARGUMENTS
bool BWTREE_INDEX_TYPE::DeleteEntry(const storage::Tuple *key,
                                    ItemPointer *value) {
  KeyType index_key;
  index_key.SetFromKey(key);
  size_t delete_count = 0;

  // In Delete() since we just use the value for comparison (i.e. read-only)
  // it is unnecessary for us to allocate memory
  bool ret = container.Delete(index_key, value);

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance()->IncrementIndexDeletes(
        delete_count, metadata);
  }
  return ret;
}

BWTREE_TEMPLATE_ARGUMENTS
bool BWTREE_INDEX_TYPE::CondInsertEntry(
    const storage::Tuple *key, ItemPointer *value,
    std::function<bool(const void *)> predicate) {
  KeyType index_key;
  index_key.SetFromKey(key);

  bool predicate_satisfied = false;

  // This function will complete them in one step
  // predicate will be set to nullptr if the predicate
  // returns true for some value
  bool ret = container.ConditionalInsert(index_key, value, predicate,
                                         &predicate_satisfied);

  // If predicate is not satisfied then we know insertion successes
  if (predicate_satisfied == false) {
    // So it should always succeed?
    assert(ret == true);
  } else {
    assert(ret == false);
  }

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance()->IncrementIndexInserts(metadata);
  }

  return ret;
}

/*
 * Scan() - Scans a range inside the index using index scan optimizer
 *
 * The scan optimizer specifies whether a scan is point query, full scan
 * or interval scan. For all of these cases the corresponding functions from
 * the index is called, and all elements are returned in result vector
 */
BWTREE_TEMPLATE_ARGUMENTS
void BWTREE_INDEX_TYPE::Scan(
    UNUSED_ATTRIBUTE const std::vector<type::Value> &value_list,
    UNUSED_ATTRIBUTE const std::vector<oid_t> &tuple_column_id_list,
    UNUSED_ATTRIBUTE const std::vector<ExpressionType> &expr_list,
    ScanDirectionType scan_direction, std::vector<ValueType> &result,
    const ConjunctionScanPredicate *csp_p) {
  // This is a hack - we do not support backward scan
  if (scan_direction == SCAN_DIRECTION_TYPE_INVALID) {
    throw Exception("Invalid scan direction \n");
  }

  LOG_TRACE("Scan() Point Query = %d; Full Scan = %d ", csp_p->IsPointQuery(),
            csp_p->IsFullIndexScan());

  if (csp_p->IsPointQuery() == true) {
    const storage::Tuple *point_query_key_p = csp_p->GetPointQueryKey();

    KeyType point_query_key;
    point_query_key.SetFromKey(point_query_key_p);

    // Note: We could call ScanKey() to achieve better modularity
    // (slightly less code), but since ScanKey() is a virtual function
    // this would induce an overhead for point query, which must be highly
    // optimized and super fast
    container.GetValue(point_query_key, result);
  } else if (csp_p->IsFullIndexScan() == true) {
    // If it is a full index scan, then just do the scan
    // until we have reached the end of the index by the same
    // we take the snapshot of the last leaf node
    for (auto scan_itr = container.Begin(); (scan_itr.IsEnd() == false);
         scan_itr++) {
      result.push_back(scan_itr->second);
    }  // for it from begin() to end()
  } else {
    const storage::Tuple *low_key_p = csp_p->GetLowKey();
    const storage::Tuple *high_key_p = csp_p->GetHighKey();

    LOG_TRACE("Partial scan low key: %s\n high key: %s",
              low_key_p->GetInfo().c_str(), high_key_p->GetInfo().c_str());

    // Construct low key and high key in KeyType form, rather than
    // the standard in-memory tuple
    KeyType index_low_key;
    KeyType index_high_key;
    index_low_key.SetFromKey(low_key_p);
    index_high_key.SetFromKey(high_key_p);

    // We use bwtree Begin() to first reach the lower bound
    // of the search key
    // Also we keep scanning until we have reached the end of the index
    // or we have seen a key higher than the high key
    for (auto scan_itr = container.Begin(index_low_key);
         (scan_itr.IsEnd() == false) &&
             (container.KeyCmpLessEqual(scan_itr->first, index_high_key));
         scan_itr++) {
      result.push_back(scan_itr->second);
    }
  }  // if is full scan

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance()->IncrementIndexReads(
        result.size(), metadata);
  }

  return;
}

/*
 * ScanLimit() - Scan the index with predicate and limit/offset
 *
 * This function scans the index using the given index optimizer's low key and
 * high key. In addition to merely doing the scan, it checks scan direction
 * and uses either begin() or end() iterator to scan the index, and stops
 * after offset + limit elements are scanned, and limit elements are finally
 * returned
 */
BWTREE_TEMPLATE_ARGUMENTS
void BWTREE_INDEX_TYPE::ScanLimit(
    const std::vector<type::Value> &value_list,
    const std::vector<oid_t> &tuple_column_id_list,
    const std::vector<ExpressionType> &expr_list,
    ScanDirectionType scan_direction, std::vector<ValueType> &result,
    const ConjunctionScanPredicate *csp_p, uint64_t limit, uint64_t offset) {

  // Only work with limit == 1 and offset == 0
  // Because that gets translated to "min"
  // But still since we could not access tuples in the table
  // the index just fetches the first qualified key without further checking
  // including checking for non-exact bounds!!!
  if (csp_p->IsPointQuery() == false && limit == 1 && offset == 0) {
    if (scan_direction == SCAN_DIRECTION_TYPE_FORWARD) {
      const storage::Tuple *low_key_p = csp_p->GetLowKey();
      const storage::Tuple *high_key_p = csp_p->GetHighKey();

      LOG_TRACE(
          "ScanLimit() special case (limit = 1; offset = 0; ASCENDING): %s",
          low_key_p->GetInfo().c_str());

      KeyType index_low_key;
      KeyType index_high_key;
      index_low_key.SetFromKey(low_key_p);
      index_high_key.SetFromKey(high_key_p);

      auto scan_itr = container.Begin(index_low_key);
      if ((scan_itr.IsEnd() == false) &&
          (container.KeyCmpLessEqual(scan_itr->first, index_high_key))) {

        result.push_back(scan_itr->second);
      }
    }
    // descending
    else if (scan_direction == SCAN_DIRECTION_TYPE_BACKWARD) {
      const storage::Tuple *low_key_p = csp_p->GetLowKey();
      const storage::Tuple *high_key_p = csp_p->GetHighKey();

      LOG_TRACE(
          "ScanLimit() special case (limit = 1;"
          " offset = 0; DESCENDING): %s",
          high_key_p->GetInfo().c_str());

      KeyType index_low_key;
      KeyType index_high_key;
      index_low_key.SetFromKey(low_key_p);
      index_high_key.SetFromKey(high_key_p);

      // This might or might not reach the high key
      // If it does not reach high key then the high key does not exist
      // and we need to move the iterator backward by 1
      auto scan_itr = container.Begin(index_high_key);

      // It could not be REND since we just use lower_bound
      // Note that REND < BEGIN <= END
      // and REND == --BEGIN
      // and Beein() must return something between [BEGIN, END]
      // we do not worry about REND
      // We rely on short circuited logic expression here to make sure
      // either iterator is END or it is a valid value for testing
      if (scan_itr.IsEnd() == true ||
          container.KeyCmpLess(index_high_key, scan_itr->first) == true) {
        scan_itr--;

        // If after decreament it is REND then return because we could not
        // test the current element
        if (scan_itr.IsREnd() == true) {
          LOG_TRACE("After decreamenting it is REND iterator");

          return;
        }

        // We must reach a valid key; otherwise we will reach it in
        // the previous Begin()
        // But still it might not be exact
        PL_ASSERT(container.KeyCmpLess(index_high_key, scan_itr->first) ==
                  false);
      }

      if (container.KeyCmpLess(scan_itr->first, index_low_key) == true) {
        LOG_TRACE(
            "The iterator is not qualified "
            "because it is smaller than low key");

        return;
      }

      // After this we know the iterator is between [low key, high key]
      // and may be on the high en

      KeyType prev_key = scan_itr->first;

      do {
        result.push_back(scan_itr->second);
        scan_itr--;
      } while (scan_itr.IsREnd() == false &&
               container.KeyCmpEqual(scan_itr->first, prev_key) == true);

      LOG_TRACE("In bewtree, result size is %lu", result.size());
    } else {
      throw "ScanLimit(): Invalid scan direction";
    }
  }
  // Last
  else {
    Scan(value_list, tuple_column_id_list, expr_list, scan_direction, result,
         csp_p);
  }

  return;
}

BWTREE_TEMPLATE_ARGUMENTS
void BWTREE_INDEX_TYPE::ScanAllKeys(std::vector<ValueType> &result) {
  auto it = container.Begin();

  // scan all entries
  while (it.IsEnd() == false) {
    result.push_back(it->second);
    it++;
  }

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance()->IncrementIndexReads(
        result.size(), metadata);
  }
  return;
}

BWTREE_TEMPLATE_ARGUMENTS
void BWTREE_INDEX_TYPE::ScanKey(const storage::Tuple *key,
                                std::vector<ValueType> &result) {
  KeyType index_key;
  index_key.SetFromKey(key);

  // This function in BwTree fills a given vector
  container.GetValue(index_key, result);

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance()->IncrementIndexReads(
        result.size(), metadata);
  }

  return;
}

BWTREE_TEMPLATE_ARGUMENTS
std::string BWTREE_INDEX_TYPE::GetTypeName() const { return "BWTree"; }

// IMPORTANT: Make sure you don't exceed CompactIntegerKey_MAX_SLOTS

template class BWTreeIndex<CompactIntsKey<1>, ItemPointer *,
                           CompactIntsComparator<1>,
                           CompactIntsEqualityChecker<1>, CompactIntsHasher<1>,
                           ItemPointerComparator, ItemPointerHashFunc>;
template class BWTreeIndex<CompactIntsKey<2>, ItemPointer *,
                           CompactIntsComparator<2>,
                           CompactIntsEqualityChecker<2>, CompactIntsHasher<2>,
                           ItemPointerComparator, ItemPointerHashFunc>;
template class BWTreeIndex<CompactIntsKey<3>, ItemPointer *,
                           CompactIntsComparator<3>,
                           CompactIntsEqualityChecker<3>, CompactIntsHasher<3>,
                           ItemPointerComparator, ItemPointerHashFunc>;
template class BWTreeIndex<CompactIntsKey<4>, ItemPointer *,
                           CompactIntsComparator<4>,
                           CompactIntsEqualityChecker<4>, CompactIntsHasher<4>,
                           ItemPointerComparator, ItemPointerHashFunc>;

// Generic key
template class BWTreeIndex<GenericKey<4>, ItemPointer *,
                           FastGenericComparator<4>, GenericEqualityChecker<4>,
                           GenericHasher<4>, ItemPointerComparator,
                           ItemPointerHashFunc>;
template class BWTreeIndex<GenericKey<8>, ItemPointer *,
                           FastGenericComparator<8>, GenericEqualityChecker<8>,
                           GenericHasher<8>, ItemPointerComparator,
                           ItemPointerHashFunc>;
template class BWTreeIndex<GenericKey<16>, ItemPointer *,
                           FastGenericComparator<16>,
                           GenericEqualityChecker<16>, GenericHasher<16>,
                           ItemPointerComparator, ItemPointerHashFunc>;
template class BWTreeIndex<GenericKey<64>, ItemPointer *,
                           FastGenericComparator<64>,
                           GenericEqualityChecker<64>, GenericHasher<64>,
                           ItemPointerComparator, ItemPointerHashFunc>;
template class BWTreeIndex<GenericKey<256>, ItemPointer *,
                           FastGenericComparator<256>,
                           GenericEqualityChecker<256>, GenericHasher<256>,
                           ItemPointerComparator, ItemPointerHashFunc>;

// Tuple key
template class BWTreeIndex<TupleKey, ItemPointer *, TupleKeyComparator,
                           TupleKeyEqualityChecker, TupleKeyHasher,
                           ItemPointerComparator, ItemPointerHashFunc>;

}  // End index namespace
}  // End peloton namespace
<commit_msg>remove backward limit 1 in bwtree<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// bwtree_index.cpp
//
// Identification: src/backend/index/bwtree_index.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//
#include "index/bwtree_index.h"

#include "common/logger.h"
#include "index/index_key.h"
#include "index/scan_optimizer.h"
#include "statistics/stats_aggregator.h"
#include "storage/tuple.h"

namespace peloton {
namespace index {

BWTREE_TEMPLATE_ARGUMENTS
BWTREE_INDEX_TYPE::BWTreeIndex(IndexMetadata *metadata)
    :  // Base class
      Index{metadata},
      // Key "less than" relation comparator
      comparator{},
      // Key equality checker
      equals{},
      // Key hash function
      hash_func{},
      // NOTE: These two arguments need to be constructed in advance
      // and do not have trivial constructor
      //
      // NOTE 2: We set the first parameter to false to disable automatic GC
      //
      container{false, comparator, equals, hash_func} {
  return;
}

BWTREE_TEMPLATE_ARGUMENTS
BWTREE_INDEX_TYPE::~BWTreeIndex() {}

/*
 * InsertEntry() - insert a key-value pair into the map
 *
 * If the key value pair already exists in the map, just return false
 */
BWTREE_TEMPLATE_ARGUMENTS
bool BWTREE_INDEX_TYPE::InsertEntry(const storage::Tuple *key,
                                    ItemPointer *value) {
  KeyType index_key;
  index_key.SetFromKey(key);

  bool ret = container.Insert(index_key, value);

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance()->IncrementIndexInserts(metadata);
  }

  return ret;
}

/*
 * DeleteEntry() - Removes a key-value pair
 *
 * If the key-value pair does not exists yet in the map return false
 */
BWTREE_TEMPLATE_ARGUMENTS
bool BWTREE_INDEX_TYPE::DeleteEntry(const storage::Tuple *key,
                                    ItemPointer *value) {
  KeyType index_key;
  index_key.SetFromKey(key);
  size_t delete_count = 0;

  // In Delete() since we just use the value for comparison (i.e. read-only)
  // it is unnecessary for us to allocate memory
  bool ret = container.Delete(index_key, value);

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance()->IncrementIndexDeletes(
        delete_count, metadata);
  }
  return ret;
}

BWTREE_TEMPLATE_ARGUMENTS
bool BWTREE_INDEX_TYPE::CondInsertEntry(
    const storage::Tuple *key, ItemPointer *value,
    std::function<bool(const void *)> predicate) {
  KeyType index_key;
  index_key.SetFromKey(key);

  bool predicate_satisfied = false;

  // This function will complete them in one step
  // predicate will be set to nullptr if the predicate
  // returns true for some value
  bool ret = container.ConditionalInsert(index_key, value, predicate,
                                         &predicate_satisfied);

  // If predicate is not satisfied then we know insertion successes
  if (predicate_satisfied == false) {
    // So it should always succeed?
    assert(ret == true);
  } else {
    assert(ret == false);
  }

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance()->IncrementIndexInserts(metadata);
  }

  return ret;
}

/*
 * Scan() - Scans a range inside the index using index scan optimizer
 *
 * The scan optimizer specifies whether a scan is point query, full scan
 * or interval scan. For all of these cases the corresponding functions from
 * the index is called, and all elements are returned in result vector
 */
BWTREE_TEMPLATE_ARGUMENTS
void BWTREE_INDEX_TYPE::Scan(
    UNUSED_ATTRIBUTE const std::vector<type::Value> &value_list,
    UNUSED_ATTRIBUTE const std::vector<oid_t> &tuple_column_id_list,
    UNUSED_ATTRIBUTE const std::vector<ExpressionType> &expr_list,
    ScanDirectionType scan_direction, std::vector<ValueType> &result,
    const ConjunctionScanPredicate *csp_p) {
  // This is a hack - we do not support backward scan
  if (scan_direction == SCAN_DIRECTION_TYPE_INVALID) {
    throw Exception("Invalid scan direction \n");
  }

  LOG_TRACE("Scan() Point Query = %d; Full Scan = %d ", csp_p->IsPointQuery(),
            csp_p->IsFullIndexScan());

  if (csp_p->IsPointQuery() == true) {
    const storage::Tuple *point_query_key_p = csp_p->GetPointQueryKey();

    KeyType point_query_key;
    point_query_key.SetFromKey(point_query_key_p);

    // Note: We could call ScanKey() to achieve better modularity
    // (slightly less code), but since ScanKey() is a virtual function
    // this would induce an overhead for point query, which must be highly
    // optimized and super fast
    container.GetValue(point_query_key, result);
  } else if (csp_p->IsFullIndexScan() == true) {
    // If it is a full index scan, then just do the scan
    // until we have reached the end of the index by the same
    // we take the snapshot of the last leaf node
    for (auto scan_itr = container.Begin(); (scan_itr.IsEnd() == false);
         scan_itr++) {
      result.push_back(scan_itr->second);
    }  // for it from begin() to end()
  } else {
    const storage::Tuple *low_key_p = csp_p->GetLowKey();
    const storage::Tuple *high_key_p = csp_p->GetHighKey();

    LOG_TRACE("Partial scan low key: %s\n high key: %s",
              low_key_p->GetInfo().c_str(), high_key_p->GetInfo().c_str());

    // Construct low key and high key in KeyType form, rather than
    // the standard in-memory tuple
    KeyType index_low_key;
    KeyType index_high_key;
    index_low_key.SetFromKey(low_key_p);
    index_high_key.SetFromKey(high_key_p);

    // We use bwtree Begin() to first reach the lower bound
    // of the search key
    // Also we keep scanning until we have reached the end of the index
    // or we have seen a key higher than the high key
    for (auto scan_itr = container.Begin(index_low_key);
         (scan_itr.IsEnd() == false) &&
             (container.KeyCmpLessEqual(scan_itr->first, index_high_key));
         scan_itr++) {
      result.push_back(scan_itr->second);
    }
  }  // if is full scan

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance()->IncrementIndexReads(
        result.size(), metadata);
  }

  return;
}

/*
 * ScanLimit() - Scan the index with predicate and limit/offset
 *
 * This function scans the index using the given index optimizer's low key and
 * high key. In addition to merely doing the scan, it checks scan direction
 * and uses either begin() or end() iterator to scan the index, and stops
 * after offset + limit elements are scanned, and limit elements are finally
 * returned
 */
BWTREE_TEMPLATE_ARGUMENTS
void BWTREE_INDEX_TYPE::ScanLimit(
    const std::vector<type::Value> &value_list,
    const std::vector<oid_t> &tuple_column_id_list,
    const std::vector<ExpressionType> &expr_list,
    ScanDirectionType scan_direction, std::vector<ValueType> &result,
    const ConjunctionScanPredicate *csp_p, uint64_t limit, uint64_t offset) {

  // Only work with limit == 1 and offset == 0
  // Because that gets translated to "min"
  // But still since we could not access tuples in the table
  // the index just fetches the first qualified key without further checking
  // including checking for non-exact bounds!!!
  if (csp_p->IsPointQuery() == false && limit == 1 && offset == 0) {
    if (scan_direction == SCAN_DIRECTION_TYPE_FORWARD) {
      const storage::Tuple *low_key_p = csp_p->GetLowKey();
      const storage::Tuple *high_key_p = csp_p->GetHighKey();

      LOG_TRACE(
          "ScanLimit() special case (limit = 1; offset = 0; ASCENDING): %s",
          low_key_p->GetInfo().c_str());

      KeyType index_low_key;
      KeyType index_high_key;
      index_low_key.SetFromKey(low_key_p);
      index_high_key.SetFromKey(high_key_p);

      auto scan_itr = container.Begin(index_low_key);
      if ((scan_itr.IsEnd() == false) &&
          (container.KeyCmpLessEqual(scan_itr->first, index_high_key))) {

        result.push_back(scan_itr->second);
      }

      // If the passing is forward and limit 1, return 1 tuple
      return;
    }
  }

  Scan(value_list, tuple_column_id_list, expr_list, scan_direction, result,
       csp_p);

  return;
}

BWTREE_TEMPLATE_ARGUMENTS
void BWTREE_INDEX_TYPE::ScanAllKeys(std::vector<ValueType> &result) {
  auto it = container.Begin();

  // scan all entries
  while (it.IsEnd() == false) {
    result.push_back(it->second);
    it++;
  }

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance()->IncrementIndexReads(
        result.size(), metadata);
  }
  return;
}

BWTREE_TEMPLATE_ARGUMENTS
void BWTREE_INDEX_TYPE::ScanKey(const storage::Tuple *key,
                                std::vector<ValueType> &result) {
  KeyType index_key;
  index_key.SetFromKey(key);

  // This function in BwTree fills a given vector
  container.GetValue(index_key, result);

  if (FLAGS_stats_mode != STATS_TYPE_INVALID) {
    stats::BackendStatsContext::GetInstance()->IncrementIndexReads(
        result.size(), metadata);
  }

  return;
}

BWTREE_TEMPLATE_ARGUMENTS
std::string BWTREE_INDEX_TYPE::GetTypeName() const { return "BWTree"; }

// IMPORTANT: Make sure you don't exceed CompactIntegerKey_MAX_SLOTS

template class BWTreeIndex<CompactIntsKey<1>, ItemPointer *,
                           CompactIntsComparator<1>,
                           CompactIntsEqualityChecker<1>, CompactIntsHasher<1>,
                           ItemPointerComparator, ItemPointerHashFunc>;
template class BWTreeIndex<CompactIntsKey<2>, ItemPointer *,
                           CompactIntsComparator<2>,
                           CompactIntsEqualityChecker<2>, CompactIntsHasher<2>,
                           ItemPointerComparator, ItemPointerHashFunc>;
template class BWTreeIndex<CompactIntsKey<3>, ItemPointer *,
                           CompactIntsComparator<3>,
                           CompactIntsEqualityChecker<3>, CompactIntsHasher<3>,
                           ItemPointerComparator, ItemPointerHashFunc>;
template class BWTreeIndex<CompactIntsKey<4>, ItemPointer *,
                           CompactIntsComparator<4>,
                           CompactIntsEqualityChecker<4>, CompactIntsHasher<4>,
                           ItemPointerComparator, ItemPointerHashFunc>;

// Generic key
template class BWTreeIndex<GenericKey<4>, ItemPointer *,
                           FastGenericComparator<4>, GenericEqualityChecker<4>,
                           GenericHasher<4>, ItemPointerComparator,
                           ItemPointerHashFunc>;
template class BWTreeIndex<GenericKey<8>, ItemPointer *,
                           FastGenericComparator<8>, GenericEqualityChecker<8>,
                           GenericHasher<8>, ItemPointerComparator,
                           ItemPointerHashFunc>;
template class BWTreeIndex<GenericKey<16>, ItemPointer *,
                           FastGenericComparator<16>,
                           GenericEqualityChecker<16>, GenericHasher<16>,
                           ItemPointerComparator, ItemPointerHashFunc>;
template class BWTreeIndex<GenericKey<64>, ItemPointer *,
                           FastGenericComparator<64>,
                           GenericEqualityChecker<64>, GenericHasher<64>,
                           ItemPointerComparator, ItemPointerHashFunc>;
template class BWTreeIndex<GenericKey<256>, ItemPointer *,
                           FastGenericComparator<256>,
                           GenericEqualityChecker<256>, GenericHasher<256>,
                           ItemPointerComparator, ItemPointerHashFunc>;

// Tuple key
template class BWTreeIndex<TupleKey, ItemPointer *, TupleKeyComparator,
                           TupleKeyEqualityChecker, TupleKeyHasher,
                           ItemPointerComparator, ItemPointerHashFunc>;

}  // End index namespace
}  // End peloton namespace
<|endoftext|>


<commit_before>#ifdef WII

#include "joystick.h"

#include <ogc/pad.h>
#include <wiiuse/wpad.h>

void WiiJoystick::poll(){
    PAD_ScanPads();
    WPAD_ScanPads();
}

JoystickInput WiiJoystick::readAll(){
    JoystickInput input;
    // Number passed should be a port 1-4 I believe same with gc pad this can be modified later for multiplayer
    u32 held = WPAD_ButtonsHeld(0);

    // WIIMOTE for now, we can add in nunchuck and classic later
    if(held & WPAD_BUTTON_HOME){
        //input.button7 = true;
    } else if(held & WPAD_BUTTON_1){
        input.button1 = true;
    } else if(held & WPAD_BUTTON_2){
        input.button2 = true;
    } else if(held & WPAD_BUTTON_A){
    } else if(held & WPAD_BUTTON_B){

    } else if(held & WPAD_BUTTON_MINUS){
        input.button4 = true;
    } else if(held & WPAD_BUTTON_PLUS){
        input.button3 = true;
    } else if(held & WPAD_BUTTON_UP){
        input.left = true;
    } else if(held & WPAD_BUTTON_DOWN){
        input.right = true;
    } else if(held & WPAD_BUTTON_LEFT){
        input.down = true;
    } else if(held & WPAD_BUTTON_RIGHT){
        input.up = true;
    }

    // Gamecube Pad of course this assumes in the first position
    u16 gcheld = PAD_ButtonsHeld(0);
    if(gcheld & PAD_BUTTON_A){
        input.button1 = true;
    } else if(gcheld & PAD_BUTTON_B){
        input.button2 = true;
    } else if(gcheld & PAD_BUTTON_Y){
        input.button4 = true;
    } else if(gcheld & PAD_BUTTON_X){
        input.button3 = true;
    } else if(gcheld & PAD_BUTTON_UP){
        input.up = true;
    } else if(gcheld & PAD_BUTTON_DOWN){
        input.down = true;
    } else if(gcheld & PAD_BUTTON_LEFT){
        input.left = true;
    } else if(gcheld & PAD_BUTTON_RIGHT){
        input.right = true;
    } else if(gcheld & PAD_BUTTON_START){
        // enter
    } else if(gcheld & PAD_BUTTON_MENU){
        // esc
    }

    return input;
}

WiiJoystick::~WiiJoystick(){
    WPAD_Shutdown();
}

WiiJoystick::WiiJoystick(){
    WPAD_Init();
    PAD_Init();
}

#endif
<commit_msg>Add in information for wiimote with attachements.<commit_after>#ifdef WII

#include "joystick.h"

#include <ogc/pad.h>
#include <wiiuse/wpad.h>

void WiiJoystick::poll(){
    PAD_ScanPads();
    WPAD_ScanPads();
}

JoystickInput WiiJoystick::readAll(){
    JoystickInput input;
    // Number passed should be a port 1-4 I believe same with gc pad this can be modified later for multiplayer

    // Wii data
    WPADData * wpad;
    wpad = WPAD_Data(0);

    // Gamecube
    u16 gcheld = PAD_ButtonsHeld(0);

    // Wii controller
    if (wpad->exp.type == WPAD_EXP_CLASSIC){
        // Classic controller
        if(wpad->btns_h & WPAD_CLASSIC_BUTTON_UP){
            input.up = true;
        }
        if(wpad->btns_h & WPAD_CLASSIC_BUTTON_DOWN){
            input.down = true;
        }
        if(wpad->btns_h & WPAD_CLASSIC_BUTTON_LEFT){
            input.left = true;
        }
        if(wpad->btns_h & WPAD_CLASSIC_BUTTON_RIGHT){
            input.right = true;
        }
    } else if (wpad->exp.type == WPAD_EXP_NUNCHUK){
        // With nunchuck
        if(wpad->exp.nunchuk.js.pos.y >= 0xB0){
            input.up = true;
        }
        if(wpad->exp.nunchuk.js.pos.y <= 0x40){
            input.down = true;
        }
        if(wpad->exp.nunchuk.js.pos.x <= 0x40){
            input.left = true;
        }
        if(wpad->exp.nunchuk.js.pos.x >= 0xB0){
            input.right = true;
        }
    } else {
        // No attachment
        if(wpad->btns_h & WPAD_BUTTON_UP){
            if(wpad->ir.valid){
                input.up = true;
            } else {
                input.left = true;
            }
        }
        if(wpad->btns_h & WPAD_BUTTON_DOWN){
            if(wpad->ir.valid){
                input.down = true;
            } else {
                input.right = true;
            }
        }
        if(wpad->btns_h & WPAD_BUTTON_LEFT){
            if(wpad->ir.valid){
                input.left = true;
            } else {
                input.down = true;
            }
        }
        if(wpad->btns_h & WPAD_BUTTON_RIGHT){
            if(wpad->ir.valid){
                input.right = true;
            } else {
                input.up = true;
            }
        }
    }

    // Gamecube controller
    if(gcheld & PAD_BUTTON_UP){
        input.up = true;
    }
    if(gcheld & PAD_BUTTON_DOWN){
        input.down = true;
    }
    if(gcheld & PAD_BUTTON_LEFT){
        input.left = true;
    }
    if(gcheld & PAD_BUTTON_RIGHT){
        input.right = true;
    }

    // Check all input buttons
    if (wpad->btns_h & WPAD_CLASSIC_BUTTON_X || wpad->btns_h & WPAD_BUTTON_1 || gcheld & PAD_BUTTON_X){
        input.button1 = true;
    }
    if (wpad->btns_h & WPAD_CLASSIC_BUTTON_Y || wpad->btns_h & WPAD_BUTTON_2 || gcheld & PAD_BUTTON_Y){
        input.button2 = true;
    }
    if (wpad->btns_h & WPAD_CLASSIC_BUTTON_A || wpad->btns_h & WPAD_BUTTON_A || gcheld & PAD_BUTTON_A){
        input.button3 = true;
    }
    if (wpad->btns_h & WPAD_CLASSIC_BUTTON_B || wpad->btns_h & WPAD_BUTTON_B || gcheld & PAD_BUTTON_B){
        input.button4 = true;
    }
    if (wpad->btns_h & WPAD_CLASSIC_BUTTON_PLUS || wpad->btns_h & WPAD_BUTTON_PLUS || gcheld & PAD_BUTTON_START){
        // enter
    }
    if (wpad->btns_h & WPAD_CLASSIC_BUTTON_HOME || wpad->btns_h & WPAD_BUTTON_HOME || gcheld & PAD_BUTTON_MENU){
        // esc
    }
    if (wpad->btns_h & WPAD_CLASSIC_BUTTON_MINUS || wpad->btns_h & WPAD_BUTTON_MINUS){
        // ?
    }

    return input;
}

WiiJoystick::~WiiJoystick(){
    WPAD_Shutdown();
}

WiiJoystick::WiiJoystick(){
    WPAD_Init();
    PAD_Init();
}

#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 * Copyright (c) 2019, Acer Yun-Tse Yang All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * 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.
 *
 ******************************************************************************/
#include <type_traits>
#include <utility>

namespace sqlite3cpp {
namespace detail {

template <int>
struct placeholder_tmpl {};

template<int... Ints>
using indexes = std::integer_sequence<int, Ints...>;

template<int Max>
using make_indexes_t = std::make_integer_sequence<int, Max>;
}
}  // namespace sqlite3cpp::detail

// custome placeholders
namespace std {
template <int N>
struct is_placeholder<sqlite3cpp::detail::placeholder_tmpl<N>>
    : integral_constant<int, N + 1> {};
}

namespace sqlite3cpp {
namespace detail {

/**
 * tuple enumerate
 */
template <class F, class Tuple, int... I>
constexpr decltype(auto) enumerate_impl(F &&f, Tuple &&t,
                                        std::integer_sequence<int, I...>) {
  return (
      std::invoke(std::forward<F>(f), I, std::get<I>(std::forward<Tuple>(t))),
      ...);
}

template <class F, class Tuple>
constexpr decltype(auto) enumerate(F &&f, Tuple &&t) {
  return detail::enumerate_impl(
      std::forward<F>(f), std::forward<Tuple>(t),
      std::make_integer_sequence<
          int, std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
}

/**
 * Helpers for retrieve column values.
 */
inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *, int index,
                            int &val) {
  val = sqlite3_column_int(stmt, index);
}

inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *, int index,
                            int64_t &val) {
  val = sqlite3_column_int64(stmt, index);
}

inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *, int index,
                            double &val) {
  val = sqlite3_column_double(stmt, index);
}

inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *db, int index,
                            std::string &val) {
  char const* res = (char const *)sqlite3_column_text(stmt, index);
  if (!res) {
    int ec = sqlite3_errcode(db);
    if (ec != SQLITE_OK)
      throw error(ec);
  }
  val.assign(res, sqlite3_column_bytes(stmt, index));
}

inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *db, int index,
                            std::string_view &val) {
  char const *res = (char const *)sqlite3_column_text(stmt, index);
  if (!res) {
    int ec = sqlite3_errcode(db);
    if (ec != SQLITE_OK)
      throw error(ec);
  }
  val = std::string_view{
      (char const *)sqlite3_column_text(stmt, index),
      (std::string_view::size_type)sqlite3_column_bytes(stmt, index)};
}

inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *db, int index,
                            std::optional<std::string> &val) {
  char const* res = (char const *)sqlite3_column_text(stmt, index);
  if (!res) {
    int ec = sqlite3_errcode(db);
    if (ec != SQLITE_OK)
      val.reset();
  }
  val = std::string{res,
                    (std::string::size_type)sqlite3_column_bytes(stmt, index)};
}

inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *db, int index,
                            std::optional<std::string_view> &val) {
  char const *res = (char const *)sqlite3_column_text(stmt, index);
  if (!res) {
    int ec = sqlite3_errcode(db);
    if (ec != SQLITE_OK)
      val.reset();
  }
  val = std::string_view{
      res, (std::string_view::size_type)sqlite3_column_bytes(stmt, index)};
}

/*
 * Helpers for binding values to sqlite3_stmt.
 */
inline void bind_to_stmt(sqlite3_stmt *stmt, int i) {}

inline int bind_val(sqlite3_stmt *stmt, int index, int val) {
  return sqlite3_bind_int(stmt, index, val);
}

inline int bind_val(sqlite3_stmt *stmt, int index, double val) {
  return sqlite3_bind_double(stmt, index, val);
}

inline int bind_val(sqlite3_stmt *stmt, int index, std::string const &val) {
  return sqlite3_bind_text(stmt, index, val.c_str(), val.size(), SQLITE_STATIC);
}

inline int bind_val(sqlite3_stmt *stmt, int index, std::string_view const &val) {
  return sqlite3_bind_text(stmt, index, val.data(), val.size(), SQLITE_STATIC);
}

inline int bind_val(sqlite3_stmt *stmt, int index, char const *val) {
  return sqlite3_bind_text(stmt, index, val, -1, SQLITE_STATIC);
}

inline int bind_val(sqlite3_stmt *stmt, int index, std::nullptr_t _) {
  return sqlite3_bind_null(stmt, index);
}

template <typename T, typename... Args>
void bind_to_stmt(sqlite3_stmt *stmt, int index, T &&val, Args &&... args) {
  int ec = 0;
  if (0 != (ec = bind_val(stmt, index, std::forward<T>(val)))) throw error(ec);
  bind_to_stmt(stmt, index + 1, std::forward<Args>(args)...);
}

/**
 * Helpers for converting value from sqlite3_value.
 */
template <typename T>
struct Type {};

inline int get(Type<int>, sqlite3_value **v, int const index) {
  return sqlite3_value_int(v[index]);
}

inline int64_t get(Type<int64_t>, sqlite3_value **v, int const index) {
  return sqlite3_value_int64(v[index]);
}

inline double get(Type<double>, sqlite3_value **v, int const index) {
  return sqlite3_value_double(v[index]);
}

inline std::string get(Type<std::string>, sqlite3_value **v, int const index) {
  return std::string((char const *)sqlite3_value_text(v[index]),
                     (size_t)sqlite3_value_bytes(v[index]));
}

inline std::string_view get(Type<std::string_view>, sqlite3_value **v, int const index) {
  return std::string_view((char const *)sqlite3_value_text(v[index]),
                          (size_t)sqlite3_value_bytes(v[index]));
}

/**
 * Helpers for setting result of scalar functions.
 */
inline void result(int val, sqlite3_context *ctx) {
  sqlite3_result_int(ctx, val);
}

inline void result(int64_t val, sqlite3_context *ctx) {
  sqlite3_result_int64(ctx, val);
}

inline void result(double val, sqlite3_context *ctx) {
  sqlite3_result_double(ctx, val);
}

inline void result(std::string const &val, sqlite3_context *ctx) {
  sqlite3_result_text(ctx, val.c_str(), val.size(), SQLITE_TRANSIENT);
}

/**
 * Magic for typesafe invoking lambda/std::function from sqlite3
 * (registered via sqlite3_create_function).
 */
template <typename R, typename... Args, int... Is>
R invoke(std::function<R(Args...)> func, int argc, sqlite3_value **argv,
         indexes<Is...>) {
  // TODO Check argc
  // Expand argv per index
  return func(get(Type<Args>{}, argv, Is)...);
}

template <typename R, typename... Args>
R invoke(std::function<R(Args...)> func, int argc, sqlite3_value **argv) {
  return invoke(func, argc, argv, make_indexes_t<sizeof...(Args)>{});
}

template <typename R, typename... Args>
database::xfunc_t make_invoker(std::function<R(Args...)> &&func) {
  return [func](sqlite3_context *ctx, int argc, sqlite3_value **argv) {
    result(invoke(func, argc, argv), ctx);
  };
}

template <typename... Args>
database::xfunc_t make_invoker(std::function<void(Args...)> &&func) {
  return [func](sqlite3_context *ctx, int argc, sqlite3_value **argv) {
    invoke(func, argc, argv);
  };
}

/**
 * Function traits for supporting lambda.
 */

// For generic types that are functors, delegate to its 'operator()'
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())> {};

// for pointers to member function
template <typename C, typename R, typename... Args>
struct function_traits<R (C::*)(Args...)> {
  typedef std::function<R(Args...)> f_type;
  static const size_t arity = sizeof...(Args);
};

// for pointers to const member function
template <typename C, typename R, typename... Args>
struct function_traits<R (C::*)(Args...) const> {
  typedef std::function<R(Args...)> f_type;
  static const size_t arity = sizeof...(Args);
};

// for function pointers
template <typename R, typename... Args>
struct function_traits<R (*)(Args...)> {
  typedef std::function<R(Args...)> f_type;
  static const size_t arity = sizeof...(Args);
};

/**
 * Member function binder helpers (auto expand by passed function prototype)
 */
template <typename F, typename C, int... Is>
typename function_traits<F>::f_type bind_this(F f, C *this_, indexes<Is...>) {
  return std::bind(f, this_, placeholder_tmpl<Is>{}...);
}

template <typename F, typename C>
typename function_traits<F>::f_type bind_this(F f, C *this_) {
  using traits = function_traits<F>;
  return bind_this(f, this_, make_indexes_t<traits::arity>{});
}
}
}  // namespace sqlite3cpp::detail

namespace sqlite3cpp {

/**
 * row impl
 */
template <typename... Cols>
std::tuple<Cols...> row::to() const {
  // TODO: Report errors
  std::tuple<Cols...> result;
  detail::enumerate(
      [this](int index, auto &&tuple_value) {
        detail::get_col_val_aux(m_stmt, m_db, index, tuple_value);
      },
      result);
  return result;
}

/**
 * cursor impl
 */
template <typename... Args>
cursor &cursor::execute(std::string const &sql, Args &&... args) {
  sqlite3_stmt *stmt = 0;
  int ec = 0;

  if (0 != (ec = sqlite3_prepare_v2(m_db, sql.c_str(), sql.size(), &stmt, 0)))
    throw error(ec);

  m_stmt.reset(stmt);
  detail::bind_to_stmt(m_stmt.get(), 1, std::forward<Args>(args)...);
  step();
  return *this;
}

/**
 * database impl
 */

template <typename... Args>
cursor database::execute(std::string const &sql, Args &&... args) {
  cursor c = make_cursor();
  c.execute(sql, std::forward<Args>(args)...);
  return c;
}

template <typename FUNC>
void database::create_scalar(std::string const &name, FUNC func, int flags) {
  using traits = detail::function_traits<FUNC>;

  auto *xfunc_ptr =
      new xfunc_t(detail::make_invoker(typename traits::f_type(func)));

  int ec = 0;
  if (0 != (ec = sqlite3_create_function_v2(
                m_db.get(), name.c_str(), (int)traits::arity, flags,
                (void *)xfunc_ptr, &database::forward, 0, 0, &dispose))) {
    delete xfunc_ptr;
    throw error(ec);
  }
}

template <typename AG>
void database::create_aggregate(std::string const &name, int flags) {
  using detail::make_invoker;
  using detail::bind_this;
  using detail::result;
  using traits = detail::function_traits<decltype(&AG::step)>;

  aggregate_wrapper_t *wrapper = new aggregate_wrapper_t;
  AG *inst = new AG;
  wrapper->reset = [inst]() { *inst = AG(); };
  wrapper->release = [inst]() { delete inst; };
  wrapper->step = make_invoker(bind_this(&AG::step, inst));
  wrapper->fin = [inst](sqlite3_context *ctx) {
    result(inst->finalize(), ctx);
  };

  int ec = 0;
  if (0 != (ec = sqlite3_create_function_v2(
                m_db.get(), name.c_str(), (int)traits::arity, flags,
                (void *)wrapper, 0, &step_ag, &final_ag, &dispose_ag))) {
    delete inst;
    delete wrapper;
    throw error(ec);
  }
}

}  // namespace sqlite3cpp
<commit_msg>Reset aggregate instance with destructor and placement new.<commit_after>/*****************************************************************************
 * Copyright (c) 2019, Acer Yun-Tse Yang All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * 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.
 *
 ******************************************************************************/
#include <type_traits>
#include <utility>

namespace sqlite3cpp {
namespace detail {

template <int>
struct placeholder_tmpl {};

template<int... Ints>
using indexes = std::integer_sequence<int, Ints...>;

template<int Max>
using make_indexes_t = std::make_integer_sequence<int, Max>;
}
}  // namespace sqlite3cpp::detail

// custome placeholders
namespace std {
template <int N>
struct is_placeholder<sqlite3cpp::detail::placeholder_tmpl<N>>
    : integral_constant<int, N + 1> {};
}

namespace sqlite3cpp {
namespace detail {

/**
 * tuple enumerate
 */
template <class F, class Tuple, int... I>
constexpr decltype(auto) enumerate_impl(F &&f, Tuple &&t,
                                        std::integer_sequence<int, I...>) {
  return (
      std::invoke(std::forward<F>(f), I, std::get<I>(std::forward<Tuple>(t))),
      ...);
}

template <class F, class Tuple>
constexpr decltype(auto) enumerate(F &&f, Tuple &&t) {
  return detail::enumerate_impl(
      std::forward<F>(f), std::forward<Tuple>(t),
      std::make_integer_sequence<
          int, std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
}

/**
 * Helpers for retrieve column values.
 */
inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *, int index,
                            int &val) {
  val = sqlite3_column_int(stmt, index);
}

inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *, int index,
                            int64_t &val) {
  val = sqlite3_column_int64(stmt, index);
}

inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *, int index,
                            double &val) {
  val = sqlite3_column_double(stmt, index);
}

inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *db, int index,
                            std::string &val) {
  char const* res = (char const *)sqlite3_column_text(stmt, index);
  if (!res) {
    int ec = sqlite3_errcode(db);
    if (ec != SQLITE_OK)
      throw error(ec);
  }
  val.assign(res, sqlite3_column_bytes(stmt, index));
}

inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *db, int index,
                            std::string_view &val) {
  char const *res = (char const *)sqlite3_column_text(stmt, index);
  if (!res) {
    int ec = sqlite3_errcode(db);
    if (ec != SQLITE_OK)
      throw error(ec);
  }
  val = std::string_view{
      (char const *)sqlite3_column_text(stmt, index),
      (std::string_view::size_type)sqlite3_column_bytes(stmt, index)};
}

inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *db, int index,
                            std::optional<std::string> &val) {
  char const* res = (char const *)sqlite3_column_text(stmt, index);
  if (!res) {
    int ec = sqlite3_errcode(db);
    if (ec != SQLITE_OK)
      val.reset();
  }
  val = std::string{res,
                    (std::string::size_type)sqlite3_column_bytes(stmt, index)};
}

inline void get_col_val_aux(sqlite3_stmt *stmt, sqlite3 *db, int index,
                            std::optional<std::string_view> &val) {
  char const *res = (char const *)sqlite3_column_text(stmt, index);
  if (!res) {
    int ec = sqlite3_errcode(db);
    if (ec != SQLITE_OK)
      val.reset();
  }
  val = std::string_view{
      res, (std::string_view::size_type)sqlite3_column_bytes(stmt, index)};
}

/*
 * Helpers for binding values to sqlite3_stmt.
 */
inline void bind_to_stmt(sqlite3_stmt *stmt, int i) {}

inline int bind_val(sqlite3_stmt *stmt, int index, int val) {
  return sqlite3_bind_int(stmt, index, val);
}

inline int bind_val(sqlite3_stmt *stmt, int index, double val) {
  return sqlite3_bind_double(stmt, index, val);
}

inline int bind_val(sqlite3_stmt *stmt, int index, std::string const &val) {
  return sqlite3_bind_text(stmt, index, val.c_str(), val.size(), SQLITE_STATIC);
}

inline int bind_val(sqlite3_stmt *stmt, int index, std::string_view const &val) {
  return sqlite3_bind_text(stmt, index, val.data(), val.size(), SQLITE_STATIC);
}

inline int bind_val(sqlite3_stmt *stmt, int index, char const *val) {
  return sqlite3_bind_text(stmt, index, val, -1, SQLITE_STATIC);
}

inline int bind_val(sqlite3_stmt *stmt, int index, std::nullptr_t _) {
  return sqlite3_bind_null(stmt, index);
}

template <typename T, typename... Args>
void bind_to_stmt(sqlite3_stmt *stmt, int index, T &&val, Args &&... args) {
  int ec = 0;
  if (0 != (ec = bind_val(stmt, index, std::forward<T>(val)))) throw error(ec);
  bind_to_stmt(stmt, index + 1, std::forward<Args>(args)...);
}

/**
 * Helpers for converting value from sqlite3_value.
 */
template <typename T>
struct Type {};

inline int get(Type<int>, sqlite3_value **v, int const index) {
  return sqlite3_value_int(v[index]);
}

inline int64_t get(Type<int64_t>, sqlite3_value **v, int const index) {
  return sqlite3_value_int64(v[index]);
}

inline double get(Type<double>, sqlite3_value **v, int const index) {
  return sqlite3_value_double(v[index]);
}

inline std::string get(Type<std::string>, sqlite3_value **v, int const index) {
  return std::string((char const *)sqlite3_value_text(v[index]),
                     (size_t)sqlite3_value_bytes(v[index]));
}

inline std::string_view get(Type<std::string_view>, sqlite3_value **v, int const index) {
  return std::string_view((char const *)sqlite3_value_text(v[index]),
                          (size_t)sqlite3_value_bytes(v[index]));
}

/**
 * Helpers for setting result of scalar functions.
 */
inline void result(int val, sqlite3_context *ctx) {
  sqlite3_result_int(ctx, val);
}

inline void result(int64_t val, sqlite3_context *ctx) {
  sqlite3_result_int64(ctx, val);
}

inline void result(double val, sqlite3_context *ctx) {
  sqlite3_result_double(ctx, val);
}

inline void result(std::string const &val, sqlite3_context *ctx) {
  sqlite3_result_text(ctx, val.c_str(), val.size(), SQLITE_TRANSIENT);
}

/**
 * Magic for typesafe invoking lambda/std::function from sqlite3
 * (registered via sqlite3_create_function).
 */
template <typename R, typename... Args, int... Is>
R invoke(std::function<R(Args...)> func, int argc, sqlite3_value **argv,
         indexes<Is...>) {
  // TODO Check argc
  // Expand argv per index
  return func(get(Type<Args>{}, argv, Is)...);
}

template <typename R, typename... Args>
R invoke(std::function<R(Args...)> func, int argc, sqlite3_value **argv) {
  return invoke(func, argc, argv, make_indexes_t<sizeof...(Args)>{});
}

template <typename R, typename... Args>
database::xfunc_t make_invoker(std::function<R(Args...)> &&func) {
  return [func](sqlite3_context *ctx, int argc, sqlite3_value **argv) {
    result(invoke(func, argc, argv), ctx);
  };
}

template <typename... Args>
database::xfunc_t make_invoker(std::function<void(Args...)> &&func) {
  return [func](sqlite3_context *ctx, int argc, sqlite3_value **argv) {
    invoke(func, argc, argv);
  };
}

/**
 * Function traits for supporting lambda.
 */

// For generic types that are functors, delegate to its 'operator()'
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())> {};

// for pointers to member function
template <typename C, typename R, typename... Args>
struct function_traits<R (C::*)(Args...)> {
  typedef std::function<R(Args...)> f_type;
  static const size_t arity = sizeof...(Args);
};

// for pointers to const member function
template <typename C, typename R, typename... Args>
struct function_traits<R (C::*)(Args...) const> {
  typedef std::function<R(Args...)> f_type;
  static const size_t arity = sizeof...(Args);
};

// for function pointers
template <typename R, typename... Args>
struct function_traits<R (*)(Args...)> {
  typedef std::function<R(Args...)> f_type;
  static const size_t arity = sizeof...(Args);
};

/**
 * Member function binder helpers (auto expand by passed function prototype)
 */
template <typename F, typename C, int... Is>
typename function_traits<F>::f_type bind_this(F f, C *this_, indexes<Is...>) {
  return std::bind(f, this_, placeholder_tmpl<Is>{}...);
}

template <typename F, typename C>
typename function_traits<F>::f_type bind_this(F f, C *this_) {
  using traits = function_traits<F>;
  return bind_this(f, this_, make_indexes_t<traits::arity>{});
}
}
}  // namespace sqlite3cpp::detail

namespace sqlite3cpp {

/**
 * row impl
 */
template <typename... Cols>
std::tuple<Cols...> row::to() const {
  // TODO: Report errors
  std::tuple<Cols...> result;
  detail::enumerate(
      [this](int index, auto &&tuple_value) {
        detail::get_col_val_aux(m_stmt, m_db, index, tuple_value);
      },
      result);
  return result;
}

/**
 * cursor impl
 */
template <typename... Args>
cursor &cursor::execute(std::string const &sql, Args &&... args) {
  sqlite3_stmt *stmt = 0;
  int ec = 0;

  if (0 != (ec = sqlite3_prepare_v2(m_db, sql.c_str(), sql.size(), &stmt, 0)))
    throw error(ec);

  m_stmt.reset(stmt);
  detail::bind_to_stmt(m_stmt.get(), 1, std::forward<Args>(args)...);
  step();
  return *this;
}

/**
 * database impl
 */

template <typename... Args>
cursor database::execute(std::string const &sql, Args &&... args) {
  cursor c = make_cursor();
  c.execute(sql, std::forward<Args>(args)...);
  return c;
}

template <typename FUNC>
void database::create_scalar(std::string const &name, FUNC func, int flags) {
  using traits = detail::function_traits<FUNC>;

  auto *xfunc_ptr =
      new xfunc_t(detail::make_invoker(typename traits::f_type(func)));

  int ec = 0;
  if (0 != (ec = sqlite3_create_function_v2(
                m_db.get(), name.c_str(), (int)traits::arity, flags,
                (void *)xfunc_ptr, &database::forward, 0, 0, &dispose))) {
    delete xfunc_ptr;
    throw error(ec);
  }
}

template <typename AG>
void database::create_aggregate(std::string const &name, int flags) {
  using detail::make_invoker;
  using detail::bind_this;
  using detail::result;
  using traits = detail::function_traits<decltype(&AG::step)>;

  aggregate_wrapper_t *wrapper = new aggregate_wrapper_t;
  AG *inst = new AG;
  wrapper->reset = [inst]() {
    inst->~AG();
    new (inst) AG();
  };
  wrapper->release = [inst]() { delete inst; };
  wrapper->step = make_invoker(bind_this(&AG::step, inst));
  wrapper->fin = [inst](sqlite3_context *ctx) {
    result(inst->finalize(), ctx);
  };

  int ec = 0;
  if (0 != (ec = sqlite3_create_function_v2(
                m_db.get(), name.c_str(), (int)traits::arity, flags,
                (void *)wrapper, 0, &step_ag, &final_ag, &dispose_ag))) {
    delete inst;
    delete wrapper;
    throw error(ec);
  }
}

}  // namespace sqlite3cpp
<|endoftext|>


<commit_before>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * E131Plugin.cpp
 * The E1.31 plugin for ola
 * Copyright (C) 2007-2009 Simon Newton
 */

#include <stdlib.h>
#include <stdio.h>

#include <olad/PluginAdaptor.h>
#include <olad/Preferences.h>

#include "E131Plugin.h"
#include "E131Device.h"
#include "e131/CID.h"

/*
 * Entry point to this plugin
 */
extern "C" ola::AbstractPlugin* create(const ola::PluginAdaptor *adaptor) {
  return new ola::e131::E131Plugin(adaptor);
}

/*
 * Called when the plugin is unloaded
 */
extern "C" void destroy(ola::Plugin* plugin) {
  delete plugin;
}

namespace ola {
namespace e131 {

const string E131Plugin::PLUGIN_NAME = "E1.31 (DMX over ACN) Plugin";
const string E131Plugin::PLUGIN_PREFIX = "e131";
const string E131Plugin::DEVICE_NAME = "E1.31 (DMX over ACN) Device";
const string E131Plugin::CID_KEY = "cid";

/*
 * Start the plugin
 */
bool E131Plugin::StartHook() {
  CID cid = CID::FromString(m_preferences->GetValue(CID_KEY));

  m_device = new E131Device(this, DEVICE_NAME, cid, m_preferences,
                            m_plugin_adaptor);

  if (!m_device->Start()) {
    delete m_device;
    return false;
  }

  m_plugin_adaptor->RegisterDevice(m_device);
  return true;
}

/*
 * Stop the plugin
 */
bool E131Plugin::StopHook() {
  m_plugin_adaptor->UnregisterDevice(m_device);
  if (!m_device->Stop())
    return false;

  delete m_device;
  return true;
}

/*
 * Return the description for this plugin
 */
string E131Plugin::Description() const {
    return
"E1.31 (Streaming DMX over ACN) Plugin\n"
"----------------------------\n"
"\n"
"This plugin creates a single device with eight input and eight output ports.\n"
"\n"
"Each port can be assigned to a diffent E1.31 Universe.\n"
"\n"
"--- Config file : ola-e131.conf ---\n"
"\n"
"ip = a.b.c.d\n"
"The local ip address to use for multicasting.\n"
"\n"
"cid = 00010203-0405-0607-0809-0A0B0C0D0E0F\n"
"The CID to use for this device\n"
"\n";
}

/*
 * Load the plugin prefs and default to sensible values
 *
 */
bool E131Plugin::SetDefaultPreferences() {
  bool save = false;

  if (!m_preferences)
    return false;

  CID cid = CID::FromString(m_preferences->GetValue(CID_KEY));
  if (cid.IsNil()) {
    cid = CID::Generate();
    m_preferences->SetValue(CID_KEY, cid.ToString());
    m_preferences->Save();
  }

  // check if this saved correctly
  // we don't want to use it if null
  if (m_preferences->GetValue(CID_KEY) == "")
    return false;

  return true;
}

} // e131
} // ola
<commit_msg> * remove unused variable<commit_after>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * E131Plugin.cpp
 * The E1.31 plugin for ola
 * Copyright (C) 2007-2009 Simon Newton
 */

#include <stdlib.h>
#include <stdio.h>

#include <olad/PluginAdaptor.h>
#include <olad/Preferences.h>

#include "E131Plugin.h"
#include "E131Device.h"
#include "e131/CID.h"

/*
 * Entry point to this plugin
 */
extern "C" ola::AbstractPlugin* create(const ola::PluginAdaptor *adaptor) {
  return new ola::e131::E131Plugin(adaptor);
}

/*
 * Called when the plugin is unloaded
 */
extern "C" void destroy(ola::Plugin* plugin) {
  delete plugin;
}

namespace ola {
namespace e131 {

const string E131Plugin::PLUGIN_NAME = "E1.31 (DMX over ACN) Plugin";
const string E131Plugin::PLUGIN_PREFIX = "e131";
const string E131Plugin::DEVICE_NAME = "E1.31 (DMX over ACN) Device";
const string E131Plugin::CID_KEY = "cid";

/*
 * Start the plugin
 */
bool E131Plugin::StartHook() {
  CID cid = CID::FromString(m_preferences->GetValue(CID_KEY));

  m_device = new E131Device(this, DEVICE_NAME, cid, m_preferences,
                            m_plugin_adaptor);

  if (!m_device->Start()) {
    delete m_device;
    return false;
  }

  m_plugin_adaptor->RegisterDevice(m_device);
  return true;
}

/*
 * Stop the plugin
 */
bool E131Plugin::StopHook() {
  m_plugin_adaptor->UnregisterDevice(m_device);
  if (!m_device->Stop())
    return false;

  delete m_device;
  return true;
}

/*
 * Return the description for this plugin
 */
string E131Plugin::Description() const {
    return
"E1.31 (Streaming DMX over ACN) Plugin\n"
"----------------------------\n"
"\n"
"This plugin creates a single device with eight input and eight output ports.\n"
"\n"
"Each port can be assigned to a diffent E1.31 Universe.\n"
"\n"
"--- Config file : ola-e131.conf ---\n"
"\n"
"ip = a.b.c.d\n"
"The local ip address to use for multicasting.\n"
"\n"
"cid = 00010203-0405-0607-0809-0A0B0C0D0E0F\n"
"The CID to use for this device\n"
"\n";
}

/*
 * Load the plugin prefs and default to sensible values
 *
 */
bool E131Plugin::SetDefaultPreferences() {
  if (!m_preferences)
    return false;

  CID cid = CID::FromString(m_preferences->GetValue(CID_KEY));
  if (cid.IsNil()) {
    cid = CID::Generate();
    m_preferences->SetValue(CID_KEY, cid.ToString());
    m_preferences->Save();
  }

  // check if this saved correctly
  // we don't want to use it if null
  if (m_preferences->GetValue(CID_KEY) == "")
    return false;

  return true;
}

} // e131
} // ola
<|endoftext|>