<commit_before>#include "bvsd.h"

/** Main function, creates interactive loop. */
int main(const int argc, const char** argv)
{
	signal(SIGINT, mainSignal);
	signal(SIGSEGV, mainSignal);
	signal(SIGALRM, mainSignal);

	bvs = new BVS::BVS(argc, argv, &shutdownFunction);

	LOG(2, "loading modules!");
	bvs->loadModules();

	LOG(2, "connecting modules!");
	bvs->connectAllModules();

	LOG(2, "starting!");
	bvs->start(bvs->config.getValue<bool>("BVSD.interactive", true));

	bvs->run();

	std::string input;
	while (true)
	{
		std::getline(std::cin, input);
		if (std::cin.eof()) input = "q";

		if (input == "r" || input == "run" || input == "c" || input == "continue")
		{
			LOG(2, "RUN!!!");
			bvs->run();
		}
		else if (input.empty() || input == "s" || input == "step")
		{
			LOG(2, "STEP!!!");
			bvs->step();
		}
		else if (input == "p" || input == "pause")
		{
			LOG(2, "PAUSING!!!");
			bvs->pause();
		}
		else if (input.substr(0,2) == "hs" || input.substr(0, 7) == "hotswap")
		{
			size_t delimiter = input.find_first_of(" ");
			input.erase(0, delimiter+1);
			if (input.empty() || delimiter==std::string::npos) std::cout << "ERROR: no module ID given!" << std::endl;
			else bvs->hotSwap(input);
		}
		else if (input == "q" || input == "quit")
		{
			LOG(2, "quitting...");
			bvs->quit();
			LOG(2, "finished!");
			break;
		}
		else if (input == "h" || input == "help")
		{
			std::cout << "usage:" << std::endl;
			std::cout << "   r|run            run system until paused" << std::endl;
			std::cout << "   c|continue       same as run" << std::endl;
			std::cout << "   s|step           advance system by one step" << std::endl;
			std::cout << "   p|pause          pause(stop) system" << std::endl;
			std::cout << "   hs|hotswap <arg> HotSwap(TM) <moduleID>" << std::endl;
			std::cout << "   q|quit           shutdown system and quit" << std::endl;
			std::cout << "   h|help           show help" << std::endl;
		}
		else
		{
			std::cout << ">>> unknown command: " << input << std::endl << ">>> for help press 'h<enter>'!" << std::endl;
		}
	}

	delete bvs;

	return 0;
}

void mainSignal(int sig)
{
	switch (sig)
	{
		case SIGINT:
			LOG(2, "Caught 'Ctrl-C', quitting!");
			break;
		case SIGSEGV:
			LOG(2, "Caught segmentation fault...!");
			void *msgs[100];
			size_t size;
			size = backtrace(msgs, 100);
			fprintf(stderr, "\n\n\nCaught signal %d (%s)!\n\n", sig, strsignal(sig));
			char** messages;
			messages = backtrace_symbols(msgs, size);
			for (size_t i=2; i < size && messages != NULL; ++i)
				fprintf(stderr, "[bt]: (%lu) %s\n", i-2, messages[i]);
			free(messages);
			break;
		case SIGALRM:
			LOG(2, "Shutdown requested, quitting!");
			break;
	}

	if (sig==SIGSEGV)
	{
		signal(SIGSEGV, SIG_DFL);
		raise(SIGSEGV);
	}
	else
	{
		bvs->quit();
		delete bvs;
		exit(EXIT_FAILURE);
	}
}

void shutdownFunction()
{
	LOG(1,"daemon exit caused by bvs shutdown request!");
	bvs->quit();
	alarm(1); // SIGALRM after 1 second so all framework/module threads have a chance to quit
}

<commit_msg>daemon: fix (non-)interactive mode<commit_after>#include "bvsd.h"

/** Main function, creates interactive loop. */
int main(const int argc, const char** argv)
{
	signal(SIGINT, mainSignal);
	signal(SIGSEGV, mainSignal);
	signal(SIGALRM, mainSignal);

	bvs = new BVS::BVS(argc, argv, &shutdownFunction);

	LOG(2, "loading modules!");
	bvs->loadModules();

	LOG(2, "connecting modules!");
	bvs->connectAllModules();

	LOG(2, "starting!");
	if (bvs->config.getValue<bool>("BVSD.interactive", true)) {
		bvs->start();
		bvs->run();
		std::string input;
		while (true)
		{
			std::getline(std::cin, input);
			if (std::cin.eof()) input = "q";

			if (input == "r" || input == "run" || input == "c" || input == "continue")
			{
				LOG(2, "RUN!!!");
				bvs->run();
			}
			else if (input.empty() || input == "s" || input == "step")
			{
				LOG(2, "STEP!!!");
				bvs->step();
			}
			else if (input == "p" || input == "pause")
			{
				LOG(2, "PAUSING!!!");
				bvs->pause();
			}
			else if (input.substr(0,2) == "hs" || input.substr(0, 7) == "hotswap")
			{
				size_t delimiter = input.find_first_of(" ");
				input.erase(0, delimiter+1);
				if (input.empty() || delimiter==std::string::npos) std::cout << "ERROR: no module ID given!" << std::endl;
				else bvs->hotSwap(input);
			}
			else if (input == "q" || input == "quit")
			{
				LOG(2, "quitting...");
				bvs->quit();
				LOG(2, "finished!");
				break;
			}
			else if (input == "h" || input == "help")
			{
				std::cout << "usage:" << std::endl;
				std::cout << "   r|run            run system until paused" << std::endl;
				std::cout << "   c|continue       same as run" << std::endl;
				std::cout << "   s|step           advance system by one step" << std::endl;
				std::cout << "   p|pause          pause(stop) system" << std::endl;
				std::cout << "   hs|hotswap <arg> HotSwap(TM) <moduleID>" << std::endl;
				std::cout << "   q|quit           shutdown system and quit" << std::endl;
				std::cout << "   h|help           show help" << std::endl;
			}
			else
			{
				std::cout << ">>> unknown command: " << input << std::endl << ">>> for help press 'h<enter>'!" << std::endl;
			}
		}
	} else {
		bvs->start(false);
		bvs->run();
	}

	delete bvs;

	return 0;
}

void mainSignal(int sig)
{
	switch (sig)
	{
		case SIGINT:
			LOG(2, "Caught 'Ctrl-C', quitting!");
			break;
		case SIGSEGV:
			LOG(2, "Caught segmentation fault...!");
			void *msgs[100];
			size_t size;
			size = backtrace(msgs, 100);
			fprintf(stderr, "\n\n\nCaught signal %d (%s)!\n\n", sig, strsignal(sig));
			char** messages;
			messages = backtrace_symbols(msgs, size);
			for (size_t i=2; i < size && messages != NULL; ++i)
				fprintf(stderr, "[bt]: (%lu) %s\n", i-2, messages[i]);
			free(messages);
			break;
		case SIGALRM:
			LOG(2, "Shutdown requested, quitting!");
			break;
	}

	if (sig==SIGSEGV)
	{
		signal(SIGSEGV, SIG_DFL);
		raise(SIGSEGV);
	}
	else
	{
		bvs->quit();
		delete bvs;
		exit(EXIT_FAILURE);
	}
}

void shutdownFunction()
{
	LOG(1,"daemon exit caused by bvs shutdown request!");
	bvs->quit();
	alarm(1); // SIGALRM after 1 second so all framework/module threads have a chance to quit
}

<|endoftext|>


<commit_before>/* This file is part of VoltDB.
 * Copyright (C) 2008-2012 VoltDB Inc.
 *
 * VoltDB 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 3 of the License, or
 * (at your option) any later version.
 *
 * VoltDB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "indexcountexecutor.h"

#include "common/debuglog.h"
#include "common/common.h"
#include "common/tabletuple.h"
#include "common/FatalException.hpp"
#include "expressions/abstractexpression.h"
#include "expressions/expressionutil.h"
#include "plannodes/indexcountnode.h"
#include "storage/table.h"
#include "storage/tableiterator.h"
#include "storage/tablefactory.h"
#include "storage/temptable.h"
#include "storage/persistenttable.h"

using namespace voltdb;

bool IndexCountExecutor::p_init(AbstractPlanNode *abstractNode,
                                TempTableLimits* limits)
{
    VOLT_DEBUG("init IndexCount Executor");

    m_node = dynamic_cast<IndexCountPlanNode*>(abstractNode);
    assert(m_node);
    assert(m_node->getTargetTable());
    assert(m_node->getPredicate() == NULL);

    // Create output table based on output schema from the plan
    TupleSchema* schema = m_node->generateTupleSchema(false);
    int column_count = static_cast<int>(m_node->getOutputSchema().size());
    assert(column_count == 1);

    std::string* column_names = new std::string[column_count];
    column_names[0] = m_node->getOutputSchema()[0]->getColumnName();

    m_node->setOutputTable(TableFactory::getTempTable(m_node->databaseId(),
                                                      m_node->getTargetTable()->name(),
                                                      schema,
                                                      column_names,
                                                      limits));
    delete[] column_names;

    //
    // Make sure that we have search keys and that they're not null
    //
    m_numOfSearchkeys = (int)m_node->getSearchKeyExpressions().size();
    m_searchKeyBeforeSubstituteArrayPtr =
        boost::shared_array<AbstractExpression*>
    (new AbstractExpression*[m_numOfSearchkeys]);
    m_searchKeyBeforeSubstituteArray = m_searchKeyBeforeSubstituteArrayPtr.get();
    m_needsSubstituteSearchKeyPtr =
        boost::shared_array<bool>(new bool[m_numOfSearchkeys]);
    m_needsSubstituteSearchKey = m_needsSubstituteSearchKeyPtr.get();

    for (int ctr = 0; ctr < m_numOfSearchkeys; ctr++)
    {
        if (m_node->getSearchKeyExpressions()[ctr] == NULL)
        {
            VOLT_ERROR("The search key expression at position '%d' is NULL for"
                " PlanNode '%s'", ctr, m_node->debug().c_str());
            return false;
        }
        m_needsSubstituteSearchKeyPtr[ctr] =
            m_node->getSearchKeyExpressions()[ctr]->hasParameter();
        m_searchKeyBeforeSubstituteArrayPtr[ctr] =
            m_node->getSearchKeyExpressions()[ctr];
    }

    m_numOfEndkeys = (int)m_node->getEndKeyExpressions().size();
    if (m_numOfEndkeys != 0) {
        m_endKeyBeforeSubstituteArrayPtr =
            boost::shared_array<AbstractExpression*> (new AbstractExpression*[m_numOfEndkeys]);
        m_endKeyBeforeSubstituteArray = m_endKeyBeforeSubstituteArrayPtr.get();
        m_needsSubstituteEndKeyPtr =
            boost::shared_array<bool>(new bool[m_numOfEndkeys]);
        m_needsSubstituteEndKey = m_needsSubstituteEndKeyPtr.get();
        for (int ctr = 0; ctr < m_numOfEndkeys; ctr++)
        {
            if (m_node->getEndKeyExpressions()[ctr] == NULL) {
                VOLT_ERROR("The end key expression at position '%d' is NULL for"
                    " PlanNode '%s'", ctr, m_node->debug().c_str());
                return false;
            }
            m_needsSubstituteEndKeyPtr[ctr] =
                m_node->getEndKeyExpressions()[ctr]->hasParameter();
            m_endKeyBeforeSubstituteArrayPtr[ctr] =
                m_node->getEndKeyExpressions()[ctr];
        }
    }

    //
    // Initialize local variables
    //

    //output table should be temptable
    m_outputTable = static_cast<TempTable*>(m_node->getOutputTable());
    //target table should be persistenttable
    m_targetTable = static_cast<PersistentTable*>(m_node->getTargetTable());
    m_numOfColumns = static_cast<int>(m_outputTable->columnCount());

    assert(m_numOfColumns == 1);
    //
    // Grab the Index from our inner table
    // We'll throw an error if the index is missing
    //
    m_index = m_targetTable->index(m_node->getTargetIndexName());
    assert (m_index != NULL);

    // This index should have a true countable flag
    assert(m_index->is_countable_index_);

    m_searchKey = TableTuple(m_index->getKeySchema());
    m_searchKeyBackingStore = new char[m_index->getKeySchema()->tupleLength()];
    m_searchKey.moveNoHeader(m_searchKeyBackingStore);
    if (m_numOfEndkeys != 0) {
        m_endKey = TableTuple(m_index->getKeySchema());
        m_endKeyBackingStore = new char[m_index->getKeySchema()->tupleLength()];
        m_endKey.moveNoHeader(m_endKeyBackingStore);
    }

    // Miscellanous Information
    m_lookupType = m_node->getLookupType();
    if (m_numOfEndkeys != 0) {
        m_endType = m_node->getEndType();
    }

    // Need to move GTE to find (x,_) when doing a partial covering search.
    // the planner sometimes lies in this case: index_lookup_type_eq is incorrect.
    // Index_lookup_type_gte is necessary. Make the change here.
    if (m_lookupType == INDEX_LOOKUP_TYPE_EQ &&
        m_searchKey.getSchema()->columnCount() > m_numOfSearchkeys)
    {
        VOLT_TRACE("Setting lookup type to GTE for partial covering key.");
        m_lookupType = INDEX_LOOKUP_TYPE_GTE;
    }

    return true;
}

bool IndexCountExecutor::p_execute(const NValueArray &params)
{
    assert(m_node);
    assert(m_node == dynamic_cast<IndexCountPlanNode*>(m_abstractNode));
    assert(m_outputTable);
    assert(m_outputTable == static_cast<TempTable*>(m_node->getOutputTable()));
    assert(m_targetTable);
    assert(m_targetTable == m_node->getTargetTable());
    VOLT_DEBUG("IndexCount: %s.%s\n", m_targetTable->name().c_str(),
               m_index->getName().c_str());

    int activeNumOfSearchKeys = m_numOfSearchkeys;
    IndexLookupType localLookupType = m_lookupType;
    bool searchKeyUnderflow = false, endKeyOverflow = false;
    // Overflow cases that can return early without accessing the index need this
    // default 0 count as their result.
    TableTuple& tmptup = m_outputTable->tempTuple();
    tmptup.setNValue(0, ValueFactory::getBigIntValue( 0 ));
    TableTuple m_dummy;

    //
    // SEARCH KEY
    //
    m_searchKey.setAllNulls();
    VOLT_DEBUG("<Index Count>Initial (all null) search key: '%s'", m_searchKey.debugNoHeader().c_str());
    for (int ctr = 0; ctr < activeNumOfSearchKeys; ctr++) {
        if (m_needsSubstituteSearchKey[ctr]) {
            m_searchKeyBeforeSubstituteArray[ctr]->substitute(params);
        }
        NValue candidateValue = m_searchKeyBeforeSubstituteArray[ctr]->eval(&m_dummy, NULL);
        try {
            m_searchKey.setNValue(ctr, candidateValue);
        }
        catch (SQLException e) {
            // This next bit of logic handles underflow and overflow while
            // setting up the search keys.
            // e.g. TINYINT > 200 or INT <= 6000000000

            // re-throw if not an overflow or underflow
            // currently, it's expected to always be an overflow or underflow
            if ((e.getInternalFlags() & (SQLException::TYPE_OVERFLOW | SQLException::TYPE_UNDERFLOW)) == 0) {
                throw e;
            }

            // handle the case where this is a comparison, rather than equality match
            // comparison is the only place where the executor might return matching tuples
            // e.g. TINYINT < 1000 should return all values

            if ((localLookupType != INDEX_LOOKUP_TYPE_EQ) &&
                (ctr == (activeNumOfSearchKeys - 1))) {
                assert (localLookupType == INDEX_LOOKUP_TYPE_GT || localLookupType == INDEX_LOOKUP_TYPE_GTE);

                if (e.getInternalFlags() & SQLException::TYPE_OVERFLOW) {
                    m_outputTable->insertTuple(tmptup);
                    return true;
                } else if (e.getInternalFlags() & SQLException::TYPE_UNDERFLOW) {
                    searchKeyUnderflow = true;
                    break;
                } else {
                    throw e;
                }
            }
            // if a EQ comparision is out of range, then return no tuples
            else {
                m_outputTable->insertTuple(tmptup);
                return true;
            }
            break;
        }
    }
    assert(activeNumOfSearchKeys > 0);
    VOLT_TRACE("Search key after substitutions: '%s'", m_searchKey.debugNoHeader().c_str());

    if (m_numOfEndkeys != 0) {
        //
        // END KEY
        //
        m_endKey.setAllNulls();
        VOLT_DEBUG("Initial (all null) end key: '%s'", m_endKey.debugNoHeader().c_str());
        for (int ctr = 0; ctr < m_numOfEndkeys; ctr++) {
            if (m_needsSubstituteEndKey[ctr]) {
                m_endKeyBeforeSubstituteArray[ctr]->substitute(params);
            }
            NValue endKeyValue = m_endKeyBeforeSubstituteArray[ctr]->eval(&m_dummy, NULL);
            try {
                m_endKey.setNValue(ctr, endKeyValue);
            }
            catch (SQLException e) {
                // This next bit of logic handles underflow and overflow while
                // setting up the search keys.
                // e.g. TINYINT > 200 or INT <= 6000000000

                // re-throw if not an overflow or underflow
                // currently, it's expected to always be an overflow or underflow
                if ((e.getInternalFlags() & (SQLException::TYPE_OVERFLOW | SQLException::TYPE_UNDERFLOW)) == 0) {
                    throw e;
                }

                if (ctr == (m_numOfEndkeys - 1)) {
                    assert (m_endType == INDEX_LOOKUP_TYPE_LT || m_endType == INDEX_LOOKUP_TYPE_LTE);
                    if (e.getInternalFlags() & SQLException::TYPE_UNDERFLOW) {
                        m_outputTable->insertTuple(tmptup);
                        return true;
                    } else if (e.getInternalFlags() & SQLException::TYPE_OVERFLOW) {
                        endKeyOverflow = true;
                        const ValueType type = m_endKey.getSchema()->columnType(ctr);
                        NValue tmpEndKeyValue = ValueFactory::getBigIntValue(getMaxTypeValue(type));
                        m_endKey.setNValue(ctr, tmpEndKeyValue);

                        VOLT_DEBUG("<Index count> end key out of range, MAX value: %ld...\n", (long)getMaxTypeValue(type));
                        break;
                    } else {
                        throw e;
                    }
                }
                // if a EQ comparision is out of range, then return no tuples
                else {
                    m_outputTable->insertTuple(tmptup);
                    return true;
                }
                break;
            }
        }
        //assert((activeNumOfEndKeys == 0) || (m_endKey.getSchema()->columnCount() > 0));
        VOLT_TRACE("End key after substitutions: '%s'", m_endKey.debugNoHeader().c_str());
    }

    //
    // POST EXPRESSION
    //
    assert (m_node->getPredicate() == NULL);

    assert (m_index);
    assert (m_index == m_targetTable->index(m_node->getTargetIndexName()));
    assert (m_index->is_countable_index_);

    // An index count has two cases: unique and non-unique
    int64_t rkStart = 0, rkEnd = 0, rkRes = 0;
    int leftIncluded = 0, rightIncluded = 0;

    // Deal with multi-map
    VOLT_DEBUG("INDEX_LOOKUP_TYPE(%d) m_numSearchkeys(%d) key:%s",
               localLookupType, activeNumOfSearchKeys, m_searchKey.debugNoHeader().c_str());
    if (searchKeyUnderflow == false) {
        if (localLookupType == INDEX_LOOKUP_TYPE_GT) {
            rkStart = m_index->getCounterLET(&m_searchKey, true);
        } else if (localLookupType == INDEX_LOOKUP_TYPE_GTE) {
            if (m_index->hasKey(&m_searchKey)) {
                leftIncluded = 1;
                rkStart = m_index->getCounterLET(&m_searchKey, false);
            } else {
                rkStart = m_index->getCounterLET(&m_searchKey, true);
            }
            if (m_searchKey.getSchema()->columnCount() > activeNumOfSearchKeys) {
                // search key is not complete:
                // like: SELECT count(*) from T2 WHERE USERNAME ='XIN' AND POINTS < ?
                // like: SELECT count(*) from T2 WHERE POINTS < ?
                // but it actually finds the previous rank. (If m_searchKey is null, find 0 rank)
                // Add 1 back.
                rkStart++;
                leftIncluded = 1;
            }
        } else {
            return false;
        }
    }
    if (m_numOfEndkeys != 0) {
        if (endKeyOverflow) {
            rkEnd = m_index->getCounterGET(&m_endKey, true);
        } else {
            IndexLookupType localEndType = m_endType;
            if (localEndType == INDEX_LOOKUP_TYPE_LT) {
                rkEnd = m_index->getCounterGET(&m_endKey, false);
            } else if (localEndType == INDEX_LOOKUP_TYPE_LTE) {
                if (m_index->hasKey(&m_endKey)) {
                    rkEnd = m_index->getCounterGET(&m_endKey, true);
                    rightIncluded = 1;
                } else
                    rkEnd = m_index->getCounterGET(&m_endKey, false);
            } else {
                return false;
            }
        }
    } else {
        rkEnd = m_index->getSize();
        rightIncluded = 1;
    }
    rkRes = rkEnd - rkStart - 1 + leftIncluded + rightIncluded;
    VOLT_DEBUG("Index Count ANSWER %ld = %ld - %ld - 1 + %d + %d\n", (long)rkRes, (long)rkEnd, (long)rkStart, leftIncluded, rightIncluded);
    tmptup.setNValue(0, ValueFactory::getBigIntValue( rkRes ));
    m_outputTable->insertTuple(tmptup);

    VOLT_DEBUG ("Index Count :\n %s", m_outputTable->debug().c_str());
    return true;
}

IndexCountExecutor::~IndexCountExecutor() {
    delete [] m_searchKeyBackingStore;
    if (m_numOfEndkeys != 0)
        delete [] m_endKeyBackingStore;
}
<commit_msg>Use the public method other than the protected variable<commit_after>/* This file is part of VoltDB.
 * Copyright (C) 2008-2012 VoltDB Inc.
 *
 * VoltDB 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 3 of the License, or
 * (at your option) any later version.
 *
 * VoltDB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "indexcountexecutor.h"

#include "common/debuglog.h"
#include "common/common.h"
#include "common/tabletuple.h"
#include "common/FatalException.hpp"
#include "expressions/abstractexpression.h"
#include "expressions/expressionutil.h"
#include "plannodes/indexcountnode.h"
#include "storage/table.h"
#include "storage/tableiterator.h"
#include "storage/tablefactory.h"
#include "storage/temptable.h"
#include "storage/persistenttable.h"

using namespace voltdb;

bool IndexCountExecutor::p_init(AbstractPlanNode *abstractNode,
                                TempTableLimits* limits)
{
    VOLT_DEBUG("init IndexCount Executor");

    m_node = dynamic_cast<IndexCountPlanNode*>(abstractNode);
    assert(m_node);
    assert(m_node->getTargetTable());
    assert(m_node->getPredicate() == NULL);

    // Create output table based on output schema from the plan
    TupleSchema* schema = m_node->generateTupleSchema(false);
    int column_count = static_cast<int>(m_node->getOutputSchema().size());
    assert(column_count == 1);

    std::string* column_names = new std::string[column_count];
    column_names[0] = m_node->getOutputSchema()[0]->getColumnName();

    m_node->setOutputTable(TableFactory::getTempTable(m_node->databaseId(),
                                                      m_node->getTargetTable()->name(),
                                                      schema,
                                                      column_names,
                                                      limits));
    delete[] column_names;

    //
    // Make sure that we have search keys and that they're not null
    //
    m_numOfSearchkeys = (int)m_node->getSearchKeyExpressions().size();
    m_searchKeyBeforeSubstituteArrayPtr =
        boost::shared_array<AbstractExpression*>
    (new AbstractExpression*[m_numOfSearchkeys]);
    m_searchKeyBeforeSubstituteArray = m_searchKeyBeforeSubstituteArrayPtr.get();
    m_needsSubstituteSearchKeyPtr =
        boost::shared_array<bool>(new bool[m_numOfSearchkeys]);
    m_needsSubstituteSearchKey = m_needsSubstituteSearchKeyPtr.get();

    for (int ctr = 0; ctr < m_numOfSearchkeys; ctr++)
    {
        if (m_node->getSearchKeyExpressions()[ctr] == NULL)
        {
            VOLT_ERROR("The search key expression at position '%d' is NULL for"
                " PlanNode '%s'", ctr, m_node->debug().c_str());
            return false;
        }
        m_needsSubstituteSearchKeyPtr[ctr] =
            m_node->getSearchKeyExpressions()[ctr]->hasParameter();
        m_searchKeyBeforeSubstituteArrayPtr[ctr] =
            m_node->getSearchKeyExpressions()[ctr];
    }

    m_numOfEndkeys = (int)m_node->getEndKeyExpressions().size();
    if (m_numOfEndkeys != 0) {
        m_endKeyBeforeSubstituteArrayPtr =
            boost::shared_array<AbstractExpression*> (new AbstractExpression*[m_numOfEndkeys]);
        m_endKeyBeforeSubstituteArray = m_endKeyBeforeSubstituteArrayPtr.get();
        m_needsSubstituteEndKeyPtr =
            boost::shared_array<bool>(new bool[m_numOfEndkeys]);
        m_needsSubstituteEndKey = m_needsSubstituteEndKeyPtr.get();
        for (int ctr = 0; ctr < m_numOfEndkeys; ctr++)
        {
            if (m_node->getEndKeyExpressions()[ctr] == NULL) {
                VOLT_ERROR("The end key expression at position '%d' is NULL for"
                    " PlanNode '%s'", ctr, m_node->debug().c_str());
                return false;
            }
            m_needsSubstituteEndKeyPtr[ctr] =
                m_node->getEndKeyExpressions()[ctr]->hasParameter();
            m_endKeyBeforeSubstituteArrayPtr[ctr] =
                m_node->getEndKeyExpressions()[ctr];
        }
    }

    //
    // Initialize local variables
    //

    //output table should be temptable
    m_outputTable = static_cast<TempTable*>(m_node->getOutputTable());
    //target table should be persistenttable
    m_targetTable = static_cast<PersistentTable*>(m_node->getTargetTable());
    m_numOfColumns = static_cast<int>(m_outputTable->columnCount());

    assert(m_numOfColumns == 1);
    //
    // Grab the Index from our inner table
    // We'll throw an error if the index is missing
    //
    m_index = m_targetTable->index(m_node->getTargetIndexName());
    assert (m_index != NULL);

    // This index should have a true countable flag
    assert(m_index->isCountableIndex());

    m_searchKey = TableTuple(m_index->getKeySchema());
    m_searchKeyBackingStore = new char[m_index->getKeySchema()->tupleLength()];
    m_searchKey.moveNoHeader(m_searchKeyBackingStore);
    if (m_numOfEndkeys != 0) {
        m_endKey = TableTuple(m_index->getKeySchema());
        m_endKeyBackingStore = new char[m_index->getKeySchema()->tupleLength()];
        m_endKey.moveNoHeader(m_endKeyBackingStore);
    }

    // Miscellanous Information
    m_lookupType = m_node->getLookupType();
    if (m_numOfEndkeys != 0) {
        m_endType = m_node->getEndType();
    }

    // Need to move GTE to find (x,_) when doing a partial covering search.
    // the planner sometimes lies in this case: index_lookup_type_eq is incorrect.
    // Index_lookup_type_gte is necessary. Make the change here.
    if (m_lookupType == INDEX_LOOKUP_TYPE_EQ &&
        m_searchKey.getSchema()->columnCount() > m_numOfSearchkeys)
    {
        VOLT_TRACE("Setting lookup type to GTE for partial covering key.");
        m_lookupType = INDEX_LOOKUP_TYPE_GTE;
    }

    return true;
}

bool IndexCountExecutor::p_execute(const NValueArray &params)
{
    assert(m_node);
    assert(m_node == dynamic_cast<IndexCountPlanNode*>(m_abstractNode));
    assert(m_outputTable);
    assert(m_outputTable == static_cast<TempTable*>(m_node->getOutputTable()));
    assert(m_targetTable);
    assert(m_targetTable == m_node->getTargetTable());
    VOLT_DEBUG("IndexCount: %s.%s\n", m_targetTable->name().c_str(),
               m_index->getName().c_str());

    int activeNumOfSearchKeys = m_numOfSearchkeys;
    IndexLookupType localLookupType = m_lookupType;
    bool searchKeyUnderflow = false, endKeyOverflow = false;
    // Overflow cases that can return early without accessing the index need this
    // default 0 count as their result.
    TableTuple& tmptup = m_outputTable->tempTuple();
    tmptup.setNValue(0, ValueFactory::getBigIntValue( 0 ));
    TableTuple m_dummy;

    //
    // SEARCH KEY
    //
    m_searchKey.setAllNulls();
    VOLT_DEBUG("<Index Count>Initial (all null) search key: '%s'", m_searchKey.debugNoHeader().c_str());
    for (int ctr = 0; ctr < activeNumOfSearchKeys; ctr++) {
        if (m_needsSubstituteSearchKey[ctr]) {
            m_searchKeyBeforeSubstituteArray[ctr]->substitute(params);
        }
        NValue candidateValue = m_searchKeyBeforeSubstituteArray[ctr]->eval(&m_dummy, NULL);
        try {
            m_searchKey.setNValue(ctr, candidateValue);
        }
        catch (SQLException e) {
            // This next bit of logic handles underflow and overflow while
            // setting up the search keys.
            // e.g. TINYINT > 200 or INT <= 6000000000

            // re-throw if not an overflow or underflow
            // currently, it's expected to always be an overflow or underflow
            if ((e.getInternalFlags() & (SQLException::TYPE_OVERFLOW | SQLException::TYPE_UNDERFLOW)) == 0) {
                throw e;
            }

            // handle the case where this is a comparison, rather than equality match
            // comparison is the only place where the executor might return matching tuples
            // e.g. TINYINT < 1000 should return all values

            if ((localLookupType != INDEX_LOOKUP_TYPE_EQ) &&
                (ctr == (activeNumOfSearchKeys - 1))) {
                assert (localLookupType == INDEX_LOOKUP_TYPE_GT || localLookupType == INDEX_LOOKUP_TYPE_GTE);

                if (e.getInternalFlags() & SQLException::TYPE_OVERFLOW) {
                    m_outputTable->insertTuple(tmptup);
                    return true;
                } else if (e.getInternalFlags() & SQLException::TYPE_UNDERFLOW) {
                    searchKeyUnderflow = true;
                    break;
                } else {
                    throw e;
                }
            }
            // if a EQ comparision is out of range, then return no tuples
            else {
                m_outputTable->insertTuple(tmptup);
                return true;
            }
            break;
        }
    }
    assert(activeNumOfSearchKeys > 0);
    VOLT_TRACE("Search key after substitutions: '%s'", m_searchKey.debugNoHeader().c_str());

    if (m_numOfEndkeys != 0) {
        //
        // END KEY
        //
        m_endKey.setAllNulls();
        VOLT_DEBUG("Initial (all null) end key: '%s'", m_endKey.debugNoHeader().c_str());
        for (int ctr = 0; ctr < m_numOfEndkeys; ctr++) {
            if (m_needsSubstituteEndKey[ctr]) {
                m_endKeyBeforeSubstituteArray[ctr]->substitute(params);
            }
            NValue endKeyValue = m_endKeyBeforeSubstituteArray[ctr]->eval(&m_dummy, NULL);
            try {
                m_endKey.setNValue(ctr, endKeyValue);
            }
            catch (SQLException e) {
                // This next bit of logic handles underflow and overflow while
                // setting up the search keys.
                // e.g. TINYINT > 200 or INT <= 6000000000

                // re-throw if not an overflow or underflow
                // currently, it's expected to always be an overflow or underflow
                if ((e.getInternalFlags() & (SQLException::TYPE_OVERFLOW | SQLException::TYPE_UNDERFLOW)) == 0) {
                    throw e;
                }

                if (ctr == (m_numOfEndkeys - 1)) {
                    assert (m_endType == INDEX_LOOKUP_TYPE_LT || m_endType == INDEX_LOOKUP_TYPE_LTE);
                    if (e.getInternalFlags() & SQLException::TYPE_UNDERFLOW) {
                        m_outputTable->insertTuple(tmptup);
                        return true;
                    } else if (e.getInternalFlags() & SQLException::TYPE_OVERFLOW) {
                        endKeyOverflow = true;
                        const ValueType type = m_endKey.getSchema()->columnType(ctr);
                        NValue tmpEndKeyValue = ValueFactory::getBigIntValue(getMaxTypeValue(type));
                        m_endKey.setNValue(ctr, tmpEndKeyValue);

                        VOLT_DEBUG("<Index count> end key out of range, MAX value: %ld...\n", (long)getMaxTypeValue(type));
                        break;
                    } else {
                        throw e;
                    }
                }
                // if a EQ comparision is out of range, then return no tuples
                else {
                    m_outputTable->insertTuple(tmptup);
                    return true;
                }
                break;
            }
        }
        //assert((activeNumOfEndKeys == 0) || (m_endKey.getSchema()->columnCount() > 0));
        VOLT_TRACE("End key after substitutions: '%s'", m_endKey.debugNoHeader().c_str());
    }

    //
    // POST EXPRESSION
    //
    assert (m_node->getPredicate() == NULL);

    assert (m_index);
    assert (m_index == m_targetTable->index(m_node->getTargetIndexName()));
    assert (m_index->isCountableIndex());

    // An index count has two cases: unique and non-unique
    int64_t rkStart = 0, rkEnd = 0, rkRes = 0;
    int leftIncluded = 0, rightIncluded = 0;

    // Deal with multi-map
    VOLT_DEBUG("INDEX_LOOKUP_TYPE(%d) m_numSearchkeys(%d) key:%s",
               localLookupType, activeNumOfSearchKeys, m_searchKey.debugNoHeader().c_str());
    if (searchKeyUnderflow == false) {
        if (localLookupType == INDEX_LOOKUP_TYPE_GT) {
            rkStart = m_index->getCounterLET(&m_searchKey, true);
        } else if (localLookupType == INDEX_LOOKUP_TYPE_GTE) {
            if (m_index->hasKey(&m_searchKey)) {
                leftIncluded = 1;
                rkStart = m_index->getCounterLET(&m_searchKey, false);
            } else {
                rkStart = m_index->getCounterLET(&m_searchKey, true);
            }
            if (m_searchKey.getSchema()->columnCount() > activeNumOfSearchKeys) {
                // search key is not complete:
                // like: SELECT count(*) from T2 WHERE USERNAME ='XIN' AND POINTS < ?
                // like: SELECT count(*) from T2 WHERE POINTS < ?
                // but it actually finds the previous rank. (If m_searchKey is null, find 0 rank)
                // Add 1 back.
                rkStart++;
                leftIncluded = 1;
            }
        } else {
            return false;
        }
    }
    if (m_numOfEndkeys != 0) {
        if (endKeyOverflow) {
            rkEnd = m_index->getCounterGET(&m_endKey, true);
        } else {
            IndexLookupType localEndType = m_endType;
            if (localEndType == INDEX_LOOKUP_TYPE_LT) {
                rkEnd = m_index->getCounterGET(&m_endKey, false);
            } else if (localEndType == INDEX_LOOKUP_TYPE_LTE) {
                if (m_index->hasKey(&m_endKey)) {
                    rkEnd = m_index->getCounterGET(&m_endKey, true);
                    rightIncluded = 1;
                } else
                    rkEnd = m_index->getCounterGET(&m_endKey, false);
            } else {
                return false;
            }
        }
    } else {
        rkEnd = m_index->getSize();
        rightIncluded = 1;
    }
    rkRes = rkEnd - rkStart - 1 + leftIncluded + rightIncluded;
    VOLT_DEBUG("Index Count ANSWER %ld = %ld - %ld - 1 + %d + %d\n", (long)rkRes, (long)rkEnd, (long)rkStart, leftIncluded, rightIncluded);
    tmptup.setNValue(0, ValueFactory::getBigIntValue( rkRes ));
    m_outputTable->insertTuple(tmptup);

    VOLT_DEBUG ("Index Count :\n %s", m_outputTable->debug().c_str());
    return true;
}

IndexCountExecutor::~IndexCountExecutor() {
    delete [] m_searchKeyBackingStore;
    if (m_numOfEndkeys != 0)
        delete [] m_endKeyBackingStore;
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

#ifndef CQL3_LISTS_HH
#define CQL3_LISTS_HH

#include "cql3/abstract_marker.hh"
#include "to_string.hh"
#include "utils/UUID_gen.hh"
#include "operation.hh"

namespace cql3 {

#if 0
package org.apache.cassandra.cql3;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.db.Cell;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.Composite;
import org.apache.cassandra.db.marshal.Int32Type;
import org.apache.cassandra.db.marshal.ListType;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.serializers.CollectionSerializer;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.transport.Server;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.UUIDGen;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
#endif

/**
 * Static helper methods and classes for lists.
 */
class lists {
    lists() = delete;
public:
    static shared_ptr<column_specification> index_spec_of(shared_ptr<column_specification> column);
    static shared_ptr<column_specification> value_spec_of(shared_ptr<column_specification> column);

    class literal : public term::raw {
        const std::vector<shared_ptr<term::raw>> _elements;
    public:
        explicit literal(std::vector<shared_ptr<term::raw>> elements)
            : _elements(std::move(elements)) {
        }
        shared_ptr<term> prepare(database& db, const sstring& keyspace, shared_ptr<column_specification> receiver);
    private:
        void validate_assignable_to(database& db, const sstring keyspace, shared_ptr<column_specification> receiver);
    public:
        virtual assignment_testable::test_result test_assignment(database& db, const sstring& keyspace, shared_ptr<column_specification> receiver) override;
        virtual sstring to_string() const override;
    };

    class value : public multi_item_terminal, collection_terminal {
        std::vector<bytes_opt> _elements;
    public:
        explicit value(std::vector<bytes_opt> elements)
            : _elements(std::move(elements)) {
        }
        static value from_serialized(bytes_view v, shared_ptr<list_type_impl> type, serialization_format sf);
        virtual bytes_opt get(const query_options& options) override;
        virtual bytes get_with_protocol_version(serialization_format sf) override;
        bool equals(shared_ptr<list_type_impl> lt, const value& v);
        virtual std::vector<bytes_opt> get_elements() override;
        virtual sstring to_string() const;
        friend class lists;
    };
    /**
     * Basically similar to a Value, but with some non-pure function (that need
     * to be evaluated at execution time) in it.
     *
     * Note: this would also work for a list with bind markers, but we don't support
     * that because 1) it's not excessively useful and 2) we wouldn't have a good
     * column name to return in the ColumnSpecification for those markers (not a
     * blocker per-se but we don't bother due to 1)).
     */
    class delayed_value : public non_terminal {
        std::vector<shared_ptr<term>> _elements;
    public:
        explicit delayed_value(std::vector<shared_ptr<term>> elements)
                : _elements(std::move(elements)) {
        }
        virtual bool contains_bind_marker() const override;
        virtual void collect_marker_specification(shared_ptr<variable_specifications> bound_names);
        virtual shared_ptr<terminal> bind(const query_options& options) override;
    };

    /**
     * A marker for List values and IN relations
     */
    class marker : public abstract_marker {
    public:
        marker(int32_t bind_index, ::shared_ptr<column_specification> receiver)
            : abstract_marker{bind_index, std::move(receiver)}
        { }
#if 0
        protected Marker(int bindIndex, ColumnSpecification receiver)
        {
            super(bindIndex, receiver);
            assert receiver.type instanceof ListType;
        }
#endif
        virtual ::shared_ptr<terminal> bind(const query_options& options) override;
#if 0
        public Value bind(QueryOptions options) throws InvalidRequestException
        {
            ByteBuffer value = options.getValues().get(bindIndex);
            return value == null ? null : Value.fromSerialized(value, (ListType)receiver.type, options.getProtocolVersion());
        }
#endif
    };
#if 0
    /*
     * For prepend, we need to be able to generate unique but decreasing time
     * UUID, which is a bit challenging. To do that, given a time in milliseconds,
     * we adds a number representing the 100-nanoseconds precision and make sure
     * that within the same millisecond, that number is always decreasing. We
     * do rely on the fact that the user will only provide decreasing
     * milliseconds timestamp for that purpose.
     */
    private static class PrecisionTime
    {
        // Our reference time (1 jan 2010, 00:00:00) in milliseconds.
        private static final long REFERENCE_TIME = 1262304000000L;
        private static final AtomicReference<PrecisionTime> last = new AtomicReference<PrecisionTime>(new PrecisionTime(Long.MAX_VALUE, 0));

        public final long millis;
        public final int nanos;

        PrecisionTime(long millis, int nanos)
        {
            this.millis = millis;
            this.nanos = nanos;
        }

        static PrecisionTime getNext(long millis)
        {
            while (true)
            {
                PrecisionTime current = last.get();

                assert millis <= current.millis;
                PrecisionTime next = millis < current.millis
                    ? new PrecisionTime(millis, 9999)
                    : new PrecisionTime(millis, Math.max(0, current.nanos - 1));

                if (last.compareAndSet(current, next))
                    return next;
            }
        }
    }
#endif

    class setter : public operation {
    public:
        setter(const column_definition& column, shared_ptr<term> t)
                : operation(column, std::move(t)) {
        }
        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) override;
    };

    class setter_by_index : public operation {
        shared_ptr<term> _idx;
    public:
        setter_by_index(const column_definition& column, shared_ptr<term> idx, shared_ptr<term> t)
            : operation(column, std::move(t)), _idx(std::move(idx)) {
        }
        virtual bool requires_read() override;
        virtual void collect_marker_specification(shared_ptr<variable_specifications> bound_names);
        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) override;
    };

    class appender : public operation {
    public:
        using operation::operation;
        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) override;
    };

    static void do_append(shared_ptr<term> t,
            mutation& m,
            const exploded_clustering_prefix& prefix,
            const column_definition& column,
            const update_parameters& params,
            tombstone ts = {});

#if 0
    public static class Prepender extends Operation
    {
        public Prepender(ColumnDefinition column, Term t)
        {
            super(column, t);
        }

        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
        {
            assert column.type.isMultiCell() : "Attempted to prepend to a frozen list";
            Term.Terminal value = t.bind(params.options);
            if (value == null)
                return;

            assert value instanceof Lists.Value;
            long time = PrecisionTime.REFERENCE_TIME - (System.currentTimeMillis() - PrecisionTime.REFERENCE_TIME);

            List<ByteBuffer> toAdd = ((Lists.Value)value).elements;
            for (int i = 0; i < toAdd.size(); i++)
            {
                PrecisionTime pt = PrecisionTime.getNext(time);
                ByteBuffer uuid = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(pt.millis, pt.nanos));
                cf.addColumn(params.makeColumn(cf.getComparator().create(prefix, column, uuid), toAdd.get(i)));
            }
        }
    }
#endif

    class discarder : public operation {
    public:
        discarder(const column_definition& column, shared_ptr<term> t)
                : operation(column, std::move(t)) {
        }
        virtual bool requires_read() override;
        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) override;
    };

    class discarder_by_index : public operation {
    public:
        discarder_by_index(const column_definition& column, shared_ptr<term> idx)
                : operation(column, std::move(idx)) {
        }
        virtual bool requires_read() override;
        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params);
    };
};

}

#endif
<commit_msg>cql3: remove gunk from lists.hh<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

#ifndef CQL3_LISTS_HH
#define CQL3_LISTS_HH

#include "cql3/abstract_marker.hh"
#include "to_string.hh"
#include "utils/UUID_gen.hh"
#include "operation.hh"

namespace cql3 {

/**
 * Static helper methods and classes for lists.
 */
class lists {
    lists() = delete;
public:
    static shared_ptr<column_specification> index_spec_of(shared_ptr<column_specification> column);
    static shared_ptr<column_specification> value_spec_of(shared_ptr<column_specification> column);

    class literal : public term::raw {
        const std::vector<shared_ptr<term::raw>> _elements;
    public:
        explicit literal(std::vector<shared_ptr<term::raw>> elements)
            : _elements(std::move(elements)) {
        }
        shared_ptr<term> prepare(database& db, const sstring& keyspace, shared_ptr<column_specification> receiver);
    private:
        void validate_assignable_to(database& db, const sstring keyspace, shared_ptr<column_specification> receiver);
    public:
        virtual assignment_testable::test_result test_assignment(database& db, const sstring& keyspace, shared_ptr<column_specification> receiver) override;
        virtual sstring to_string() const override;
    };

    class value : public multi_item_terminal, collection_terminal {
        std::vector<bytes_opt> _elements;
    public:
        explicit value(std::vector<bytes_opt> elements)
            : _elements(std::move(elements)) {
        }
        static value from_serialized(bytes_view v, shared_ptr<list_type_impl> type, serialization_format sf);
        virtual bytes_opt get(const query_options& options) override;
        virtual bytes get_with_protocol_version(serialization_format sf) override;
        bool equals(shared_ptr<list_type_impl> lt, const value& v);
        virtual std::vector<bytes_opt> get_elements() override;
        virtual sstring to_string() const;
        friend class lists;
    };
    /**
     * Basically similar to a Value, but with some non-pure function (that need
     * to be evaluated at execution time) in it.
     *
     * Note: this would also work for a list with bind markers, but we don't support
     * that because 1) it's not excessively useful and 2) we wouldn't have a good
     * column name to return in the ColumnSpecification for those markers (not a
     * blocker per-se but we don't bother due to 1)).
     */
    class delayed_value : public non_terminal {
        std::vector<shared_ptr<term>> _elements;
    public:
        explicit delayed_value(std::vector<shared_ptr<term>> elements)
                : _elements(std::move(elements)) {
        }
        virtual bool contains_bind_marker() const override;
        virtual void collect_marker_specification(shared_ptr<variable_specifications> bound_names);
        virtual shared_ptr<terminal> bind(const query_options& options) override;
    };

    /**
     * A marker for List values and IN relations
     */
    class marker : public abstract_marker {
    public:
        marker(int32_t bind_index, ::shared_ptr<column_specification> receiver)
            : abstract_marker{bind_index, std::move(receiver)}
        { }
#if 0
        protected Marker(int bindIndex, ColumnSpecification receiver)
        {
            super(bindIndex, receiver);
            assert receiver.type instanceof ListType;
        }
#endif
        virtual ::shared_ptr<terminal> bind(const query_options& options) override;
#if 0
        public Value bind(QueryOptions options) throws InvalidRequestException
        {
            ByteBuffer value = options.getValues().get(bindIndex);
            return value == null ? null : Value.fromSerialized(value, (ListType)receiver.type, options.getProtocolVersion());
        }
#endif
    };
#if 0
    /*
     * For prepend, we need to be able to generate unique but decreasing time
     * UUID, which is a bit challenging. To do that, given a time in milliseconds,
     * we adds a number representing the 100-nanoseconds precision and make sure
     * that within the same millisecond, that number is always decreasing. We
     * do rely on the fact that the user will only provide decreasing
     * milliseconds timestamp for that purpose.
     */
    private static class PrecisionTime
    {
        // Our reference time (1 jan 2010, 00:00:00) in milliseconds.
        private static final long REFERENCE_TIME = 1262304000000L;
        private static final AtomicReference<PrecisionTime> last = new AtomicReference<PrecisionTime>(new PrecisionTime(Long.MAX_VALUE, 0));

        public final long millis;
        public final int nanos;

        PrecisionTime(long millis, int nanos)
        {
            this.millis = millis;
            this.nanos = nanos;
        }

        static PrecisionTime getNext(long millis)
        {
            while (true)
            {
                PrecisionTime current = last.get();

                assert millis <= current.millis;
                PrecisionTime next = millis < current.millis
                    ? new PrecisionTime(millis, 9999)
                    : new PrecisionTime(millis, Math.max(0, current.nanos - 1));

                if (last.compareAndSet(current, next))
                    return next;
            }
        }
    }
#endif

    class setter : public operation {
    public:
        setter(const column_definition& column, shared_ptr<term> t)
                : operation(column, std::move(t)) {
        }
        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) override;
    };

    class setter_by_index : public operation {
        shared_ptr<term> _idx;
    public:
        setter_by_index(const column_definition& column, shared_ptr<term> idx, shared_ptr<term> t)
            : operation(column, std::move(t)), _idx(std::move(idx)) {
        }
        virtual bool requires_read() override;
        virtual void collect_marker_specification(shared_ptr<variable_specifications> bound_names);
        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) override;
    };

    class appender : public operation {
    public:
        using operation::operation;
        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) override;
    };

    static void do_append(shared_ptr<term> t,
            mutation& m,
            const exploded_clustering_prefix& prefix,
            const column_definition& column,
            const update_parameters& params,
            tombstone ts = {});

#if 0
    public static class Prepender extends Operation
    {
        public Prepender(ColumnDefinition column, Term t)
        {
            super(column, t);
        }

        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
        {
            assert column.type.isMultiCell() : "Attempted to prepend to a frozen list";
            Term.Terminal value = t.bind(params.options);
            if (value == null)
                return;

            assert value instanceof Lists.Value;
            long time = PrecisionTime.REFERENCE_TIME - (System.currentTimeMillis() - PrecisionTime.REFERENCE_TIME);

            List<ByteBuffer> toAdd = ((Lists.Value)value).elements;
            for (int i = 0; i < toAdd.size(); i++)
            {
                PrecisionTime pt = PrecisionTime.getNext(time);
                ByteBuffer uuid = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(pt.millis, pt.nanos));
                cf.addColumn(params.makeColumn(cf.getComparator().create(prefix, column, uuid), toAdd.get(i)));
            }
        }
    }
#endif

    class discarder : public operation {
    public:
        discarder(const column_definition& column, shared_ptr<term> t)
                : operation(column, std::move(t)) {
        }
        virtual bool requires_read() override;
        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) override;
    };

    class discarder_by_index : public operation {
    public:
        discarder_by_index(const column_definition& column, shared_ptr<term> idx)
                : operation(column, std::move(idx)) {
        }
        virtual bool requires_read() override;
        virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params);
    };
};

}

#endif
<|endoftext|>


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

#include    "../Debug/Assertions.h"

#include    "Concrete/Bag_Array.h"  // needed for default constructor

namespace   Stroika {
    namespace   Foundation {
        namespace   Containers {

            // class Bag<T>
            template    <typename T>
            inline  Bag<T>::Bag (const Bag<T>& bag)
                : Iterable<T> (bag)
            {
            }
            template    <typename T>
            inline  Bag<T>::Bag (typename Bag<T>::_IRep* rep)
                : Iterable<T> (Memory::SharedByValue<Iterable<T>::_IRep> (rep))
            {
                RequireNotNull (rep);
            }
            template    <typename T>
            Bag<T>::Bag ()
                : Iterable<T> (Concrete::Bag_Array<T> ())
            {
            }
            template    <typename T>
            Bag<T>::Bag (const T* start, const T* end)
                : Iterable<T> (Concrete::Bag_Array<T> (start, end))
            {
            }
            template    <typename T>
            inline  Bag<T>& Bag<T>::operator= (const Bag<T>& rhs)
            {
                (void)::Iterable<T>::operator= (rhs);
                return (*this);
            }
            template    <typename T>
            inline  bool    Bag<T>::Contains (T item) const
            {
                return (_GetRep ().Contains (item));
            }
            template    <typename T>
            inline  void    Bag<T>::RemoveAll ()
            {
                _GetRep ().RemoveAll ();
            }
            template    <typename T>
            inline  void    Bag<T>::Compact ()
            {
                _GetRep ().Compact ();
            }
            template    <typename T>
            inline  Iterator<T> Bag<T>::MakeIterator () const
            {
                Iterator<T> it (const_cast<Bag<T> *> (this)->_GetRep ().MakeIterator ());
                ++it;
                return it;
            }
            template    <typename T>
            inline  Iterator<T>    Bag<T>::begin () const
            {
                return MakeIterator ();
            }
            template    <typename T>
            inline  Iterator<T>    Bag<T>::end () const
            {
                return (Iterator<T>::GetSentinal ());
            }
            template    <typename T>
            inline  typename Bag<T>::Mutator    Bag<T>::begin ()
            {
                return MakeMutator ();
            }
            template    <typename T>
            inline  typename Bag<T>::Mutator    Bag<T>::end ()
            {
                return (Bag<T>::Mutator (nullptr));
            }
            template    <typename T>
            inline  Bag<T>& Bag<T>::operator+= (T item)
            {
                Add (item);
                return (*this);
            }
            template    <typename T>
            inline  Bag<T>& Bag<T>::operator+= (const Bag<T>& items)
            {
                Add (items);
                return (*this);
            }
            template    <typename T>
            inline  Bag<T>& Bag<T>::operator-= (T item)
            {
                Remove (item);
                return (*this);
            }
            template    <typename T>
            inline  Bag<T>& Bag<T>::operator-= (const Bag<T>& items)
            {
                Remove (items);
                return (*this);
            }
            template    <typename T>
            inline   typename   Bag<T>::Mutator  Bag<T>::MakeMutator ()
            {
                Bag<T>::Mutator it = Bag<T>::Mutator (_GetRep ().MakeBagMutator ());
                ++it;
                return it;
            }
            template    <typename T>
            inline  void    Bag<T>::Add (T item)
            {
                _GetRep ().Add (item);
                Ensure (not IsEmpty ());
            }
            template    <typename T>
            void  Bag<T>::Add (const Bag<T>& items)
            {
                if (this == &items) {
                    // Copy - so we don't update this while we are copying from it...
                    Bag<T>  copiedItems =   items;
                    For (it, copiedItems) {
                        _GetRep ().Add (it.Current ());
                    }
                }
                else {
                    For (it, items) {
                        _GetRep ().Add (it.Current ());
                    }
                }
            }
            template    <typename T>
            void  Bag<T>::Add (const T* begin, const T* end)
            {
                for (const T* i = begin; i != end; i++) {
                    Add (*i);
                }
            }
            template    <typename T>
            inline  void  Bag<T>::Remove (T item)
            {
                _GetRep ().Remove (item);
            }
            template    <typename T>
            void  Bag<T>::Remove (const Bag<T>& items)
            {
                if (&_GetRep () == &items._GetRep ()) {
                    RemoveAll ();
                }
                else {
                    For (it, items) {
                        _GetRep ().Remove (it.Current ());
                    }
                }
            }
            template    <typename T>
            size_t    Bag<T>::TallyOf (T item) const
            {
                size_t count = 0;
                For (it, (*this)) {
                    if (it.Current () == item) {
                        count++;
                    }
                }
                return (count);
            }

            /*
             ********************************************************************************
             ************************************ operators *********************************
             ********************************************************************************
             */
            template    <typename T>
            bool  operator== (const Bag<T>& lhs, const Bag<T>& rhs)
            {
                if (&lhs._GetRep () == &rhs._GetRep ()) {
                    return (true);
                }
                if (lhs.GetLength () != rhs.GetLength ()) {
                    return (false);
                }

                // n^2 algorithm!!!
                For (it, lhs) {
                    if (lhs.TallyOf (it.Current ()) != rhs.TallyOf (it.Current ())) {
                        return (false);
                    }
                }
                return (true);
            }
            template    <typename T>
            Bag<T>    operator+ (const Bag<T>& lhs, const Bag<T>& rhs)
            {
                Bag<T>  temp    = lhs;
                temp += rhs;
                return (temp);
            }
            template    <typename T>
            Bag<T>    operator- (const Bag<T>& lhs, const Bag<T>& rhs)
            {
                Bag<T>  temp    = lhs;
                temp -= rhs;
                return (temp);
            }
            template    <typename T>
            inline  bool    operator!= (const Bag<T>& lhs, const Bag<T>& rhs)
            {
                return (not operator== (lhs, rhs));
            }

            // class Bag<T>::_IMutatorRep<T>
            template    <typename T>
            inline  Bag<T>::_IMutatorRep::_IMutatorRep () :
                Iterator<T>::Rep ()
            {
            }

            // class Bag<T>::Mutator
            template    <typename T>
            inline  Bag<T>::Mutator::Mutator (typename Bag<T>::_IMutatorRep* it) :
                Iterator<T> (it)
            {
            }
            template    <typename T>
            inline  typename    Bag<T>::_IMutatorRep* Bag<T>::Mutator::GetMutatorRep_ ()
            {
                /*
                 * Because of the way we construct Mutators, it is guaranteed that
                 * this cast is safe. We could have kept an extra var of the right
                 * static type, but this would have been a waste of time and memory.
                 */
                return &(dynamic_cast<_IMutatorRep&> (*this->fIterator));
            }
            template    <typename T>
            inline  void    Bag<T>::Mutator::RemoveCurrent ()
            {
                GetMutatorRep_ ()->RemoveCurrent ();
            }
            template    <typename T>
            inline  void    Bag<T>::Mutator::UpdateCurrent (T newValue)
            {
                GetMutatorRep_ ()->UpdateCurrent (newValue);
            }

            // class _IRep<T>
            template    <typename T>
            inline  Bag<T>::_IRep::_IRep ()
            {
            }
            template    <typename T>
            inline  Bag<T>::_IRep::~_IRep ()
            {
            }
            template    <typename T>
            inline  const typename  Bag<T>::_IRep&    Bag<T>::_GetRep () const
            {
                // Unsure - MAY need to use dynamic_cast here - but I think static cast performs better, so try...
                EnsureNotNull (dynamic_cast<const Bag<T>::_IRep*> (&Iterable<T>::_GetRep ()));
                return *static_cast<const Bag<T>::_IRep*> (&Iterable<T>::_GetRep ());
            }
            template    <typename T>
            inline  typename    Bag<T>::_IRep&  Bag<T>::_GetRep ()
            {
                // Unsure - MAY need to use dynamic_cast here - but I think static cast performs better, so try...
                EnsureNotNull (dynamic_cast<Bag<T>::_IRep*> (&Iterable<T>::_GetRep ()));
                return *static_cast<Bag<T>::_IRep*> (&Iterable<T>::_GetRep ());
            }

        }
    }
}

#endif /* _Stroika_Foundation_Containers_Bag_inl_ */
<commit_msg>small fixes to Bag<T> / Interable<T> integration caught by gcc<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2012.  All rights reserved
 */
#ifndef _Stroika_Foundation_Containers_Bag_inl_
#define _Stroika_Foundation_Containers_Bag_inl_

#include    "../Debug/Assertions.h"

#include    "Concrete/Bag_Array.h"  // needed for default constructor

namespace   Stroika {
    namespace   Foundation {
        namespace   Containers {

            // class Bag<T>
            template    <typename T>
            inline  Bag<T>::Bag (const Bag<T>& bag)
                : Iterable<T> (bag)
            {
            }
            template    <typename T>
            inline  Bag<T>::Bag (typename Bag<T>::_IRep* rep)
                : Iterable<T> (_SharedByValueRepType (rep))
            {
                RequireNotNull (rep);
            }
            template    <typename T>
            Bag<T>::Bag ()
                : Iterable<T> (Concrete::Bag_Array<T> ())
            {
            }
            template    <typename T>
            Bag<T>::Bag (const T* start, const T* end)
                : Iterable<T> (Concrete::Bag_Array<T> (start, end))
            {
            }
            template    <typename T>
            inline  Bag<T>& Bag<T>::operator= (const Bag<T>& rhs)
            {
                (void)Iterable<T>::operator= (rhs);
                return (*this);
            }
            template    <typename T>
            inline  bool    Bag<T>::Contains (T item) const
            {
                return (_GetRep ().Contains (item));
            }
            template    <typename T>
            inline  void    Bag<T>::RemoveAll ()
            {
                _GetRep ().RemoveAll ();
            }
            template    <typename T>
            inline  void    Bag<T>::Compact ()
            {
                _GetRep ().Compact ();
            }
            template    <typename T>
            inline  Iterator<T> Bag<T>::MakeIterator () const
            {
                Iterator<T> it (const_cast<Bag<T> *> (this)->_GetRep ().MakeIterator ());
                ++it;
                return it;
            }
            template    <typename T>
            inline  Iterator<T>    Bag<T>::begin () const
            {
                return MakeIterator ();
            }
            template    <typename T>
            inline  Iterator<T>    Bag<T>::end () const
            {
                return (Iterator<T>::GetSentinal ());
            }
            template    <typename T>
            inline  typename Bag<T>::Mutator    Bag<T>::begin ()
            {
                return MakeMutator ();
            }
            template    <typename T>
            inline  typename Bag<T>::Mutator    Bag<T>::end ()
            {
                return (Bag<T>::Mutator (nullptr));
            }
            template    <typename T>
            inline  Bag<T>& Bag<T>::operator+= (T item)
            {
                Add (item);
                return (*this);
            }
            template    <typename T>
            inline  Bag<T>& Bag<T>::operator+= (const Bag<T>& items)
            {
                Add (items);
                return (*this);
            }
            template    <typename T>
            inline  Bag<T>& Bag<T>::operator-= (T item)
            {
                Remove (item);
                return (*this);
            }
            template    <typename T>
            inline  Bag<T>& Bag<T>::operator-= (const Bag<T>& items)
            {
                Remove (items);
                return (*this);
            }
            template    <typename T>
            inline   typename   Bag<T>::Mutator  Bag<T>::MakeMutator ()
            {
                Bag<T>::Mutator it = Bag<T>::Mutator (_GetRep ().MakeBagMutator ());
                ++it;
                return it;
            }
            template    <typename T>
            inline  void    Bag<T>::Add (T item)
            {
                _GetRep ().Add (item);
                Ensure (not this->IsEmpty ());
            }
            template    <typename T>
            void  Bag<T>::Add (const Bag<T>& items)
            {
                if (this == &items) {
                    // Copy - so we don't update this while we are copying from it...
                    Bag<T>  copiedItems =   items;
                    For (it, copiedItems) {
                        _GetRep ().Add (it.Current ());
                    }
                }
                else {
                    For (it, items) {
                        _GetRep ().Add (it.Current ());
                    }
                }
            }
            template    <typename T>
            void  Bag<T>::Add (const T* begin, const T* end)
            {
                for (const T* i = begin; i != end; i++) {
                    Add (*i);
                }
            }
            template    <typename T>
            inline  void  Bag<T>::Remove (T item)
            {
                _GetRep ().Remove (item);
            }
            template    <typename T>
            void  Bag<T>::Remove (const Bag<T>& items)
            {
                if (&_GetRep () == &items._GetRep ()) {
                    RemoveAll ();
                }
                else {
                    For (it, items) {
                        _GetRep ().Remove (it.Current ());
                    }
                }
            }
            template    <typename T>
            size_t    Bag<T>::TallyOf (T item) const
            {
                size_t count = 0;
                For (it, (*this)) {
                    if (it.Current () == item) {
                        count++;
                    }
                }
                return (count);
            }

            /*
             ********************************************************************************
             ************************************ operators *********************************
             ********************************************************************************
             */
            template    <typename T>
            bool  operator== (const Bag<T>& lhs, const Bag<T>& rhs)
            {
                if (&lhs._GetRep () == &rhs._GetRep ()) {
                    return (true);
                }
                if (lhs.GetLength () != rhs.GetLength ()) {
                    return (false);
                }

                // n^2 algorithm!!!
                For (it, lhs) {
                    if (lhs.TallyOf (it.Current ()) != rhs.TallyOf (it.Current ())) {
                        return (false);
                    }
                }
                return (true);
            }
            template    <typename T>
            Bag<T>    operator+ (const Bag<T>& lhs, const Bag<T>& rhs)
            {
                Bag<T>  temp    = lhs;
                temp += rhs;
                return (temp);
            }
            template    <typename T>
            Bag<T>    operator- (const Bag<T>& lhs, const Bag<T>& rhs)
            {
                Bag<T>  temp    = lhs;
                temp -= rhs;
                return (temp);
            }
            template    <typename T>
            inline  bool    operator!= (const Bag<T>& lhs, const Bag<T>& rhs)
            {
                return (not operator== (lhs, rhs));
            }

            // class Bag<T>::_IMutatorRep<T>
            template    <typename T>
            inline  Bag<T>::_IMutatorRep::_IMutatorRep () :
                Iterator<T>::Rep ()
            {
            }

            // class Bag<T>::Mutator
            template    <typename T>
            inline  Bag<T>::Mutator::Mutator (typename Bag<T>::_IMutatorRep* it) :
                Iterator<T> (it)
            {
            }
            template    <typename T>
            inline  typename    Bag<T>::_IMutatorRep* Bag<T>::Mutator::GetMutatorRep_ ()
            {
                /*
                 * Because of the way we construct Mutators, it is guaranteed that
                 * this cast is safe. We could have kept an extra var of the right
                 * static type, but this would have been a waste of time and memory.
                 */
                return &(dynamic_cast<_IMutatorRep&> (*this->fIterator));
            }
            template    <typename T>
            inline  void    Bag<T>::Mutator::RemoveCurrent ()
            {
                GetMutatorRep_ ()->RemoveCurrent ();
            }
            template    <typename T>
            inline  void    Bag<T>::Mutator::UpdateCurrent (T newValue)
            {
                GetMutatorRep_ ()->UpdateCurrent (newValue);
            }

            // class _IRep<T>
            template    <typename T>
            inline  Bag<T>::_IRep::_IRep ()
            {
            }
            template    <typename T>
            inline  Bag<T>::_IRep::~_IRep ()
            {
            }
            template    <typename T>
            inline  const typename  Bag<T>::_IRep&    Bag<T>::_GetRep () const
            {
                // Unsure - MAY need to use dynamic_cast here - but I think static cast performs better, so try...
                EnsureNotNull (dynamic_cast<const Bag<T>::_IRep*> (&Iterable<T>::_GetRep ()));
                return *static_cast<const Bag<T>::_IRep*> (&Iterable<T>::_GetRep ());
            }
            template    <typename T>
            inline  typename    Bag<T>::_IRep&  Bag<T>::_GetRep ()
            {
                // Unsure - MAY need to use dynamic_cast here - but I think static cast performs better, so try...
                EnsureNotNull (dynamic_cast<Bag<T>::_IRep*> (&Iterable<T>::_GetRep ()));
                return *static_cast<Bag<T>::_IRep*> (&Iterable<T>::_GetRep ());
            }

        }
    }
}

#endif /* _Stroika_Foundation_Containers_Bag_inl_ */
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#if     qPlatform_POSIX
#include    <string>
#include    <unistd.h>
#include    <sys/ptrace.h>
#include    <signal.h>
#include    <cstdio>
#elif   qPlatform_Windows
#include    <Windows.h>
#endif
#include    "../Math/Common.h"

#include    "Debugger.h"

using   namespace   Stroika::Foundation;

void    Debug::DropIntoDebuggerIfPresent ()
{
#if     qPlatform_Windows
    if (::IsDebuggerPresent ()) {
        ::DebugBreak ();
    }
#elif   qPlatform_POSIX
#if     0
    // not sure this is right, but its close...
    if (ptrace (PTRACE_TRACEME, 0, NULL, 0) == -1) {
        raise (SIGTRAP);
    }
#elif   1
    // BAD, but least bad, way I know...
    char pathBuf[1024];
    sprintf(pathBuf, "/proc/%d/exe", ::getppid ());
    char dataBuf[1024];
    ssize_t n   =   :: readlink (pathBuf, dataBuf, sizeof (dataBuf) - 1);
    n = Math::PinInRange<size_t> (0, sizeof (dataBuf) - 1, static_cast<size_t> (n));
    dataBuf[n] = '\0';
    if (string (dataBuf).find ("gdb") != -1) {
        ::raise (SIGTRAP);
    }
#else
    // NYI
#endif
#else
    // not sure (yet) how to tell if being debugged...
    //abort ();
#endif
}
<commit_msg>fixed regression in clean toDebug::DropIntoDebuggerIfPresent () - use of PinInRnage()<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#if     qPlatform_POSIX
#include    <string>
#include    <unistd.h>
#include    <sys/ptrace.h>
#include    <signal.h>
#include    <cstdio>
#elif   qPlatform_Windows
#include    <Windows.h>
#endif
#include    "../Math/Common.h"

#include    "Debugger.h"

using   namespace   Stroika::Foundation;

void    Debug::DropIntoDebuggerIfPresent ()
{
#if     qPlatform_Windows
    if (::IsDebuggerPresent ()) {
        ::DebugBreak ();
    }
#elif   qPlatform_POSIX
#if     0
    // not sure this is right, but its close...
    if (ptrace (PTRACE_TRACEME, 0, NULL, 0) == -1) {
        raise (SIGTRAP);
    }
#elif   1
    // BAD, but least bad, way I know...
    char pathBuf[1024];
    sprintf(pathBuf, "/proc/%d/exe", ::getppid ());
    char dataBuf[1024];
    ssize_t n   =   :: readlink (pathBuf, dataBuf, sizeof (dataBuf) - 1);
    n = Math::PinInRange<size_t> (static_cast<size_t> (n), 0, sizeof (dataBuf) - 1);
    dataBuf[n] = '\0';
    if (string (dataBuf).find ("gdb") != -1) {
        ::raise (SIGTRAP);
    }
#else
    // NYI
#endif
#else
    // not sure (yet) how to tell if being debugged...
    //abort ();
#endif
}
<|endoftext|>


<commit_before>//=============================================================================
// ■ global.hpp
//-----------------------------------------------------------------------------
//   VMDE通用C++头文件。
//=============================================================================

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <ruby.h>

#include <cstdlib>
#include <cstdio>
#include <stdexcept>
#include <string>

#include <ctime>

#ifndef _INCLUDE_ENGINE_H
#define _INCLUDE_ENGINE_H

#define GAME_NAME "VM / 76"
#define DBG_HEAD "VM DBG [C][VMDrawEngine]"
#define RB_F_R VALUE(*)(ANYARGS) // Ruby Function Return Type

// PY Deal For MICR0$0FT Windoges ()
// Becuase it;s Windoges, I jsut dno't want to use CORERCT ENGRISh &忠闻吔屎炉此
#ifdef __MINGW32__
#include <windows.h>
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif

// Global
typedef struct _VMDE_State_t {
	bool freeze;
} VMDE_State_t;

typedef struct _VMDE_t {
	VMDE_State_t* States;
	long frame_count;
	long millisecond;
	int fps;
} VMDE_t;

extern VMDE_t* VMDE;
extern GLFWwindow* window;
extern VALUE Global_module;
extern VALUE GResPic;

// ruby_connection.cpp
VALUE warp_load_pic(VALUE self, VALUE path);
VALUE wrap_init_engine(VALUE self, VALUE w, VALUE h);
VALUE warp_main_draw_loop();
VALUE warp_main_get_frame_count();
VALUE warp_main_get_fps();

// init.cpp
int init_engine(int w, int h);
void init_RClass();
void init_RModule();

// main.cpp
void glfw_error_callback(int error, const char* description);
void main_draw_loop();

// resources.cpp
int load_img(char* p);

#endif
<commit_msg>日常黑Windows<commit_after>//=============================================================================
// ■ global.hpp
//-----------------------------------------------------------------------------
//   VMDE通用C++头文件。
//=============================================================================

#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <ruby.h>

#include <cstdlib>
#include <cstdio>
#include <stdexcept>
#include <string>

#include <ctime>

#ifndef _INCLUDE_ENGINE_H
#define _INCLUDE_ENGINE_H

#define GAME_NAME "VM / 76"
#define DBG_HEAD "VM DBG [C][VMDrawEngine]"
#define RB_F_R VALUE(*)(ANYARGS) // Ruby Function Return Type

// PY Deal For ＭICR0$○F┬ Ｗindoges (ᴚ)
// Becuase it;s Windoges, I jsut dno't want to use CORERCT ENGRISh &忠闻吔屎炉此
#ifdef __MINGW32__
#include <windows.h>
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif

// Global
typedef struct _VMDE_State_t {
	bool freeze;
} VMDE_State_t;

typedef struct _VMDE_t {
	VMDE_State_t* States;
	long frame_count;
	long millisecond;
	int fps;
} VMDE_t;

extern VMDE_t* VMDE;
extern GLFWwindow* window;
extern VALUE Global_module;
extern VALUE GResPic;

// ruby_connection.cpp
VALUE warp_load_pic(VALUE self, VALUE path);
VALUE wrap_init_engine(VALUE self, VALUE w, VALUE h);
VALUE warp_main_draw_loop();
VALUE warp_main_get_frame_count();
VALUE warp_main_get_fps();

// init.cpp
int init_engine(int w, int h);
void init_RClass();
void init_RModule();

// main.cpp
void glfw_error_callback(int error, const char* description);
void main_draw_loop();

// resources.cpp
int load_img(char* p);

#endif
<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkCESTImageNormalizationFilter.h"

#include <mitkCustomTagParser.h>
#include <mitkImage.h>
#include <mitkImageAccessByItk.h>
#include <mitkImageCast.h>

#include <boost/algorithm/string.hpp>

mitk::CESTImageNormalizationFilter::CESTImageNormalizationFilter()
{
}

mitk::CESTImageNormalizationFilter::~CESTImageNormalizationFilter()
{
}

void mitk::CESTImageNormalizationFilter::GenerateData()
{
  mitk::Image::ConstPointer inputImage = this->GetInput(0);
  if ((inputImage->GetDimension() != 4))
  {
    mitkThrow() << "mitk::CESTImageNormalizationFilter:GenerateData works only with 4D images, sorry.";
    return;
  }

  auto resultMitkImage = this->GetOutput();
  AccessFixedDimensionByItk(inputImage, NormalizeTimeSteps, 4);

  auto originalTimeGeometry = this->GetInput()->GetTimeGeometry();
  auto resultTimeGeometry = mitk::ProportionalTimeGeometry::New();

  unsigned int numberOfNonM0s = m_NonM0Indices.size();
  resultTimeGeometry->Expand(numberOfNonM0s);

  for (unsigned int index = 0; index < numberOfNonM0s; ++index)
  {
    resultTimeGeometry->SetTimeStepGeometry(originalTimeGeometry->GetGeometryCloneForTimeStep(m_NonM0Indices.at(index)), index);
  }
  resultMitkImage->SetTimeGeometry(resultTimeGeometry);

  resultMitkImage->SetPropertyList(this->GetInput()->GetPropertyList()->Clone());
  resultMitkImage->GetPropertyList()->SetStringProperty(mitk::CustomTagParser::m_OffsetsPropertyName.c_str(), m_RealOffsets.c_str());
  // remove uids
  resultMitkImage->GetPropertyList()->DeleteProperty("DICOM.0008.0018");
  resultMitkImage->GetPropertyList()->DeleteProperty("DICOM.0020.000D");
  resultMitkImage->GetPropertyList()->DeleteProperty("DICOM.0020.000E");

}

template <typename TPixel, unsigned int VImageDimension>
void mitk::CESTImageNormalizationFilter::NormalizeTimeSteps(const itk::Image<TPixel, VImageDimension>* image)
{
  typedef itk::Image<TPixel, VImageDimension> ImageType;
  typedef itk::Image<double, VImageDimension> OutputImageType;

  std::string offsets = "";
  this->GetInput()->GetPropertyList()->GetStringProperty(mitk::CustomTagParser::m_OffsetsPropertyName.c_str(), offsets);

  std::vector<std::string> parts;
  boost::split(parts, offsets, boost::is_any_of(" "));

  // determine normalization images
  std::vector<unsigned int> mZeroIndices;
  std::stringstream offsetsWithoutM0;
  m_NonM0Indices.clear();
  for (unsigned int index = 0; index < parts.size(); ++index)
  {
    if ((std::stod(parts.at(index)) < -299) || (std::stod(parts.at(index)) > 299))
    {
      mZeroIndices.push_back(index);
    }
    else
    {
      offsetsWithoutM0 << parts.at(index) << " ";
      m_NonM0Indices.push_back(index);
    }
  }

  auto resultImage = OutputImageType::New();
  typename ImageType::RegionType targetEntireRegion = image->GetLargestPossibleRegion();
  targetEntireRegion.SetSize(3, m_NonM0Indices.size());
  resultImage->SetRegions(targetEntireRegion);
  resultImage->Allocate();
  resultImage->FillBuffer(0);

  unsigned int numberOfTimesteps = image->GetLargestPossibleRegion().GetSize(3);

  typename ImageType::RegionType lowerMZeroRegion = image->GetLargestPossibleRegion();
  lowerMZeroRegion.SetSize(3, 1);
  typename ImageType::RegionType upperMZeroRegion = image->GetLargestPossibleRegion();
  upperMZeroRegion.SetSize(3, 1);
  typename ImageType::RegionType sourceRegion = image->GetLargestPossibleRegion();
  sourceRegion.SetSize(3, 1);
  typename OutputImageType::RegionType targetRegion = resultImage->GetLargestPossibleRegion();
  targetRegion.SetSize(3, 1);
  unsigned int targetTimestep = 0;
  for (unsigned int sourceTimestep = 0; sourceTimestep < numberOfTimesteps; ++sourceTimestep)
  {
    unsigned int lowerMZeroIndex = mZeroIndices[0];
    unsigned int upperMZeroIndex = mZeroIndices[0];
    for (unsigned int loop = 0; loop < mZeroIndices.size(); ++loop)
    {
      if (mZeroIndices[loop] <= sourceTimestep)
      {
        lowerMZeroIndex = mZeroIndices[loop];
      }
      if (mZeroIndices[loop] > sourceTimestep)
      {
        upperMZeroIndex = mZeroIndices[loop];
        break;
      }
    }
    bool isMZero = (lowerMZeroIndex == sourceTimestep);

    double weight = 0.0;
    if (lowerMZeroIndex == upperMZeroIndex)
    {
      weight = 1.0;
    }
    else
    {
      weight = 1.0 - double(sourceTimestep - lowerMZeroIndex) / double(upperMZeroIndex - lowerMZeroIndex);
    }

    if (isMZero)
    {
      //do nothing
    }
    else
    {
      lowerMZeroRegion.SetIndex(3, lowerMZeroIndex);
      upperMZeroRegion.SetIndex(3, upperMZeroIndex);
      sourceRegion.SetIndex(3, sourceTimestep);
      targetRegion.SetIndex(3, targetTimestep);

      itk::ImageRegionConstIterator<ImageType> lowerMZeroIterator(image, lowerMZeroRegion);
      itk::ImageRegionConstIterator<ImageType> upperMZeroIterator(image, upperMZeroRegion);
      itk::ImageRegionConstIterator<ImageType> sourceIterator(image, sourceRegion);
      itk::ImageRegionIterator<OutputImageType> targetIterator(resultImage.GetPointer(), targetRegion);

      while (!sourceIterator.IsAtEnd())
      {
        double normalizationFactor = weight * lowerMZeroIterator.Get() + (1.0 - weight) * upperMZeroIterator.Get();
        if (mitk::Equal(normalizationFactor, 0))
        {
          targetIterator.Set(0);
        }
        else
        {
          targetIterator.Set(double(sourceIterator.Get()) / normalizationFactor);
        }

        ++lowerMZeroIterator;
        ++upperMZeroIterator;
        ++sourceIterator;
        ++targetIterator;
      }
      ++targetTimestep;
    }
  }

  // get  Pointer to output image
  mitk::Image::Pointer resultMitkImage = this->GetOutput();
  // write into output image
  mitk::CastToMitkImage<OutputImageType>(resultImage, resultMitkImage);

  m_RealOffsets = offsetsWithoutM0.str();
}

void mitk::CESTImageNormalizationFilter::GenerateOutputInformation()
{
  mitk::Image::ConstPointer input = this->GetInput();
  mitk::Image::Pointer output = this->GetOutput();

  itkDebugMacro(<< "GenerateOutputInformation()");
}
<commit_msg>Use C locale for normalizing<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkCESTImageNormalizationFilter.h"

#include <mitkCustomTagParser.h>
#include <mitkImage.h>
#include <mitkImageAccessByItk.h>
#include <mitkImageCast.h>
#include <mitkLocaleSwitch.h>

#include <boost/algorithm/string.hpp>

mitk::CESTImageNormalizationFilter::CESTImageNormalizationFilter()
{
}

mitk::CESTImageNormalizationFilter::~CESTImageNormalizationFilter()
{
}

void mitk::CESTImageNormalizationFilter::GenerateData()
{
  mitk::Image::ConstPointer inputImage = this->GetInput(0);
  if ((inputImage->GetDimension() != 4))
  {
    mitkThrow() << "mitk::CESTImageNormalizationFilter:GenerateData works only with 4D images, sorry.";
    return;
  }

  auto resultMitkImage = this->GetOutput();
  AccessFixedDimensionByItk(inputImage, NormalizeTimeSteps, 4);

  auto originalTimeGeometry = this->GetInput()->GetTimeGeometry();
  auto resultTimeGeometry = mitk::ProportionalTimeGeometry::New();

  unsigned int numberOfNonM0s = m_NonM0Indices.size();
  resultTimeGeometry->Expand(numberOfNonM0s);

  for (unsigned int index = 0; index < numberOfNonM0s; ++index)
  {
    resultTimeGeometry->SetTimeStepGeometry(originalTimeGeometry->GetGeometryCloneForTimeStep(m_NonM0Indices.at(index)), index);
  }
  resultMitkImage->SetTimeGeometry(resultTimeGeometry);

  resultMitkImage->SetPropertyList(this->GetInput()->GetPropertyList()->Clone());
  resultMitkImage->GetPropertyList()->SetStringProperty(mitk::CustomTagParser::m_OffsetsPropertyName.c_str(), m_RealOffsets.c_str());
  // remove uids
  resultMitkImage->GetPropertyList()->DeleteProperty("DICOM.0008.0018");
  resultMitkImage->GetPropertyList()->DeleteProperty("DICOM.0020.000D");
  resultMitkImage->GetPropertyList()->DeleteProperty("DICOM.0020.000E");

}

template <typename TPixel, unsigned int VImageDimension>
void mitk::CESTImageNormalizationFilter::NormalizeTimeSteps(const itk::Image<TPixel, VImageDimension>* image)
{
  mitk::LocaleSwitch localeSwitch("C");
  typedef itk::Image<TPixel, VImageDimension> ImageType;
  typedef itk::Image<double, VImageDimension> OutputImageType;

  std::string offsets = "";
  this->GetInput()->GetPropertyList()->GetStringProperty(mitk::CustomTagParser::m_OffsetsPropertyName.c_str(), offsets);

  std::vector<std::string> parts;
  boost::split(parts, offsets, boost::is_any_of(" "));

  // determine normalization images
  std::vector<unsigned int> mZeroIndices;
  std::stringstream offsetsWithoutM0;
  m_NonM0Indices.clear();
  for (unsigned int index = 0; index < parts.size(); ++index)
  {
    if ((std::stod(parts.at(index)) < -299) || (std::stod(parts.at(index)) > 299))
    {
      mZeroIndices.push_back(index);
    }
    else
    {
      offsetsWithoutM0 << parts.at(index) << " ";
      m_NonM0Indices.push_back(index);
    }
  }

  auto resultImage = OutputImageType::New();
  typename ImageType::RegionType targetEntireRegion = image->GetLargestPossibleRegion();
  targetEntireRegion.SetSize(3, m_NonM0Indices.size());
  resultImage->SetRegions(targetEntireRegion);
  resultImage->Allocate();
  resultImage->FillBuffer(0);

  unsigned int numberOfTimesteps = image->GetLargestPossibleRegion().GetSize(3);

  typename ImageType::RegionType lowerMZeroRegion = image->GetLargestPossibleRegion();
  lowerMZeroRegion.SetSize(3, 1);
  typename ImageType::RegionType upperMZeroRegion = image->GetLargestPossibleRegion();
  upperMZeroRegion.SetSize(3, 1);
  typename ImageType::RegionType sourceRegion = image->GetLargestPossibleRegion();
  sourceRegion.SetSize(3, 1);
  typename OutputImageType::RegionType targetRegion = resultImage->GetLargestPossibleRegion();
  targetRegion.SetSize(3, 1);
  unsigned int targetTimestep = 0;
  for (unsigned int sourceTimestep = 0; sourceTimestep < numberOfTimesteps; ++sourceTimestep)
  {
    unsigned int lowerMZeroIndex = mZeroIndices[0];
    unsigned int upperMZeroIndex = mZeroIndices[0];
    for (unsigned int loop = 0; loop < mZeroIndices.size(); ++loop)
    {
      if (mZeroIndices[loop] <= sourceTimestep)
      {
        lowerMZeroIndex = mZeroIndices[loop];
      }
      if (mZeroIndices[loop] > sourceTimestep)
      {
        upperMZeroIndex = mZeroIndices[loop];
        break;
      }
    }
    bool isMZero = (lowerMZeroIndex == sourceTimestep);

    double weight = 0.0;
    if (lowerMZeroIndex == upperMZeroIndex)
    {
      weight = 1.0;
    }
    else
    {
      weight = 1.0 - double(sourceTimestep - lowerMZeroIndex) / double(upperMZeroIndex - lowerMZeroIndex);
    }

    if (isMZero)
    {
      //do nothing
    }
    else
    {
      lowerMZeroRegion.SetIndex(3, lowerMZeroIndex);
      upperMZeroRegion.SetIndex(3, upperMZeroIndex);
      sourceRegion.SetIndex(3, sourceTimestep);
      targetRegion.SetIndex(3, targetTimestep);

      itk::ImageRegionConstIterator<ImageType> lowerMZeroIterator(image, lowerMZeroRegion);
      itk::ImageRegionConstIterator<ImageType> upperMZeroIterator(image, upperMZeroRegion);
      itk::ImageRegionConstIterator<ImageType> sourceIterator(image, sourceRegion);
      itk::ImageRegionIterator<OutputImageType> targetIterator(resultImage.GetPointer(), targetRegion);

      while (!sourceIterator.IsAtEnd())
      {
        double normalizationFactor = weight * lowerMZeroIterator.Get() + (1.0 - weight) * upperMZeroIterator.Get();
        if (mitk::Equal(normalizationFactor, 0))
        {
          targetIterator.Set(0);
        }
        else
        {
          targetIterator.Set(double(sourceIterator.Get()) / normalizationFactor);
        }

        ++lowerMZeroIterator;
        ++upperMZeroIterator;
        ++sourceIterator;
        ++targetIterator;
      }
      ++targetTimestep;
    }
  }

  // get  Pointer to output image
  mitk::Image::Pointer resultMitkImage = this->GetOutput();
  // write into output image
  mitk::CastToMitkImage<OutputImageType>(resultImage, resultMitkImage);

  m_RealOffsets = offsetsWithoutM0.str();
}

void mitk::CESTImageNormalizationFilter::GenerateOutputInformation()
{
  mitk::Image::ConstPointer input = this->GetInput();
  mitk::Image::Pointer output = this->GetOutput();

  itkDebugMacro(<< "GenerateOutputInformation()");
}
<|endoftext|>