<commit_before>#include "SplayTree.hpp"
#include <cassert>

namespace warped {

SplayTree::SplayTree() = default;

/* Search lowest event */
std::shared_ptr<Event> SplayTree::begin() {

    // If splay tree is invalid
    if (!root_ || !num_nodes_) {
        root_       = nullptr;
        current_    = nullptr;
        num_nodes_  = 0;

        return nullptr;
    }

    if (!current_) {
        for( current_ = root_ ; current_->left_ ; current_ = current_->left_ );
    }
    return current_->data_;
}

/* Erase event */
bool SplayTree::erase( std::shared_ptr<Event> event ) {

    assert(event && root_);

    if (!current_) {
        for( current_ = root_ ; current_->left_ ; current_ = current_->left_ );
        return false;
    }

    // Search for the event to be deleted
    // Also handles the condition when current = root
    auto node = (*event <= *current_->data_) ? current_ : root_;
    while (node) {
        if (*event < *node->data_) {
            node = node->left_;
        } else if (event == node->data_) { // Comparing address is sufficient
            break;
        } else {
            node = node->right_;
        }
    }

    if (!node) { return false; }

    // Remove the node if found
    if (node != root_) {
        splay(node);
        if (node != root_) assert(0);
    }
    auto left  = root_->left_;
    auto right = root_->right_;
    num_nodes_--;
    delete root_; // node == root_
    root_      = nullptr;

    // Re-construct the tree
    if (left) {
        root_ = left;
        root_->parent_ = nullptr;
        if (right) {
            while (left->right_) {
                left = left->right_;
            }
            left->right_    = right;
            right->parent_  = left;
        }
    } else {
        root_ = right;
        if (root_) { root_->parent_  = nullptr; }
    }

    // Re-calculate the current
    if (root_) {
        for( current_ = root_ ; current_->left_ ; current_ = current_->left_ );
    }
    return true;
}

/* Insert event */
void SplayTree::insert( std::shared_ptr<Event> event ) {

    assert(event);
    auto new_node = new SplayTree::Node();
    assert(new_node);
    new_node->data_ = event;
    num_nodes_++;

    if (!root_) {
        root_    = new_node;
        current_ = new_node;
        return;
    }

    assert(current_);
    if (!current_->data_) {
        for( current_ = root_ ; current_->left_ ; current_ = current_->left_ );
    }

    if (*event <= *current_->data_) {
        current_->left_   = new_node;
        new_node->parent_ = current_;
        current_ = new_node;
        splay(new_node);
        return;
    }

    auto node = root_;
    while (1) {
        if (*event <= *node->data_) {
            if (node->left_) {
                node = node->left_;
            } else {
                node->left_ = new_node;
                break;
            }
        } else {
            if (node->right_) {
                node = node->right_;
            } else {
                node->right_ = new_node;
                break;
            }
        }
    }
    new_node->parent_ = node;
    splay(new_node);
}

/* Splay */
void SplayTree::splay( SplayTree::Node *node ) {

    unsigned int splay_cnt  = 0;
    unsigned int max_splay  = num_nodes_ / 2;
    bool parent_flag        = false;
    bool grandpa_flag = false;

    while (node != root_) {
        auto parent = node->parent_;
        if (parent == root_) {
            if (parent->left_ == node) {
                rotateRight(parent);
            } else {
                rotateLeft(parent);
            }
            break;
        } else {
            parent_flag = (parent->left_ == node) ? false : true;
            auto grand_parent = parent->parent_;
            grandpa_flag = (grand_parent->left_ == parent) ? false : true;
            if (parent_flag != grandpa_flag) { //Zig Zag
                if (!parent_flag) {
                    rotateRight(parent);
                    rotateLeft(grand_parent);
                } else {
                    rotateLeft(parent);
                    rotateRight(grand_parent);
                }
            } else { // Zig Zig
                if (!parent_flag) {
                    rotateRight(grand_parent);
                    rotateRight(parent);
                } else {
                    rotateLeft(grand_parent);
                    rotateLeft(parent);
                }
            }
        }

        if (splay_cnt >= max_splay) break;
        splay_cnt++;
    }
}

/* Rotate Left */
SplayTree::Node *SplayTree::rotateLeft( SplayTree::Node *node ) {

    if (!node) return nullptr;

    auto right = node->right_;
    if (!right) { return node; }

    auto left       = right->left_;
    auto parent     = node->parent_;
    node->parent_   = right;
    right->left_    = node;
    node->right_    = left;

    if (left) { left->parent_ = node; }
    if (node == root_) {
        root_ = right;
        root_->parent_ = nullptr;

    } else {
        right->parent_ = parent;
        if (parent->left_ == node) {
            parent->left_ = right;
        } else {
            parent->right_ = right;
        }
    }
    return right;
}

/* Rotate Right */
SplayTree::Node *SplayTree::rotateRight( SplayTree::Node *node ) {

    if (!node) return nullptr;

    auto left = node->left_;
    if (!left) { return node; }

    auto right      = left->right_;
    auto parent     = node->parent_;
    node->parent_   = left;
    left->right_    = node;
    node->left_     = right;

    if (right) { right->parent_ = node; }
    if (node == root_) {
        root_ = left;
        root_->parent_ = nullptr;

    } else {
        left->parent_ = parent;
        if (parent->left_ == node) {
            parent->left_ = left;
        } else {
            parent->right_ = left;
        }
    }
    return left;
}

} // namespace warped
<commit_msg>moved the assert to the old format<commit_after>#include "SplayTree.hpp"
#include <cassert>

namespace warped {

SplayTree::SplayTree() = default;

/* Search lowest event */
std::shared_ptr<Event> SplayTree::begin() {

    // If splay tree is invalid
    if (!root_ || !num_nodes_) {
        root_       = nullptr;
        current_    = nullptr;
        num_nodes_  = 0;

        return nullptr;
    }

    if (!current_) {
        for( current_ = root_ ; current_->left_ ; current_ = current_->left_ );
    }
    return current_->data_;
}

/* Erase event */
bool SplayTree::erase( std::shared_ptr<Event> event ) {

    assert(event);
    assert(root_);

    if (!current_) {
        for( current_ = root_ ; current_->left_ ; current_ = current_->left_ );
        return false;
    }

    // Search for the event to be deleted
    // Also handles the condition when current = root
    auto node = (*event <= *current_->data_) ? current_ : root_;
    while (node) {
        if (*event < *node->data_) {
            node = node->left_;
        } else if (event == node->data_) { // Comparing address is sufficient
            break;
        } else {
            node = node->right_;
        }
    }

    if (!node) { return false; }

    // Remove the node if found
    if (node != root_) {
        splay(node);
        if (node != root_) assert(0);
    }
    auto left  = root_->left_;
    auto right = root_->right_;
    num_nodes_--;
    delete root_; // node == root_
    root_      = nullptr;

    // Re-construct the tree
    if (left) {
        root_ = left;
        root_->parent_ = nullptr;
        if (right) {
            while (left->right_) {
                left = left->right_;
            }
            left->right_    = right;
            right->parent_  = left;
        }
    } else {
        root_ = right;
        if (root_) { root_->parent_  = nullptr; }
    }

    // Re-calculate the current
    if (root_) {
        for( current_ = root_ ; current_->left_ ; current_ = current_->left_ );
    }
    return true;
}

/* Insert event */
void SplayTree::insert( std::shared_ptr<Event> event ) {

    assert(event);
    auto new_node = new SplayTree::Node();
    assert(new_node);
    new_node->data_ = event;
    num_nodes_++;

    if (!root_) {
        root_    = new_node;
        current_ = new_node;
        return;
    }

    assert(current_);
    if (!current_->data_) {
        for( current_ = root_ ; current_->left_ ; current_ = current_->left_ );
    }

    if (*event <= *current_->data_) {
        current_->left_   = new_node;
        new_node->parent_ = current_;
        current_ = new_node;
        splay(new_node);
        return;
    }

    auto node = root_;
    while (1) {
        if (*event <= *node->data_) {
            if (node->left_) {
                node = node->left_;
            } else {
                node->left_ = new_node;
                break;
            }
        } else {
            if (node->right_) {
                node = node->right_;
            } else {
                node->right_ = new_node;
                break;
            }
        }
    }
    new_node->parent_ = node;
    splay(new_node);
}

/* Splay */
void SplayTree::splay( SplayTree::Node *node ) {

    unsigned int splay_cnt  = 0;
    unsigned int max_splay  = num_nodes_ / 2;
    bool parent_flag        = false;
    bool grandpa_flag = false;

    while (node != root_) {
        auto parent = node->parent_;
        if (parent == root_) {
            if (parent->left_ == node) {
                rotateRight(parent);
            } else {
                rotateLeft(parent);
            }
            break;
        } else {
            parent_flag = (parent->left_ == node) ? false : true;
            auto grand_parent = parent->parent_;
            grandpa_flag = (grand_parent->left_ == parent) ? false : true;
            if (parent_flag != grandpa_flag) { //Zig Zag
                if (!parent_flag) {
                    rotateRight(parent);
                    rotateLeft(grand_parent);
                } else {
                    rotateLeft(parent);
                    rotateRight(grand_parent);
                }
            } else { // Zig Zig
                if (!parent_flag) {
                    rotateRight(grand_parent);
                    rotateRight(parent);
                } else {
                    rotateLeft(grand_parent);
                    rotateLeft(parent);
                }
            }
        }

        if (splay_cnt >= max_splay) break;
        splay_cnt++;
    }
}

/* Rotate Left */
SplayTree::Node *SplayTree::rotateLeft( SplayTree::Node *node ) {

    if (!node) return nullptr;

    auto right = node->right_;
    if (!right) { return node; }

    auto left       = right->left_;
    auto parent     = node->parent_;
    node->parent_   = right;
    right->left_    = node;
    node->right_    = left;

    if (left) { left->parent_ = node; }
    if (node == root_) {
        root_ = right;
        root_->parent_ = nullptr;

    } else {
        right->parent_ = parent;
        if (parent->left_ == node) {
            parent->left_ = right;
        } else {
            parent->right_ = right;
        }
    }
    return right;
}

/* Rotate Right */
SplayTree::Node *SplayTree::rotateRight( SplayTree::Node *node ) {

    if (!node) return nullptr;

    auto left = node->left_;
    if (!left) { return node; }

    auto right      = left->right_;
    auto parent     = node->parent_;
    node->parent_   = left;
    left->right_    = node;
    node->left_     = right;

    if (right) { right->parent_ = node; }
    if (node == root_) {
        root_ = left;
        root_->parent_ = nullptr;

    } else {
        left->parent_ = parent;
        if (parent->left_ == node) {
            parent->left_ = left;
        } else {
            parent->right_ = left;
        }
    }
    return left;
}

} // namespace warped
<|endoftext|>


<commit_before>// StringUtil.cc for fluxbox
// Copyright (c) 2001 Henrik Kinnunen (fluxgen@linuxmail.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.	IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include "StringUtil.hh"

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

//------- strdup ------------------------
//TODO: comment this
//----------------------------------------
char *StringUtil::strdup(const char *s) {
  int l = strlen(s) + 1;
  char *n = new char[l];
  strncpy(n, s, l);
  return n;
}

//------- strcasestr --------------
// TODO: comment this
//---------------------------------
const char * StringUtil::strcasestr(const char *str, const char *ptn) {
	const char *s2, *p2;
	for( ; *str; str++) {
		for(s2=str,p2=ptn; ; s2++,p2++) {
			if (!*p2) return str;
			if (toupper(*s2) != toupper(*p2)) break;
		}
	}
	return 0;
}

//------------- expandFilename ----------------------
// if ~ then expand it to home of user
// returns expanded filename
// (note: the function creates new memory for the string)
//---------------------------------------------------
char *StringUtil::expandFilename(const char *filename) {

	char retval[strlen(filename)+strlen(getenv("HOME"))+2];
  retval[0]=0; //mark end
  if (filename[0]=='~') {
    strcat(retval, getenv("HOME"));
    strcat(retval, &filename[1]);
  } else
    return StringUtil::strdup(filename);	//return unmodified value

  return StringUtil::strdup(retval);	//return modified value
}
<commit_msg>Changed to auto_ptr and added comment<commit_after>// StringUtil.cc for fluxbox
// Copyright (c) 2001 Henrik Kinnunen (fluxgen@linuxmail.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.	IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include "StringUtil.hh"

#include <string>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <memory>

using namespace std;

//------- strdup ------------------------
//TODO: comment this
//----------------------------------------
char *StringUtil::strdup(const char *s) {
  int l = strlen(s) + 1;
  char *n = new char[l];
  strncpy(n, s, l);
  return n;
}

//------- strcasestr --------------
// Tries to find a string in another and
// ignoring the case of the characters
// Returns 0 on success else pointer to str.
// TODO: comment this
//---------------------------------
const char * StringUtil::strcasestr(const char *str, const char *ptn) {
	const char *s2, *p2;
	for( ; *str; str++) {
		for(s2=str, p2=ptn; ; s2++,p2++) {
			if (!*p2) return str;
			if (toupper(*s2) != toupper(*p2)) break;
		}
	}
	return 0;
}

//------------- expandFilename ----------------------
// if ~ then expand it to home of user
// returns expanded filename
// (note: the function creates new memory for the string)
//---------------------------------------------------
char *StringUtil::expandFilename(const char *filename) {

	auto_ptr<char> retval( new char[strlen(filename)+strlen(getenv("HOME"))+2]);
  if (filename[0]=='~') {
    strcat(retval.get(), getenv("HOME"));
    strcat(retval.get(), &filename[1]);
  } else
    return StringUtil::strdup(filename);	//return unmodified value

  return StringUtil::strdup(retval.get());	//return modified value
}
<|endoftext|>


<commit_before>/* Copyright (c) 2009 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <getopt.h>
#include <stdlib.h>
#include <string.h>

#include <cppunit/CompilerOutputter.h>
#include <cppunit/Message.h>
#include <cppunit/Protector.h>
#include <cppunit/TestResult.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/extensions/TypeInfoHelper.h>
#include <cppunit/ui/text/TestRunner.h>
#include <gtest/gtest.h>

#include <typeinfo>

#include "Common.h"
#include "ClientException.h"

char testName[256];
bool progress = false;
bool googleOnly = false;

void __attribute__ ((noreturn))
usage(char *arg0)
{
    printf("Usage: %s "
            "[-p] [-t testName]\n"
           "\t-t\t--test\tRun a specific test..\n"
           "\t-p\t--progress\tShow test progress.\n",
           "\t-g\t--google\tRun google tests only.\n",
           arg0);
    exit(EXIT_FAILURE);
}

void
cmdline(int argc, char *argv[])
{
    struct option long_options[] = {
        {"test", required_argument, NULL, 't'},
        {"progress", no_argument, NULL, 'p'},
        {"google", no_argument, NULL, 'g'},
        {0, 0, 0, 0},
    };

    int c;
    int i = 0;
    while ((c = getopt_long(argc, argv, "t:pg",
                            long_options, &i)) >= 0)
    {
        switch (c) {
        case 't':
            strncpy(testName, optarg, sizeof(testName));
            testName[sizeof(testName) - 1] = '\0';
            break;
        case 'p':
            progress = true;
            break;
        case 'g':
            googleOnly = true;
            break;
        default:
            usage(argv[0]);
        }
    }
}

// CppUnit doesn't put this in a public header
struct CppUnit::ProtectorContext {
    void* _[2];
    std::string description;
};

int
main(int argc, char *argv[])
{
    int googleArgc = 0;
    char* googleArgv[] = {NULL};
    ::testing::InitGoogleTest(&googleArgc, googleArgv);

    const char *defaultTest = "";
    strncpy(testName, defaultTest, sizeof(testName));
    cmdline(argc, argv);

    CppUnit::TextUi::TestRunner runner;
    CppUnit::TestFactoryRegistry& registry =
            CppUnit::TestFactoryRegistry::getRegistry();

    // This thing will print RAMCloud::Exception::message when RAMCloud
    // exceptions are thrown in our unit tests.
    class RAMCloudProtector : public CppUnit::Protector {
        bool protect(const CppUnit::Functor& functor,
                     const CppUnit::ProtectorContext& context) {
            if (context.description == "setUp() failed")
                RAMCloud::logger.setLogLevels(RAMCloud::WARNING);
            try {
                return functor();
            } catch (const RAMCloud::Exception& e) {
                std::string className(
                    CppUnit::TypeInfoHelper::getClassName(typeid(e)));
                CppUnit::Message message(className + ":\n    " + e.str());
                reportError(context, message);
            } catch (const RAMCloud::ClientException& e) {
                std::string className(
                    CppUnit::TypeInfoHelper::getClassName(typeid(e)));
                CppUnit::Message message(className + ":\n    " + e.str());
                reportError(context, message);
            }
            return false;
        }
    };
    // CppUnit's ProtectorChain::pop() will call delete on our protector, so I
    // guess they want us to use new to allocate it.
    runner.eventManager().pushProtector(new RAMCloudProtector());

    runner.addTest(registry.makeTest());

    // set log levels for gtest unit tests
    struct LoggerEnvironment : public ::testing::Environment {
        void SetUp() { RAMCloud::logger.setLogLevels(RAMCloud::WARNING); }
    };
    ::testing::AddGlobalTestEnvironment(new LoggerEnvironment());

    int r = 0;
    if (!googleOnly)
        r += !runner.run(testName, false, true, progress);
    if (googleOnly || !strcmp(testName, defaultTest))
        r += RUN_ALL_TESTS();
    return r;
}
<commit_msg>Change the order of tests to run gtests first (so that the cppunit output doesn't get scrolled out of sight by the voluminous gtest output).<commit_after>/* Copyright (c) 2009 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <getopt.h>
#include <stdlib.h>
#include <string.h>

#include <cppunit/CompilerOutputter.h>
#include <cppunit/Message.h>
#include <cppunit/Protector.h>
#include <cppunit/TestResult.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/extensions/TypeInfoHelper.h>
#include <cppunit/ui/text/TestRunner.h>
#include <gtest/gtest.h>

#include <typeinfo>

#include "Common.h"
#include "ClientException.h"

char testName[256];
bool progress = false;
bool googleOnly = false;

void __attribute__ ((noreturn))
usage(char *arg0)
{
    printf("Usage: %s "
            "[-p] [-t testName]\n"
           "\t-t\t--test\tRun a specific test..\n"
           "\t-p\t--progress\tShow test progress.\n",
           "\t-g\t--google\tRun google tests only.\n",
           arg0);
    exit(EXIT_FAILURE);
}

void
cmdline(int argc, char *argv[])
{
    struct option long_options[] = {
        {"test", required_argument, NULL, 't'},
        {"progress", no_argument, NULL, 'p'},
        {"google", no_argument, NULL, 'g'},
        {0, 0, 0, 0},
    };

    int c;
    int i = 0;
    while ((c = getopt_long(argc, argv, "t:pg",
                            long_options, &i)) >= 0)
    {
        switch (c) {
        case 't':
            strncpy(testName, optarg, sizeof(testName));
            testName[sizeof(testName) - 1] = '\0';
            break;
        case 'p':
            progress = true;
            break;
        case 'g':
            googleOnly = true;
            break;
        default:
            usage(argv[0]);
        }
    }
}

// CppUnit doesn't put this in a public header
struct CppUnit::ProtectorContext {
    void* _[2];
    std::string description;
};

int
main(int argc, char *argv[])
{
    int googleArgc = 0;
    char* googleArgv[] = {NULL};
    ::testing::InitGoogleTest(&googleArgc, googleArgv);

    const char *defaultTest = "";
    strncpy(testName, defaultTest, sizeof(testName));
    cmdline(argc, argv);

    // First run gtest tests.
    // set log levels for gtest unit tests
    struct LoggerEnvironment : public ::testing::Environment {
        void SetUp() { RAMCloud::logger.setLogLevels(RAMCloud::WARNING); }
    };
    ::testing::AddGlobalTestEnvironment(new LoggerEnvironment());

    int r = 0;
    if (googleOnly || !strcmp(testName, defaultTest))
        r += RUN_ALL_TESTS();

    // Next run cppunit tests.

    CppUnit::TextUi::TestRunner runner;
    CppUnit::TestFactoryRegistry& registry =
            CppUnit::TestFactoryRegistry::getRegistry();

    // This thing will print RAMCloud::Exception::message when RAMCloud
    // exceptions are thrown in our unit tests.
    class RAMCloudProtector : public CppUnit::Protector {
        bool protect(const CppUnit::Functor& functor,
                     const CppUnit::ProtectorContext& context) {
            if (context.description == "setUp() failed")
                RAMCloud::logger.setLogLevels(RAMCloud::WARNING);
            try {
                return functor();
            } catch (const RAMCloud::Exception& e) {
                std::string className(
                    CppUnit::TypeInfoHelper::getClassName(typeid(e)));
                CppUnit::Message message(className + ":\n    " + e.str());
                reportError(context, message);
            } catch (const RAMCloud::ClientException& e) {
                std::string className(
                    CppUnit::TypeInfoHelper::getClassName(typeid(e)));
                CppUnit::Message message(className + ":\n    " + e.str());
                reportError(context, message);
            }
            return false;
        }
    };
    // CppUnit's ProtectorChain::pop() will call delete on our protector, so I
    // guess they want us to use new to allocate it.
    runner.eventManager().pushProtector(new RAMCloudProtector());
    runner.addTest(registry.makeTest());
    if (!googleOnly)
        r += !runner.run(testName, false, true, progress);

    return r;
}
<|endoftext|>


<commit_before>#include "algorithm8.hpp"
#include <unordered_set>
#include <distributions/random.hpp>
#include <distributions/vector_math.hpp>
#include <distributions/trivial_hash.hpp>

#define LOOM_ASSERT_CLOSE(x, y) \
    LOOM_ASSERT_LT(fabs((x) - (y)) / ((x) + (y) + 1e-20), 1e-4)

namespace loom
{

void Algorithm8::clear ()
{
    model.clear();
    kinds.clear();
}

void Algorithm8::model_load (const CrossCat & cross_cat)
{
    clear();
    feature_clustering = cross_cat.feature_clustering;
    for (const auto & kind : cross_cat.kinds) {
        model.extend(kind.model);
    }
    LOOM_ASSERT_EQ(model.schema, cross_cat.schema);
}

void Algorithm8::mixture_init_empty (
        const CrossCat & cross_cat,
        rng_t & rng)
{
    const size_t kind_count = cross_cat.kinds.size();
    LOOM_ASSERT_LT(0, kind_count);
    kinds.resize(kind_count);
    for (size_t i = 0; i < kind_count; ++i) {
        const auto & counts = cross_cat.kinds[i].mixture.clustering.counts();
        kinds[i].mixture.init_unobserved(model, counts, rng);
    }
}

//----------------------------------------------------------------------------
// Block Pitman-Yor Sampler
//
// This sampler follows the math in
// $DISTRIBUTIONS_PATH/src/clustering.hpp
// distributions::Clustering<int>::PitmanYor::sample_assignments(...)

class Algorithm8::BlockPitmanYorSampler
{
public:

    BlockPitmanYorSampler (
            const distributions::Clustering<int>::PitmanYor & clustering,
            const std::vector<VectorFloat> & likelihoods,
            std::vector<uint32_t> & assignments);

    void run (size_t iterations, rng_t & rng);

    typedef std::unordered_set<uint32_t, distributions::TrivialHash<uint32_t>>
        IdSet;

private:

    void validate () const;

    float get_likelihood_empty () const;
    std::vector<uint32_t> get_counts_from_assignments () const;
    IdSet get_empty_kinds_from_counts () const;
    VectorFloat get_prior_from_counts () const;
    void add_empty_kind (size_t kindid);
    void remove_empty_kind (size_t kindid);

    static float compute_posterior (
            const VectorFloat & prior_in,
            const VectorFloat & likelihood_in,
            VectorFloat & posterior_out);

    const float alpha_;
    const float d_;
    const size_t feature_count_;
    const size_t kind_count_;
    const std::vector<VectorFloat> & likelihoods_;
    std::vector<uint32_t> & assignments_;
    std::vector<uint32_t> counts_;
    IdSet empty_kinds_;
    size_t empty_kind_count_;
    VectorFloat prior_;
    VectorFloat posterior_;
};

Algorithm8::BlockPitmanYorSampler::BlockPitmanYorSampler (
        const distributions::Clustering<int>::PitmanYor & clustering,
        const std::vector<VectorFloat> & likelihoods,
        std::vector<uint32_t> & assignments) :
    alpha_(clustering.alpha),
    d_(clustering.d),
    feature_count_(likelihoods.size()),
    kind_count_(likelihoods[0].size()),
    likelihoods_(likelihoods),
    assignments_(assignments),
    counts_(get_counts_from_assignments()),
    empty_kinds_(get_empty_kinds_from_counts()),
    empty_kind_count_(empty_kinds_.size()),
    prior_(get_prior_from_counts()),
    posterior_(kind_count_)
{
    LOOM_ASSERT_LT(0, alpha_);
    LOOM_ASSERT_LE(0, d_);
    LOOM_ASSERT_LT(d_, 1);

    LOOM_ASSERT_LT(0, likelihoods.size());
    LOOM_ASSERT_EQ(likelihoods.size(), assignments.size());
    for (const auto & likelihood : likelihoods) {
        LOOM_ASSERT_EQ(likelihood.size(), kind_count_);
    }
}

inline std::vector<uint32_t>
    Algorithm8::BlockPitmanYorSampler::get_counts_from_assignments () const
{
    std::vector<uint32_t> counts(kind_count_, 0);
    for (size_t f = 0; f < feature_count_; ++f) {
        size_t k = assignments_[f];
        LOOM_ASSERT1(k < kind_count_, "bad kind id: " << k);
        ++counts[k];
    }
    return counts;
}

inline Algorithm8::BlockPitmanYorSampler::IdSet
    Algorithm8::BlockPitmanYorSampler::get_empty_kinds_from_counts () const
{
    IdSet empty_kinds;
    for (size_t k = 0; k < kind_count_; ++k) {
        if (counts_[k] == 0) {
            empty_kinds.insert(k);
        }
    }
    return empty_kinds;
}

inline VectorFloat
    Algorithm8::BlockPitmanYorSampler::get_prior_from_counts () const
{
    VectorFloat prior(kind_count_);
    const float likelihood_empty = get_likelihood_empty();
    for (size_t k = 0; k < kind_count_; ++k) {
        if (auto count = counts_[k]) {
            prior[k] = count - d_;
        } else {
            prior[k] = likelihood_empty;
        }
    }
    return prior;
}

inline void Algorithm8::BlockPitmanYorSampler::validate () const
{
    std::vector<uint32_t> expected_counts = get_counts_from_assignments();
    for (size_t k = 0; k < kind_count_; ++k) {
        LOOM_ASSERT_EQ(counts_[k], expected_counts[k]);
    }

    LOOM_ASSERT_EQ(empty_kind_count_, empty_kinds_.size());
    for (size_t k = 0; k < kind_count_; ++k) {
        bool in_empty_kinds = (empty_kinds_.find(k) != empty_kinds_.end());
        bool has_zero_count = (counts_[k] == 0);
        LOOM_ASSERT_EQ(in_empty_kinds, has_zero_count);
    }

    VectorFloat expected_prior = get_prior_from_counts();
    for (size_t k = 0; k < kind_count_; ++k) {
        LOOM_ASSERT_CLOSE(prior_[k], expected_prior[k]);
    }
}

inline float Algorithm8::BlockPitmanYorSampler::get_likelihood_empty () const
{
    if (empty_kind_count_) {
        float nonempty_kind_count = kind_count_ - empty_kind_count_;
        return (alpha_ + d_ * nonempty_kind_count) / empty_kind_count_;
    } else {
        return 0.f;
    }
}

inline void Algorithm8::BlockPitmanYorSampler::add_empty_kind (size_t kindid)
{
    empty_kinds_.insert(kindid);
    ++empty_kind_count_;
    const float likelihood_empty = get_likelihood_empty();
    for (auto k : empty_kinds_) {
        prior_[k] = likelihood_empty;
    }
}

inline void Algorithm8::BlockPitmanYorSampler::remove_empty_kind (size_t kindid)
{
    empty_kinds_.erase(kindid);
    --empty_kind_count_;
    const float likelihood_empty = get_likelihood_empty();
    for (auto k : empty_kinds_) {
        prior_[k] = likelihood_empty;
    }
}

inline float Algorithm8::BlockPitmanYorSampler::compute_posterior (
        const VectorFloat & prior_in,
        const VectorFloat & likelihood_in,
        VectorFloat & posterior_out)
{
    const size_t size = prior_in.size();
    const float * __restrict__ prior =
        DIST_ASSUME_ALIGNED(prior_in.data());
    const float * __restrict__ likelihood =
        DIST_ASSUME_ALIGNED(likelihood_in.data());
    float * __restrict__ posterior =
        DIST_ASSUME_ALIGNED(posterior_out.data());

    float total = 0;
    for (size_t i = 0; i < size; ++i) {
        total += posterior[i] = prior[i] * likelihood[i];
    }
    return total;
}

using distributions::sample_from_likelihoods;

void Algorithm8::BlockPitmanYorSampler::run (
        size_t iterations,
        rng_t & rng)
{
    LOOM_ASSERT_LT(0, iterations);

    for (size_t i = 0; i < iterations; ++i) {
        for (size_t f = 0; f < feature_count_; ++f) {
            size_t k = assignments_[f];

            if (--counts_[k] == 0) {
                add_empty_kind(k);
            } else {
                prior_[k] = counts_[k] - d_;
            }

            const VectorFloat & likelihood = likelihoods_[f];
            float total = compute_posterior(prior_, likelihood, posterior_);
            k = sample_from_likelihoods(rng, posterior_, total);
            assignments_[f] = k;

            if (counts_[k]++ == 0) {
                remove_empty_kind(k);
            }
            prior_[k] = counts_[k] - d_;

            if (LOOM_DEBUG_LEVEL >= 3) {
                validate();
            }
        }
    }
}

void Algorithm8::infer_assignments (
        std::vector<uint32_t> & featureid_to_kindid,
        size_t iterations,
        bool parallel,
        rng_t & rng) const
{
    LOOM_ASSERT_LT(0, iterations);

    const auto seed = rng();
    const size_t feature_count = featureid_to_kindid.size();
    const size_t kind_count = kinds.size();
    std::vector<VectorFloat> likelihoods(feature_count);

    #pragma omp parallel if (parallel)
    {
        rng_t rng;

        #pragma omp for schedule(dynamic, 1)
        for (size_t f = 0; f < feature_count; ++f) {
            rng.seed(seed + f);
            VectorFloat & scores = likelihoods[f];
            scores.resize(kind_count);
            for (size_t k = 0; k < kind_count; ++k) {
                const auto & mixture = kinds[k].mixture;
                scores[k] = mixture.score_feature(model, f, rng);
            }
            distributions::scores_to_likelihoods(scores);
        }
    }

    BlockPitmanYorSampler sampler(
            feature_clustering,
            likelihoods,
            featureid_to_kindid);

    sampler.run(iterations, rng);
}

} // namespace loom
<commit_msg>Fix parallelization bug<commit_after>#include "algorithm8.hpp"
#include <unordered_set>
#include <distributions/random.hpp>
#include <distributions/vector_math.hpp>
#include <distributions/trivial_hash.hpp>

#define LOOM_ASSERT_CLOSE(x, y) \
    LOOM_ASSERT_LT(fabs((x) - (y)) / ((x) + (y) + 1e-20), 1e-4)

namespace loom
{

void Algorithm8::clear ()
{
    model.clear();
    kinds.clear();
}

void Algorithm8::model_load (const CrossCat & cross_cat)
{
    clear();
    feature_clustering = cross_cat.feature_clustering;
    for (const auto & kind : cross_cat.kinds) {
        model.extend(kind.model);
    }
    LOOM_ASSERT_EQ(model.schema, cross_cat.schema);
}

void Algorithm8::mixture_init_empty (
        const CrossCat & cross_cat,
        rng_t & rng)
{
    const size_t kind_count = cross_cat.kinds.size();
    LOOM_ASSERT_LT(0, kind_count);
    kinds.resize(kind_count);
    for (size_t i = 0; i < kind_count; ++i) {
        const auto & counts = cross_cat.kinds[i].mixture.clustering.counts();
        kinds[i].mixture.init_unobserved(model, counts, rng);
    }
}

//----------------------------------------------------------------------------
// Block Pitman-Yor Sampler
//
// This sampler follows the math in
// $DISTRIBUTIONS_PATH/src/clustering.hpp
// distributions::Clustering<int>::PitmanYor::sample_assignments(...)

class Algorithm8::BlockPitmanYorSampler
{
public:

    BlockPitmanYorSampler (
            const distributions::Clustering<int>::PitmanYor & clustering,
            const std::vector<VectorFloat> & likelihoods,
            std::vector<uint32_t> & assignments);

    void run (size_t iterations, rng_t & rng);

    typedef std::unordered_set<uint32_t, distributions::TrivialHash<uint32_t>>
        IdSet;

private:

    void validate () const;

    float get_likelihood_empty () const;
    std::vector<uint32_t> get_counts_from_assignments () const;
    IdSet get_empty_kinds_from_counts () const;
    VectorFloat get_prior_from_counts () const;
    void add_empty_kind (size_t kindid);
    void remove_empty_kind (size_t kindid);

    static float compute_posterior (
            const VectorFloat & prior_in,
            const VectorFloat & likelihood_in,
            VectorFloat & posterior_out);

    const float alpha_;
    const float d_;
    const size_t feature_count_;
    const size_t kind_count_;
    const std::vector<VectorFloat> & likelihoods_;
    std::vector<uint32_t> & assignments_;
    std::vector<uint32_t> counts_;
    IdSet empty_kinds_;
    size_t empty_kind_count_;
    VectorFloat prior_;
    VectorFloat posterior_;
};

Algorithm8::BlockPitmanYorSampler::BlockPitmanYorSampler (
        const distributions::Clustering<int>::PitmanYor & clustering,
        const std::vector<VectorFloat> & likelihoods,
        std::vector<uint32_t> & assignments) :
    alpha_(clustering.alpha),
    d_(clustering.d),
    feature_count_(likelihoods.size()),
    kind_count_(likelihoods[0].size()),
    likelihoods_(likelihoods),
    assignments_(assignments),
    counts_(get_counts_from_assignments()),
    empty_kinds_(get_empty_kinds_from_counts()),
    empty_kind_count_(empty_kinds_.size()),
    prior_(get_prior_from_counts()),
    posterior_(kind_count_)
{
    LOOM_ASSERT_LT(0, alpha_);
    LOOM_ASSERT_LE(0, d_);
    LOOM_ASSERT_LT(d_, 1);

    LOOM_ASSERT_LT(0, likelihoods.size());
    LOOM_ASSERT_EQ(likelihoods.size(), assignments.size());
    for (const auto & likelihood : likelihoods) {
        LOOM_ASSERT_EQ(likelihood.size(), kind_count_);
    }
}

inline std::vector<uint32_t>
    Algorithm8::BlockPitmanYorSampler::get_counts_from_assignments () const
{
    std::vector<uint32_t> counts(kind_count_, 0);
    for (size_t f = 0; f < feature_count_; ++f) {
        size_t k = assignments_[f];
        LOOM_ASSERT1(k < kind_count_, "bad kind id: " << k);
        ++counts[k];
    }
    return counts;
}

inline Algorithm8::BlockPitmanYorSampler::IdSet
    Algorithm8::BlockPitmanYorSampler::get_empty_kinds_from_counts () const
{
    IdSet empty_kinds;
    for (size_t k = 0; k < kind_count_; ++k) {
        if (counts_[k] == 0) {
            empty_kinds.insert(k);
        }
    }
    return empty_kinds;
}

inline VectorFloat
    Algorithm8::BlockPitmanYorSampler::get_prior_from_counts () const
{
    VectorFloat prior(kind_count_);
    const float likelihood_empty = get_likelihood_empty();
    for (size_t k = 0; k < kind_count_; ++k) {
        if (auto count = counts_[k]) {
            prior[k] = count - d_;
        } else {
            prior[k] = likelihood_empty;
        }
    }
    return prior;
}

inline void Algorithm8::BlockPitmanYorSampler::validate () const
{
    std::vector<uint32_t> expected_counts = get_counts_from_assignments();
    for (size_t k = 0; k < kind_count_; ++k) {
        LOOM_ASSERT_EQ(counts_[k], expected_counts[k]);
    }

    LOOM_ASSERT_EQ(empty_kind_count_, empty_kinds_.size());
    for (size_t k = 0; k < kind_count_; ++k) {
        bool in_empty_kinds = (empty_kinds_.find(k) != empty_kinds_.end());
        bool has_zero_count = (counts_[k] == 0);
        LOOM_ASSERT_EQ(in_empty_kinds, has_zero_count);
    }

    VectorFloat expected_prior = get_prior_from_counts();
    for (size_t k = 0; k < kind_count_; ++k) {
        LOOM_ASSERT_CLOSE(prior_[k], expected_prior[k]);
    }
}

inline float Algorithm8::BlockPitmanYorSampler::get_likelihood_empty () const
{
    if (empty_kind_count_) {
        float nonempty_kind_count = kind_count_ - empty_kind_count_;
        return (alpha_ + d_ * nonempty_kind_count) / empty_kind_count_;
    } else {
        return 0.f;
    }
}

inline void Algorithm8::BlockPitmanYorSampler::add_empty_kind (size_t kindid)
{
    empty_kinds_.insert(kindid);
    ++empty_kind_count_;
    const float likelihood_empty = get_likelihood_empty();
    for (auto k : empty_kinds_) {
        prior_[k] = likelihood_empty;
    }
}

inline void Algorithm8::BlockPitmanYorSampler::remove_empty_kind (size_t kindid)
{
    empty_kinds_.erase(kindid);
    --empty_kind_count_;
    const float likelihood_empty = get_likelihood_empty();
    for (auto k : empty_kinds_) {
        prior_[k] = likelihood_empty;
    }
}

inline float Algorithm8::BlockPitmanYorSampler::compute_posterior (
        const VectorFloat & prior_in,
        const VectorFloat & likelihood_in,
        VectorFloat & posterior_out)
{
    const size_t size = prior_in.size();
    const float * __restrict__ prior =
        DIST_ASSUME_ALIGNED(prior_in.data());
    const float * __restrict__ likelihood =
        DIST_ASSUME_ALIGNED(likelihood_in.data());
    float * __restrict__ posterior =
        DIST_ASSUME_ALIGNED(posterior_out.data());

    float total = 0;
    for (size_t i = 0; i < size; ++i) {
        total += posterior[i] = prior[i] * likelihood[i];
    }
    return total;
}

using distributions::sample_from_likelihoods;

void Algorithm8::BlockPitmanYorSampler::run (
        size_t iterations,
        rng_t & rng)
{
    LOOM_ASSERT_LT(0, iterations);

    for (size_t i = 0; i < iterations; ++i) {
        for (size_t f = 0; f < feature_count_; ++f) {
            size_t k = assignments_[f];

            if (--counts_[k] == 0) {
                add_empty_kind(k);
            } else {
                prior_[k] = counts_[k] - d_;
            }

            const VectorFloat & likelihood = likelihoods_[f];
            float total = compute_posterior(prior_, likelihood, posterior_);
            k = sample_from_likelihoods(rng, posterior_, total);
            assignments_[f] = k;

            if (counts_[k]++ == 0) {
                remove_empty_kind(k);
            }
            prior_[k] = counts_[k] - d_;

            if (LOOM_DEBUG_LEVEL >= 3) {
                validate();
            }
        }
    }
}

void Algorithm8::infer_assignments (
        std::vector<uint32_t> & featureid_to_kindid,
        size_t iterations,
        bool parallel,
        rng_t & rng) const
{
    LOOM_ASSERT_LT(0, iterations);

    const auto seed = rng();
    const size_t feature_count = featureid_to_kindid.size();
    const size_t kind_count = kinds.size();
    std::vector<VectorFloat> likelihoods(feature_count);
    for (auto & likelihood : likelihoods) {
        likelihood.resize(kind_count);
    }

    #pragma omp parallel if (parallel)
    {
        rng_t rng;

        #pragma omp for schedule(dynamic, 1)
        for (size_t f = 0; f < feature_count; ++f) {
            rng.seed(seed + f);
            VectorFloat & scores = likelihoods[f];
            for (size_t k = 0; k < kind_count; ++k) {
                const auto & mixture = kinds[k].mixture;
                scores[k] = mixture.score_feature(model, f, rng);
            }
            distributions::scores_to_likelihoods(scores);
        }
    }

    BlockPitmanYorSampler sampler(
            feature_clustering,
            likelihoods,
            featureid_to_kindid);

    sampler.run(iterations, rng);
}

} // namespace loom
<|endoftext|>


<commit_before>#ifndef ALIGNMENT_H
#define ALIGNMENT_H

#include <iostream>
#include <functional>
#include <zlib.h>
#include "utility.hpp"
#include "path.hpp"
#include "position.hpp"
#include "vg.pb.h"

#include "htslib/hfile.h"
#include "htslib/hts.h"
#include "htslib/sam.h"
#include "htslib/vcf.h"

namespace vg {

const char* const BAM_DNA_LOOKUP = "=ACMGRSVTWYHKDBN";

int hts_for_each(string& filename, function<void(Alignment&)> lambda);
int hts_for_each_parallel(string& filename, function<void(Alignment&)> lambda);
int fastq_for_each(string& filename, function<void(Alignment&)> lambda);
bool get_next_alignment_from_fastq(gzFile fp, char* buffer, size_t len, Alignment& alignment);
bool get_next_interleaved_alignment_pair_from_fastq(gzFile fp, char* buffer, size_t len, Alignment& mate1, Alignment& mate2);
bool get_next_alignment_pair_from_fastqs(gzFile fp1, gzFile fp2, char* buffer, size_t len, Alignment& mate1, Alignment& mate2);

size_t fastq_unpaired_for_each(string& filename, function<void(Alignment&)> lambda);
size_t fastq_paired_interleaved_for_each(string& filename, function<void(Alignment&, Alignment&)> lambda);
size_t fastq_paired_two_files_for_each(string& file1, string& file2, function<void(Alignment&, Alignment&)> lambda);
// parallel versions of above
size_t fastq_unpaired_for_each_parallel(string& filename, function<void(Alignment&)> lambda);
size_t fastq_paired_interleaved_for_each_parallel(string& filename, function<void(Alignment&, Alignment&)> lambda);
size_t fastq_paired_two_files_for_each_parallel(string& file1, string& file2, function<void(Alignment&, Alignment&)> lambda);

bam_hdr_t* hts_file_header(string& filename, string& header);
bam_hdr_t* hts_string_header(string& header,
                             map<string, int64_t>& path_length,
                             map<string, string>& rg_sample);
void write_alignments(std::ostream& out, vector<Alignment>& buf);
void write_alignment_to_file(const string& file, const Alignment& aln);

void mapping_cigar(const Mapping& mapping, vector<pair<int, char> >& cigar);
string cigar_string(vector<pair<int, char> >& cigar);
string mapping_string(const string& source, const Mapping& mapping);

Alignment bam_to_alignment(const bam1_t *b, map<string, string>& rg_sample);

bam1_t* alignment_to_bam(const string& sam_header,
                         const Alignment& alignment,
                         const string& refseq,
                         const int32_t refpos,
                         const bool refrev,
                         const string& cigar,
                         const string& mateseq,
                         const int32_t matepos,
                         const int32_t tlen);

string alignment_to_sam(const Alignment& alignment,
                        const string& refseq,
                        const int32_t refpos,
                        const bool refrev,
                        const string& cigar,
                        const string& mateseq,
                        const int32_t matepos,
                        const int32_t tlen);

string cigar_against_path(const Alignment& alignment, bool on_reverse_strand);

int32_t sam_flag(const Alignment& alignment, bool on_reverse_strand);
short quality_char_to_short(char c);
char quality_short_to_char(short i);
string string_quality_char_to_short(const string& quality);
string string_quality_short_to_char(const string& quality);
void alignment_quality_char_to_short(Alignment& alignment);
void alignment_quality_short_to_char(Alignment& alignment);
void parse_rg_sample_map(char* hts_header, map<string, string>& rg_sample);
int alignment_to_length(const Alignment& a);
int alignment_from_length(const Alignment& a);
// Adds a2 onto the end of a1, returns reference to a1
Alignment& extend_alignment(Alignment& a1, const Alignment& a2, bool debug=false);
// Merge a set of alignments into one
Alignment merge_alignments(const vector<Alignment>& alns, bool debug=false);
// Merge two alignments end-to-end (could be "concat")
Alignment merge_alignments(const Alignment& a1, const Alignment& a2, bool debug=false);
Alignment strip_from_start(const Alignment& aln, size_t drop);
Alignment strip_from_end(const Alignment& aln, size_t drop);
Alignment trim_alignment(const Alignment& aln, const Position& pos1, const Position& pos2);
vector<Alignment> alignment_ends(const Alignment& aln, size_t len1, size_t len2);
// generate a digest of the alignmnet
const string hash_alignment(const Alignment& aln);
// Flip the alignment's sequence and is_reverse flag, and flip and re-order its
// Mappings to match. A function to get node lengths is needed because the
// Mappings in the alignment will need to give their positions from the opposite
// ends of their nodes. Offsets will be updated to count unused bases from node
// start when considering the node in its new orientation.
Alignment reverse_complement_alignment(const Alignment& aln, const function<int64_t(id_t)>& node_length);
vector<Alignment> reverse_complement_alignments(const vector<Alignment>& alns, const function<int64_t(int64_t)>& node_length);
int softclip_start(const Alignment& alignment);
int softclip_end(const Alignment& alignment);
size_t to_length_after_pos(const Alignment& aln, const Position& pos);
size_t from_length_after_pos(const Alignment& aln, const Position& pos);
size_t to_length_before_pos(const Alignment& aln, const Position& pos);
size_t from_length_before_pos(const Alignment& aln, const Position& pos);

// project the alignment's path back into a different ID space
void translate_nodes(Alignment& a, const map<id_t, pair<id_t, bool> >& ids, const std::function<size_t(int64_t)>& node_length);

// Invert the orientation in the alignment of all the nodes whose IDs are
// listed. It needs a callback to ask the length of any given node.
void flip_nodes(Alignment& a, const set<int64_t>& ids, const std::function<size_t(int64_t)>& node_length);

// simplifies the path in the alignment
Alignment simplify(const Alignment& a);
void write_alignment_to_file(const Alignment& aln, const string& filename);

// quality information; a kind of poor man's pileup
map<id_t, int> alignment_quality_per_node(const Alignment& aln);

}

#endif
<commit_msg>Finish documenting alignment simplification<commit_after>#ifndef ALIGNMENT_H
#define ALIGNMENT_H

#include <iostream>
#include <functional>
#include <zlib.h>
#include "utility.hpp"
#include "path.hpp"
#include "position.hpp"
#include "vg.pb.h"

#include "htslib/hfile.h"
#include "htslib/hts.h"
#include "htslib/sam.h"
#include "htslib/vcf.h"

namespace vg {

const char* const BAM_DNA_LOOKUP = "=ACMGRSVTWYHKDBN";

int hts_for_each(string& filename, function<void(Alignment&)> lambda);
int hts_for_each_parallel(string& filename, function<void(Alignment&)> lambda);
int fastq_for_each(string& filename, function<void(Alignment&)> lambda);
bool get_next_alignment_from_fastq(gzFile fp, char* buffer, size_t len, Alignment& alignment);
bool get_next_interleaved_alignment_pair_from_fastq(gzFile fp, char* buffer, size_t len, Alignment& mate1, Alignment& mate2);
bool get_next_alignment_pair_from_fastqs(gzFile fp1, gzFile fp2, char* buffer, size_t len, Alignment& mate1, Alignment& mate2);

size_t fastq_unpaired_for_each(string& filename, function<void(Alignment&)> lambda);
size_t fastq_paired_interleaved_for_each(string& filename, function<void(Alignment&, Alignment&)> lambda);
size_t fastq_paired_two_files_for_each(string& file1, string& file2, function<void(Alignment&, Alignment&)> lambda);
// parallel versions of above
size_t fastq_unpaired_for_each_parallel(string& filename, function<void(Alignment&)> lambda);
size_t fastq_paired_interleaved_for_each_parallel(string& filename, function<void(Alignment&, Alignment&)> lambda);
size_t fastq_paired_two_files_for_each_parallel(string& file1, string& file2, function<void(Alignment&, Alignment&)> lambda);

bam_hdr_t* hts_file_header(string& filename, string& header);
bam_hdr_t* hts_string_header(string& header,
                             map<string, int64_t>& path_length,
                             map<string, string>& rg_sample);
void write_alignments(std::ostream& out, vector<Alignment>& buf);
void write_alignment_to_file(const string& file, const Alignment& aln);

void mapping_cigar(const Mapping& mapping, vector<pair<int, char> >& cigar);
string cigar_string(vector<pair<int, char> >& cigar);
string mapping_string(const string& source, const Mapping& mapping);

Alignment bam_to_alignment(const bam1_t *b, map<string, string>& rg_sample);

bam1_t* alignment_to_bam(const string& sam_header,
                         const Alignment& alignment,
                         const string& refseq,
                         const int32_t refpos,
                         const bool refrev,
                         const string& cigar,
                         const string& mateseq,
                         const int32_t matepos,
                         const int32_t tlen);

string alignment_to_sam(const Alignment& alignment,
                        const string& refseq,
                        const int32_t refpos,
                        const bool refrev,
                        const string& cigar,
                        const string& mateseq,
                        const int32_t matepos,
                        const int32_t tlen);

string cigar_against_path(const Alignment& alignment, bool on_reverse_strand);

int32_t sam_flag(const Alignment& alignment, bool on_reverse_strand);
short quality_char_to_short(char c);
char quality_short_to_char(short i);
string string_quality_char_to_short(const string& quality);
string string_quality_short_to_char(const string& quality);
void alignment_quality_char_to_short(Alignment& alignment);
void alignment_quality_short_to_char(Alignment& alignment);
void parse_rg_sample_map(char* hts_header, map<string, string>& rg_sample);
int alignment_to_length(const Alignment& a);
int alignment_from_length(const Alignment& a);
// Adds a2 onto the end of a1, returns reference to a1
Alignment& extend_alignment(Alignment& a1, const Alignment& a2, bool debug=false);
// Merge a set of alignments into one
Alignment merge_alignments(const vector<Alignment>& alns, bool debug=false);
// Merge two alignments end-to-end (could be "concat")
Alignment merge_alignments(const Alignment& a1, const Alignment& a2, bool debug=false);
Alignment strip_from_start(const Alignment& aln, size_t drop);
Alignment strip_from_end(const Alignment& aln, size_t drop);
Alignment trim_alignment(const Alignment& aln, const Position& pos1, const Position& pos2);
vector<Alignment> alignment_ends(const Alignment& aln, size_t len1, size_t len2);
// generate a digest of the alignmnet
const string hash_alignment(const Alignment& aln);
// Flip the alignment's sequence and is_reverse flag, and flip and re-order its
// Mappings to match. A function to get node lengths is needed because the
// Mappings in the alignment will need to give their positions from the opposite
// ends of their nodes. Offsets will be updated to count unused bases from node
// start when considering the node in its new orientation.
Alignment reverse_complement_alignment(const Alignment& aln, const function<int64_t(id_t)>& node_length);
vector<Alignment> reverse_complement_alignments(const vector<Alignment>& alns, const function<int64_t(int64_t)>& node_length);
int softclip_start(const Alignment& alignment);
int softclip_end(const Alignment& alignment);
size_t to_length_after_pos(const Alignment& aln, const Position& pos);
size_t from_length_after_pos(const Alignment& aln, const Position& pos);
size_t to_length_before_pos(const Alignment& aln, const Position& pos);
size_t from_length_before_pos(const Alignment& aln, const Position& pos);

// project the alignment's path back into a different ID space
void translate_nodes(Alignment& a, const map<id_t, pair<id_t, bool> >& ids, const std::function<size_t(int64_t)>& node_length);

// Invert the orientation in the alignment of all the nodes whose IDs are
// listed. It needs a callback to ask the length of any given node.
void flip_nodes(Alignment& a, const set<int64_t>& ids, const std::function<size_t(int64_t)>& node_length);

/// Simplifies the Path in the Alignment. Note that this removes deletions at
/// the start and end of Mappings, so code that handles simplified Alignments
/// needs to handle offsets on internal Mappings.
Alignment simplify(const Alignment& a);
void write_alignment_to_file(const Alignment& aln, const string& filename);

// quality information; a kind of poor man's pileup
map<id_t, int> alignment_quality_per_node(const Alignment& aln);

}

#endif
<|endoftext|>


<commit_before>#include <iostream>
using namespace std;

#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "amzHeaders.h"

AmzHeaders::AmzHeaders() {
	this->count=0;
	this->namesLength=0;
	this->valuesLength=0;
}

AmzHeaders::~AmzHeaders() {
	for (int i=0;i<this->count;i++) {
		this->names[i] = NULL;
		free(this->values[i]);
	}
}

void AmzHeaders::add(char *name, char *format, ...) {
	this->names[this->count]=name;

	char *result;
	va_list args;
	va_start(args, format);
	vasprintf(&result, format, args);
	va_end(args);

	this->values[this->count]=result;

	this->namesLength+=strlen(name);
	this->valuesLength+=strlen(result);

	this->count++;
}

char *AmzHeaders::serializeIntoStringToSign() {
	// add 2 chars for each entry because each entry is joined by ":" and ended with \n
	int len = this->namesLength + this->valuesLength + (this->count * 2) + 2;
	char *result = (char *) malloc(len);
	result[0]=0;
	for (int i=0;i<this->count;i++) {
		strcat(result, this->names[i]);
		strcat(result, ":");
		strcat(result, this->values[i]);
		strcat(result, "\n");
	}

	return result;
}

struct curl_slist *AmzHeaders::serializeIntoCurl(struct curl_slist *slist) {
	struct curl_slist *slist2 = slist;
	char value[1024*10];
	for (int i=0;i<this->count;i++) {
		sprintf(value, "%s: %s", this->names[i], this->values[i]);
		slist2 = curl_slist_append(slist2, value);
	}

	return slist2;
}
<commit_msg>sort headers<commit_after>#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "amzHeaders.h"

AmzHeaders::AmzHeaders() {
	this->count=0;
	this->namesLength=0;
	this->valuesLength=0;
}

AmzHeaders::~AmzHeaders() {
	for (int i=0;i<this->count;i++) {
		this->names[i] = NULL;
		free(this->values[i]);
	}
}

void AmzHeaders::add(char *name, char *format, ...) {
	this->names[this->count]=name;

	char *result;
	va_list args;
	va_start(args, format);
	vasprintf(&result, format, args);
	va_end(args);

	this->values[this->count]=result;

	this->namesLength+=strlen(name);
	this->valuesLength+=strlen(result);

	this->count++;
}

char *AmzHeaders::serializeIntoStringToSign() {
	// okay here I cheat and use C++. Please forgive me or rewrite in plain C.
	std::vector<std::string> headersList;
	for (int i=0;i<this->count;i++) {
		char *header;
		asprintf(&header, "%s:%s\n", this->names[i], this->values[i]);
		headersList.push_back(header);
		free(header);
	}

	std::sort(headersList.begin(), headersList.end());

	std::string result;

	for (int i=0;i<this->count;i++) {
		result.append(headersList[i]);
	}

	return strdup((char *) result.c_str());
}

struct curl_slist *AmzHeaders::serializeIntoCurl(struct curl_slist *slist) {
	struct curl_slist *slist2 = slist;
	char value[1024*10];
	for (int i=0;i<this->count;i++) {
		sprintf(value, "%s: %s", this->names[i], this->values[i]);
		slist2 = curl_slist_append(slist2, value);
	}

	return slist2;
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "fnord-base/io/filerepository.h"
#include "fnord-base/io/fileutil.h"
#include "fnord-base/application.h"
#include "fnord-base/logging.h"
#include "fnord-base/random.h"
#include "fnord-base/thread/eventloop.h"
#include "fnord-base/thread/threadpool.h"
#include "fnord-base/thread/FixedSizeThreadPool.h"
#include "fnord-base/wallclock.h"
#include "fnord-base/VFS.h"
#include "fnord-rpc/ServerGroup.h"
#include "fnord-rpc/RPC.h"
#include "fnord-rpc/RPCClient.h"
#include "fnord-base/cli/flagparser.h"
#include "fnord-json/json.h"
#include "fnord-json/jsonrpc.h"
#include "fnord-http/httprouter.h"
#include "fnord-http/httpserver.h"
#include "fnord-http/VFSFileServlet.h"
#include "fnord-feeds/FeedService.h"
#include "fnord-feeds/RemoteFeedFactory.h"
#include "fnord-feeds/RemoteFeedReader.h"
#include "fnord-dproc/LocalScheduler.h"
#include "fnord-dproc/DispatchService.h"
#include "fnord-base/stats/statsdagent.h"
#include "fnord-sstable/SSTableServlet.h"
#include "fnord-logtable/LogTableServlet.h"
#include "fnord-logtable/TableRepository.h"
#include "fnord-logtable/TableJanitor.h"
#include "fnord-logtable/TableReplication.h"
#include "fnord-afx/ArtifactReplication.h"
#include "fnord-logtable/NumericBoundsSummary.h"
#include "fnord-mdb/MDB.h"
#include "fnord-mdb/MDBUtil.h"
#include "common.h"
#include "schemas.h"
#include "CustomerNamespace.h"
#include "analytics/AnalyticsServlet.h"
#include "analytics/FeedExportApp.h"
#include "analytics/CTRByPositionQuery.h"
#include "analytics/CTRByPageQuery.h"
#include "analytics/CTRByResultItemCategoryQuery.h"
#include "analytics/TopSearchQueriesQuery.h"
#include "analytics/DiscoveryDashboardQuery.h"
#include "analytics/DiscoveryCatalogStatsQuery.h"
#include "analytics/DiscoveryCategoryStatsQuery.h"
#include "analytics/DiscoverySearchStatsQuery.h"
#include "analytics/ECommerceKPIQuery.h"
#include "analytics/AnalyticsQueryEngine.h"
#include "analytics/AnalyticsQueryEngine.h"
#include "analytics/ShopStatsServlet.h"

using namespace fnord;

fnord::thread::EventLoop ev;

int main(int argc, const char** argv) {
  fnord::Application::init();
  fnord::Application::logToStderr();

  fnord::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8000",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "datadir",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "datadir path",
      "<path>");

  flags.defineFlag(
      "shopstats_table",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "path",
      "<file>");

  flags.defineFlag(
      "loglevel",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  /* thread pools */
  fnord::thread::ThreadPool tpool;
  fnord::thread::FixedSizeThreadPool wpool(8);
  wpool.start();

  /* http */
  fnord::http::HTTPRouter http_router;
  fnord::http::HTTPServer http_server(&http_router, &ev);
  http_server.listen(flags.getInt("http_port"));
  http::HTTPConnectionPool http(&ev);

  /* tsdb */
  tsdb::TSDBClient tsdb("http://nue03.prod.fnrd.net:7003/tsdb", &http);

  /* dproc */
  dproc::DispatchService dproc;
  auto local_scheduler = mkRef(new dproc::LocalScheduler());
  local_scheduler->start();

  /* feed export */
  auto feed_export_app = mkRef(new FeedExportApp(&tsdb));
  dproc.registerApp(feed_export_app.get(), local_scheduler.get());

  {
    FeedConfig fc;
    fc.set_customer("dawanda");
    fc.set_feed("ECommerceSearchQueriesFeed");
    fc.set_partition_size(kMicrosPerHour * 4);
    fc.set_first_partition(1430438400000000); // 2015-05-01 00:00:00Z
    fc.set_num_shards(128);

    feed_export_app->configureFeed(fc);
  }

  {
    FeedConfig fc;
    fc.set_customer("dawanda");
    fc.set_feed("ECommerceRecoQueriesFeed");
    fc.set_partition_size(kMicrosPerHour * 4);
    fc.set_first_partition(1431014400000000);
    fc.set_num_shards(32);

    feed_export_app->configureFeed(fc);
  }

  /* stop stats */
  //auto shopstats = cm::ShopStatsTable::open(flags.getString("shopstats_table"));
  //cm::ShopStatsServlet shopstats_servlet(shopstats);
  //http_router.addRouteByPrefixMatch("/shopstats", &shopstats_servlet, &tpool);

  /* analytics core */
  auto dir = flags.getString("datadir");
  cm::AnalyticsQueryEngine analytics(32, dir, &tsdb);
  cm::AnalyticsServlet analytics_servlet(&analytics, &dproc);
  http_router.addRouteByPrefixMatch("/analytics", &analytics_servlet, &tpool);

  analytics.registerQueryFactory("ctr_by_position", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::CTRByPositionQuery(scan, segments);
  });

  analytics.registerQueryFactory("ctr_by_page", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::CTRByPageQuery(scan, segments);
  });

  analytics.registerQueryFactory("ctr_by_result_item_category", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::CTRByResultItemCategoryQuery(scan, segments);
  });

  analytics.registerQueryFactory("discovery_dashboard", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryDashboardQuery(
        scan,
        segments,
        query.start_time,
        query.end_time);
  });

  analytics.registerQueryFactory("discovery_search_stats", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoverySearchStatsQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        params);
  });

  analytics.registerQueryFactory("discovery_catalog_stats", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCatalogStatsQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        params);
  });

  analytics.registerQueryFactory("discovery_category0_stats", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        "search_queries.category1",
        "search_queries.category1",
        params);
  });

  analytics.registerQueryFactory("discovery_category1_stats", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        "search_queries.category1",
        "search_queries.category2",
        params);
  });

  analytics.registerQueryFactory("discovery_category2_stats", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        "search_queries.category2",
        "search_queries.category3",
        params);
  });

  analytics.registerQueryFactory("discovery_category3_stats", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        "search_queries.category3",
        "search_queries.category3",
        params);
  });

  analytics.registerQueryFactory("top_search_queries", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::TopSearchQueriesQuery(scan, segments, params);
  });

  analytics.registerQueryFactory("ecommerce_dashboard", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::ECommerceKPIQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        params);
  });

  ev.run();
  local_scheduler->stop();

  fnord::logInfo("cm.analytics.backend", "Exiting...");
  exit(0);
}

<commit_msg>cleaning up<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "fnord-base/io/filerepository.h"
#include "fnord-base/io/fileutil.h"
#include "fnord-base/application.h"
#include "fnord-base/logging.h"
#include "fnord-base/random.h"
#include "fnord-base/thread/eventloop.h"
#include "fnord-base/thread/threadpool.h"
#include "fnord-base/thread/FixedSizeThreadPool.h"
#include "fnord-base/wallclock.h"
#include "fnord-base/VFS.h"
#include "fnord-rpc/ServerGroup.h"
#include "fnord-rpc/RPC.h"
#include "fnord-rpc/RPCClient.h"
#include "fnord-base/cli/flagparser.h"
#include "fnord-json/json.h"
#include "fnord-json/jsonrpc.h"
#include "fnord-http/httprouter.h"
#include "fnord-http/httpserver.h"
#include "fnord-http/VFSFileServlet.h"
#include "fnord-feeds/FeedService.h"
#include "fnord-feeds/RemoteFeedFactory.h"
#include "fnord-feeds/RemoteFeedReader.h"
#include "fnord-dproc/LocalScheduler.h"
#include "fnord-dproc/DispatchService.h"
#include "fnord-base/stats/statsdagent.h"
#include "fnord-sstable/SSTableServlet.h"
#include "fnord-logtable/LogTableServlet.h"
#include "fnord-logtable/TableRepository.h"
#include "fnord-logtable/TableJanitor.h"
#include "fnord-logtable/TableReplication.h"
#include "fnord-afx/ArtifactReplication.h"
#include "fnord-logtable/NumericBoundsSummary.h"
#include "fnord-mdb/MDB.h"
#include "fnord-mdb/MDBUtil.h"
#include "common.h"
#include "schemas.h"
#include "CustomerNamespace.h"
#include "analytics/AnalyticsServlet.h"
#include "analytics/FeedExportApp.h"
#include "analytics/CTRByPositionQuery.h"
#include "analytics/CTRByPageQuery.h"
#include "analytics/CTRByResultItemCategoryQuery.h"
#include "analytics/TopSearchQueriesQuery.h"
#include "analytics/DiscoveryDashboardQuery.h"
#include "analytics/DiscoveryCatalogStatsQuery.h"
#include "analytics/DiscoveryCategoryStatsQuery.h"
#include "analytics/DiscoverySearchStatsQuery.h"
#include "analytics/ECommerceKPIQuery.h"
#include "analytics/AnalyticsQueryEngine.h"
#include "analytics/AnalyticsQueryEngine.h"
#include "analytics/ShopStatsServlet.h"

using namespace fnord;

fnord::thread::EventLoop ev;

int main(int argc, const char** argv) {
  fnord::Application::init();
  fnord::Application::logToStderr();

  fnord::cli::FlagParser flags;

  flags.defineFlag(
      "http_port",
      fnord::cli::FlagParser::T_INTEGER,
      false,
      NULL,
      "8000",
      "Start the public http server on this port",
      "<port>");

  flags.defineFlag(
      "datadir",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "datadir path",
      "<path>");

  flags.defineFlag(
      "shopstats_table",
      cli::FlagParser::T_STRING,
      true,
      NULL,
      NULL,
      "path",
      "<file>");

  flags.defineFlag(
      "loglevel",
      fnord::cli::FlagParser::T_STRING,
      false,
      NULL,
      "INFO",
      "loglevel",
      "<level>");

  flags.parseArgv(argc, argv);

  Logger::get()->setMinimumLogLevel(
      strToLogLevel(flags.getString("loglevel")));

  /* thread pools */
  fnord::thread::ThreadPool tpool;
  fnord::thread::FixedSizeThreadPool wpool(8);
  wpool.start();

  /* http */
  fnord::http::HTTPRouter http_router;
  fnord::http::HTTPServer http_server(&http_router, &ev);
  http_server.listen(flags.getInt("http_port"));
  http::HTTPConnectionPool http(&ev);

  /* tsdb */
  tsdb::TSDBClient tsdb("http://nue03.prod.fnrd.net:7003/tsdb", &http);

  /* dproc */
  dproc::DispatchService dproc;
  auto local_scheduler = mkRef(new dproc::LocalScheduler());
  local_scheduler->start();

  /* feed export */
  auto feed_export_app = mkRef(new FeedExportApp(&tsdb));
  dproc.registerApp(feed_export_app.get(), local_scheduler.get());

  {
    FeedConfig fc;
    fc.set_customer("dawanda");
    fc.set_feed("ECommerceSearchQueriesFeed");
    fc.set_partition_size(kMicrosPerHour * 4);
    fc.set_first_partition(1430438400000000); // 2015-05-01 00:00:00Z
    fc.set_num_shards(128);

    feed_export_app->configureFeed(fc);
  }

  {
    FeedConfig fc;
    fc.set_customer("dawanda");
    fc.set_feed("ECommerceRecoQueriesFeed");
    fc.set_partition_size(kMicrosPerHour * 4);
    fc.set_first_partition(1432785600000000);
    fc.set_num_shards(32);

    feed_export_app->configureFeed(fc);
  }

  /* stop stats */
  //auto shopstats = cm::ShopStatsTable::open(flags.getString("shopstats_table"));
  //cm::ShopStatsServlet shopstats_servlet(shopstats);
  //http_router.addRouteByPrefixMatch("/shopstats", &shopstats_servlet, &tpool);

  /* analytics core */
  auto dir = flags.getString("datadir");
  cm::AnalyticsQueryEngine analytics(32, dir, &tsdb);
  cm::AnalyticsServlet analytics_servlet(&analytics, &dproc);
  http_router.addRouteByPrefixMatch("/analytics", &analytics_servlet, &tpool);

  analytics.registerQueryFactory("ctr_by_position", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::CTRByPositionQuery(scan, segments);
  });

  analytics.registerQueryFactory("ctr_by_page", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::CTRByPageQuery(scan, segments);
  });

  analytics.registerQueryFactory("ctr_by_result_item_category", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::CTRByResultItemCategoryQuery(scan, segments);
  });

  analytics.registerQueryFactory("discovery_dashboard", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryDashboardQuery(
        scan,
        segments,
        query.start_time,
        query.end_time);
  });

  analytics.registerQueryFactory("discovery_search_stats", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoverySearchStatsQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        params);
  });

  analytics.registerQueryFactory("discovery_catalog_stats", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCatalogStatsQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        params);
  });

  analytics.registerQueryFactory("discovery_category0_stats", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        "search_queries.category1",
        "search_queries.category1",
        params);
  });

  analytics.registerQueryFactory("discovery_category1_stats", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        "search_queries.category1",
        "search_queries.category2",
        params);
  });

  analytics.registerQueryFactory("discovery_category2_stats", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        "search_queries.category2",
        "search_queries.category3",
        params);
  });

  analytics.registerQueryFactory("discovery_category3_stats", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::DiscoveryCategoryStatsQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        "search_queries.category3",
        "search_queries.category3",
        params);
  });

  analytics.registerQueryFactory("top_search_queries", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::TopSearchQueriesQuery(scan, segments, params);
  });

  analytics.registerQueryFactory("ecommerce_dashboard", [] (
      const cm::AnalyticsQuery& query,
      const cm::AnalyticsQuery::SubQueryParams params,
      const Vector<RefPtr<cm::TrafficSegment>>& segments,
      cm::AnalyticsTableScan* scan) {
    return new cm::ECommerceKPIQuery(
        scan,
        segments,
        query.start_time,
        query.end_time,
        params);
  });

  ev.run();
  local_scheduler->stop();

  fnord::logInfo("cm.analytics.backend", "Exiting...");
  exit(0);
}

<|endoftext|>


<commit_before>/// @file
/// @version 3.5
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#include <gtypes/Rectangle.h>
#include <gtypes/Vector2.h>
#include <gtypes/Vector3.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hmap.h>

#include "aprilUtil.h"

#define HSTR_SEPARATOR ','

namespace april
{
	RenderOperation TriangleList = RO_TRIANGLE_LIST; // DEPRECATED
	RenderOperation TriangleStrip = RO_TRIANGLE_STRIP; // DEPRECATED
	RenderOperation TriangleFan = RO_TRIANGLE_FAN; // DEPRECATED
	RenderOperation LineList = RO_LINE_LIST; // DEPRECATED
	RenderOperation LineStrip = RO_LINE_STRIP; // DEPRECATED
	RenderOperation PointList = RO_POINT_LIST; // DEPRECATED
	RenderOperation RENDER_OP_UNDEFINED = RO_UNDEFINED; // DEPRECATED
	BlendMode DEFAULT = BM_DEFAULT; // DEPRECATED
	BlendMode ALPHA_BLEND = BM_ALPHA; // DEPRECATED
	BlendMode ADD = BM_ADD; // DEPRECATED
	BlendMode SUBTRACT = BM_SUBTRACT; // DEPRECATED
	BlendMode OVERWRITE = BM_OVERWRITE; // DEPRECATED
	BlendMode BLEND_MODE_UNDEFINED = BM_UNDEFINED; // DEPRECATED
	ColorMode NORMAL = CM_DEFAULT; // DEPRECATED
	ColorMode MULTIPLY = CM_MULTIPLY; // DEPRECATED
	ColorMode LERP = CM_LERP; // DEPRECATED
	ColorMode ALPHA_MAP = CM_ALPHA_MAP; // DEPRECATED
	ColorMode COLOR_MODE_UNDEFINED = CM_UNDEFINED; // DEPRECATED

	const char hstrSeparator = ',';

	void PlainVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void ColoredVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void TexturedVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void ColoredTexturedVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void ColoredTexturedNormalVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void TexturedNormalVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void ColoredNormalVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void rgbToHsl(unsigned char r, unsigned char g, unsigned char b, float* h, float* s, float* l)
	{
		int min = hmin(hmin(r, g), b);
		int max = hmax(hmax(r, g), b);
		int delta = max - min;
		*h = *s = 0.0f;
		*l = (max + min) / 510.0f;
		if (delta > 0)
		{
			if (*l > 0.0f && *l < 1.0f)
			{
				*s = (delta / 255.0f) / (*l < 0.5f ? (2 * *l) : (2 - 2 * *l));
			}
			if (max == r)
			{
				*h = (g - b) / (float)delta;
				if (g < b)
				{
					*h += 6.0f;
				}
			}
			else if (max == g)
			{
				*h += (b - r) / (float)delta + 2.0f;
			}
			else if (max == b)
			{
				*h += (r - g) / (float)delta + 4.0f;
			}
			*h *= 0.16666667f;
		}
	}

	float _colorHueToRgb(float p, float q, float h)
	{
		h = (h < 0 ? h + 1 : ((h > 1) ? h - 1 : h));
		if (h * 6 < 1)
		{
			return p + (q - p) * h * 6;
		}
		if (h * 2 < 1)
		{
			return q;
		}
		if (h * 3 < 2)
		{
			return (p + (q - p) * (0.6666667f - h) * 6);
		}
		return p;
	}

	void hslToRgb(float h, float s, float l, unsigned char* r, unsigned char* g, unsigned char* b)
	{
		if (s == 0.0f)
		{
			*r = *g = *b = (unsigned char)(l * 255);
			return;
		}
		float q = (l < 0.5f ? l * (1 + s) : l + s - l * s);
		float p = l * 2 - q;
		*r = (unsigned char)hround(255.0f * _colorHueToRgb(p, q, h + 0.3333333f));
		*g = (unsigned char)hround(255.0f * _colorHueToRgb(p, q, h));
		*b = (unsigned char)hround(255.0f * _colorHueToRgb(p, q, h - 0.3333333f));
	}

	hstr generateName(chstr prefix)
	{
		static hmap<hstr, int> counters;
		int count = counters[prefix] + 1;
		counters[prefix] = count;
		return prefix + hstr(count);
	}

	hstr gvec2ToHstr(gvec2 vector)
	{
		return hsprintf("%f%c%f", vector.x, HSTR_SEPARATOR, vector.y);
	}

	hstr gvec3ToHstr(gvec3 vector)
	{
		return hsprintf("%f%c%f%c%f", vector.x, HSTR_SEPARATOR, vector.y, HSTR_SEPARATOR, vector.z);
	}

	hstr grectToHstr(grect rect)
	{
		return hsprintf("%f%c%f%c%f%c%f", rect.x, HSTR_SEPARATOR, rect.y, HSTR_SEPARATOR, rect.w, HSTR_SEPARATOR, rect.h);
	}

	gvec2 hstrToGvec2(chstr string)
	{
		harray<hstr> data = string.split(HSTR_SEPARATOR);
		if (data.size() != 2)
		{
			throw hl_exception("Cannot convert string '" + string + "' to gtypes::Vector2.");
		}
		return gvec2(data[0].trim(), data[1].trim());
	}

	gvec3 hstrToGvec3(chstr string)
	{
		harray<hstr> data = string.split(HSTR_SEPARATOR);
		if (data.size() != 3)
		{
			throw hl_exception("Cannot convert string '" + string + "' to gtypes::Vector3.");
		}
		return gvec3(data[0].trim(), data[1].trim(), data[2].trim());
	}

	grect hstrToGrect(chstr string)
	{
		harray<hstr> data = string.split(HSTR_SEPARATOR);
		if (data.size() != 4)
		{
			throw hl_exception("Cannot convert string '" + string + "' to gtypes::Rectangle.");
		}
		return grect(data[0].trim(), data[1].trim(), data[2].trim(), data[3].trim());
	}

}
<commit_msg>removed unused variable<commit_after>/// @file
/// @version 3.5
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#include <gtypes/Rectangle.h>
#include <gtypes/Vector2.h>
#include <gtypes/Vector3.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hmap.h>

#include "aprilUtil.h"

#define HSTR_SEPARATOR ','

namespace april
{
	RenderOperation TriangleList = RO_TRIANGLE_LIST; // DEPRECATED
	RenderOperation TriangleStrip = RO_TRIANGLE_STRIP; // DEPRECATED
	RenderOperation TriangleFan = RO_TRIANGLE_FAN; // DEPRECATED
	RenderOperation LineList = RO_LINE_LIST; // DEPRECATED
	RenderOperation LineStrip = RO_LINE_STRIP; // DEPRECATED
	RenderOperation PointList = RO_POINT_LIST; // DEPRECATED
	RenderOperation RENDER_OP_UNDEFINED = RO_UNDEFINED; // DEPRECATED
	BlendMode DEFAULT = BM_DEFAULT; // DEPRECATED
	BlendMode ALPHA_BLEND = BM_ALPHA; // DEPRECATED
	BlendMode ADD = BM_ADD; // DEPRECATED
	BlendMode SUBTRACT = BM_SUBTRACT; // DEPRECATED
	BlendMode OVERWRITE = BM_OVERWRITE; // DEPRECATED
	BlendMode BLEND_MODE_UNDEFINED = BM_UNDEFINED; // DEPRECATED
	ColorMode NORMAL = CM_DEFAULT; // DEPRECATED
	ColorMode MULTIPLY = CM_MULTIPLY; // DEPRECATED
	ColorMode LERP = CM_LERP; // DEPRECATED
	ColorMode ALPHA_MAP = CM_ALPHA_MAP; // DEPRECATED
	ColorMode COLOR_MODE_UNDEFINED = CM_UNDEFINED; // DEPRECATED

	void PlainVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void ColoredVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void TexturedVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void ColoredTexturedVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void ColoredTexturedNormalVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void TexturedNormalVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void ColoredNormalVertex::operator=(const gvec3& v)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
	}

	void rgbToHsl(unsigned char r, unsigned char g, unsigned char b, float* h, float* s, float* l)
	{
		int min = hmin(hmin(r, g), b);
		int max = hmax(hmax(r, g), b);
		int delta = max - min;
		*h = *s = 0.0f;
		*l = (max + min) / 510.0f;
		if (delta > 0)
		{
			if (*l > 0.0f && *l < 1.0f)
			{
				*s = (delta / 255.0f) / (*l < 0.5f ? (2 * *l) : (2 - 2 * *l));
			}
			if (max == r)
			{
				*h = (g - b) / (float)delta;
				if (g < b)
				{
					*h += 6.0f;
				}
			}
			else if (max == g)
			{
				*h += (b - r) / (float)delta + 2.0f;
			}
			else if (max == b)
			{
				*h += (r - g) / (float)delta + 4.0f;
			}
			*h *= 0.16666667f;
		}
	}

	float _colorHueToRgb(float p, float q, float h)
	{
		h = (h < 0 ? h + 1 : ((h > 1) ? h - 1 : h));
		if (h * 6 < 1)
		{
			return p + (q - p) * h * 6;
		}
		if (h * 2 < 1)
		{
			return q;
		}
		if (h * 3 < 2)
		{
			return (p + (q - p) * (0.6666667f - h) * 6);
		}
		return p;
	}

	void hslToRgb(float h, float s, float l, unsigned char* r, unsigned char* g, unsigned char* b)
	{
		if (s == 0.0f)
		{
			*r = *g = *b = (unsigned char)(l * 255);
			return;
		}
		float q = (l < 0.5f ? l * (1 + s) : l + s - l * s);
		float p = l * 2 - q;
		*r = (unsigned char)hround(255.0f * _colorHueToRgb(p, q, h + 0.3333333f));
		*g = (unsigned char)hround(255.0f * _colorHueToRgb(p, q, h));
		*b = (unsigned char)hround(255.0f * _colorHueToRgb(p, q, h - 0.3333333f));
	}

	hstr generateName(chstr prefix)
	{
		static hmap<hstr, int> counters;
		int count = counters[prefix] + 1;
		counters[prefix] = count;
		return prefix + hstr(count);
	}

	hstr gvec2ToHstr(gvec2 vector)
	{
		return hsprintf("%f%c%f", vector.x, HSTR_SEPARATOR, vector.y);
	}

	hstr gvec3ToHstr(gvec3 vector)
	{
		return hsprintf("%f%c%f%c%f", vector.x, HSTR_SEPARATOR, vector.y, HSTR_SEPARATOR, vector.z);
	}

	hstr grectToHstr(grect rect)
	{
		return hsprintf("%f%c%f%c%f%c%f", rect.x, HSTR_SEPARATOR, rect.y, HSTR_SEPARATOR, rect.w, HSTR_SEPARATOR, rect.h);
	}

	gvec2 hstrToGvec2(chstr string)
	{
		harray<hstr> data = string.split(HSTR_SEPARATOR);
		if (data.size() != 2)
		{
			throw hl_exception("Cannot convert string '" + string + "' to gtypes::Vector2.");
		}
		return gvec2(data[0].trim(), data[1].trim());
	}

	gvec3 hstrToGvec3(chstr string)
	{
		harray<hstr> data = string.split(HSTR_SEPARATOR);
		if (data.size() != 3)
		{
			throw hl_exception("Cannot convert string '" + string + "' to gtypes::Vector3.");
		}
		return gvec3(data[0].trim(), data[1].trim(), data[2].trim());
	}

	grect hstrToGrect(chstr string)
	{
		harray<hstr> data = string.split(HSTR_SEPARATOR);
		if (data.size() != 4)
		{
			throw hl_exception("Cannot convert string '" + string + "' to gtypes::Rectangle.");
		}
		return grect(data[0].trim(), data[1].trim(), data[2].trim(), data[3].trim());
	}

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * Copyright (c) 2010 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 */

#ifndef __BASE_DEBUG_HH__
#define __BASE_DEBUG_HH__

#include <map>
#include <string>
#include <vector>

namespace Debug {

void breakpoint();

class Flag
{
  protected:
    const char *_name;
    const char *_desc;
    std::vector<Flag *> _kids;

  public:
    Flag(const char *name, const char *desc);
    virtual ~Flag();

    std::string name() const { return _name; }
    std::string desc() const { return _desc; }
    std::vector<Flag *> kids() { return _kids; }

    virtual void enable() = 0;
    virtual void disable() = 0;
};

class SimpleFlag : public Flag
{
  protected:
    bool _status;

  public:
    SimpleFlag(const char *name, const char *desc)
        : Flag(name, desc)
    { }

    bool status() const { return _status; }
    operator bool() const { return _status; }
    bool operator!() const { return !_status; }

    void enable() { _status = true; }
    void disable() { _status = false; }
};

class CompoundFlag : public SimpleFlag
{
  protected:
    void
    addFlag(Flag &f)
    {
        if (&f != NULL)
            _kids.push_back(&f);
    }

  public:
    CompoundFlag(const char *name, const char *desc,
        Flag &f00 = *(Flag *)0, Flag &f01 = *(Flag *)0,
        Flag &f02 = *(Flag *)0, Flag &f03 = *(Flag *)0,
        Flag &f04 = *(Flag *)0, Flag &f05 = *(Flag *)0,
        Flag &f06 = *(Flag *)0, Flag &f07 = *(Flag *)0,
        Flag &f08 = *(Flag *)0, Flag &f09 = *(Flag *)0,
        Flag &f10 = *(Flag *)0, Flag &f11 = *(Flag *)0,
        Flag &f12 = *(Flag *)0, Flag &f13 = *(Flag *)0,
        Flag &f14 = *(Flag *)0, Flag &f15 = *(Flag *)0,
        Flag &f16 = *(Flag *)0, Flag &f17 = *(Flag *)0,
        Flag &f18 = *(Flag *)0, Flag &f19 = *(Flag *)0)
        : SimpleFlag(name, desc)
    {
        addFlag(f00); addFlag(f01); addFlag(f02); addFlag(f03); addFlag(f04);
        addFlag(f05); addFlag(f06); addFlag(f07); addFlag(f08); addFlag(f09);
        addFlag(f10); addFlag(f11); addFlag(f12); addFlag(f13); addFlag(f14);
        addFlag(f15); addFlag(f16); addFlag(f17); addFlag(f18); addFlag(f19);
    }

    void enable();
    void disable();
};

typedef std::map<std::string, Flag *> FlagsMap;
FlagsMap &allFlags();

Flag *findFlag(const std::string &name);

bool changeFlag(const char *s, bool value);

} // namespace Debug

void setDebugFlag(const char *string);

void clearDebugFlag(const char *string);

void dumpDebugFlags();

#endif // __BASE_DEBUG_HH__
<commit_msg>base: explicitly suggest potential use of 'All' debug flags<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * Copyright (c) 2010 The Hewlett-Packard Development Company
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 */

#ifndef __BASE_DEBUG_HH__
#define __BASE_DEBUG_HH__

#include <map>
#include <string>
#include <vector>

namespace Debug {

void breakpoint();

class Flag
{
  protected:
    const char *_name;
    const char *_desc;
    std::vector<Flag *> _kids;

  public:
    Flag(const char *name, const char *desc);
    virtual ~Flag();

    std::string name() const { return _name; }
    std::string desc() const { return _desc; }
    std::vector<Flag *> kids() { return _kids; }

    virtual void enable() = 0;
    virtual void disable() = 0;
};

class SimpleFlag : public Flag
{
  protected:
    bool _status;

  public:
    SimpleFlag(const char *name, const char *desc)
        : Flag(name, desc)
    { }

    bool status() const { return _status; }
    operator bool() const { return _status; }
    bool operator!() const { return !_status; }

    void enable() { _status = true; }
    void disable() { _status = false; }
};

class CompoundFlag : public SimpleFlag
{
  protected:
    void
    addFlag(Flag &f)
    {
        if (&f != NULL)
            _kids.push_back(&f);
    }

  public:
    CompoundFlag(const char *name, const char *desc,
        Flag &f00 = *(Flag *)0, Flag &f01 = *(Flag *)0,
        Flag &f02 = *(Flag *)0, Flag &f03 = *(Flag *)0,
        Flag &f04 = *(Flag *)0, Flag &f05 = *(Flag *)0,
        Flag &f06 = *(Flag *)0, Flag &f07 = *(Flag *)0,
        Flag &f08 = *(Flag *)0, Flag &f09 = *(Flag *)0,
        Flag &f10 = *(Flag *)0, Flag &f11 = *(Flag *)0,
        Flag &f12 = *(Flag *)0, Flag &f13 = *(Flag *)0,
        Flag &f14 = *(Flag *)0, Flag &f15 = *(Flag *)0,
        Flag &f16 = *(Flag *)0, Flag &f17 = *(Flag *)0,
        Flag &f18 = *(Flag *)0, Flag &f19 = *(Flag *)0)
        : SimpleFlag(name, desc)
    {
        addFlag(f00); addFlag(f01); addFlag(f02); addFlag(f03); addFlag(f04);
        addFlag(f05); addFlag(f06); addFlag(f07); addFlag(f08); addFlag(f09);
        addFlag(f10); addFlag(f11); addFlag(f12); addFlag(f13); addFlag(f14);
        addFlag(f15); addFlag(f16); addFlag(f17); addFlag(f18); addFlag(f19);
    }

    void enable();
    void disable();
};

typedef std::map<std::string, Flag *> FlagsMap;
FlagsMap &allFlags();

Flag *findFlag(const std::string &name);

extern Flag *const All;

bool changeFlag(const char *s, bool value);

} // namespace Debug

void setDebugFlag(const char *string);

void clearDebugFlag(const char *string);

void dumpDebugFlags();

#endif // __BASE_DEBUG_HH__
<|endoftext|>