<commit_before>/**
 * \file XmlElement.cpp
 * \brief XML Element
 * \author tcantenot
 * \version 0.1
 * \date 18 mars 2014
 */

#include "Utils.hpp"
#include "XmlComment.hpp"
#include "XmlElement.hpp"
#include "XmlText.hpp"

#ifdef APP_DEBUG
#include <algorithm>
#include <cassert>
#endif

namespace Xml
{
    Element::Element(std::string const & name, Node * parent):
        Node(parent),
        mName(name),
        mAttributes(),
        mChildren()
    {

    }

    Element::~Element()
    {
        // Free memory
        this->clearContent();
    }

    Element::ElementList
    Element::elements() const
    {
        ElementList elements;
        for(auto const & c : mChildren)
        {
            if(c->isElement())
            {
                elements.push_back(static_cast<Element const *>(c));
            }
        }
        return elements;
    }

    Element const *
    Element::parentElement() const
    {
        Node * parent = mParent;
        do
        {
            if(parent->isElement())
            {
                return static_cast<Element const *>(parent);
            }
        }
        while((parent = mParent->parent()) != nullptr);

        return nullptr;
    }

    std::string
    Element::text() const
    {
        std::string content = "";

        for(auto const & c : mChildren)
        {
            if(c != nullptr)
            {
                content += c->contentText();
            }
        }

        return content;
    }

    void
    Element::setContent(std::string const & content)
    {
        this->clearContent();
        this->appendText(content);
    }

    void
    Element::clearContent()
    {
        for(auto & c : mChildren)
        {
            if(c->isElement())
            {
                static_cast<Element *>(c)->clearContent();
            }

            delete c;
        }
    }

    void
    Element::append(Element * element)
    {
        this->appendNode(element);
    }

    void
    Element::appendText(std::string const & text)
    {
        this->appendNode(new Text(text));
    }

    void
    Element::appendComment(std::string const & comment)
    {
        this->appendNode(new Comment(comment));
    }

    void
    Element::appendPI(std::string const & pi)
    {
        (void) pi;
        //TODO
        //this->appendNode(new PI(content));
    }

    std::string const &
    Element::name() const
    {
        return mName;
    }

    void
    Element::setName(std::string const & name)
    {
        mName = name;
    }

    std::string const &
    Element::attribute(std::string const & name) const
    {
        static std::string const notFound = "";

        auto it = mAttributes.find(name);

        return (it != std::end(mAttributes)) ? it->second : notFound;
    }

    void
    Element::setAttribute(std::string const & name, std::string const & value)
    {
        mAttributes[name] = value;
    }

    void
    Element::exportToStream(std::ostream & stream, std::size_t level, std::string const & indent) const
    {
        stream << Utils::repeat(indent, level) << "<" << mName << " ";

        for(auto const & a : mAttributes)
        {
            stream << a.first << "=\"" << a.second << "\" ";
        }

        stream << ">\n";

        for(auto const & c : mChildren)
        {
            exportToStream(stream, level + 1, indent);
        }

        stream << Utils::repeat(indent, level) << "</" << mName << ">\n";
    }

    bool
    Element::isElement() const
    {
        return true;
    }

    void
    Element::appendNode(Node * node)
    {
        #ifdef APP_DEBUG
        assert(node != this);

        assert(
            std::find(std::begin(mChildren), std::end(mChildren), node)
            != std::end(mChildren)
        );
        #endif

        mChildren.push_back(node);
    }
}

<commit_msg>Fixed assertion in XmlElement<commit_after>/**
 * \file XmlElement.cpp
 * \brief XML Element
 * \author tcantenot
 * \version 0.1
 * \date 18 mars 2014
 */

#include "Utils.hpp"
#include "XmlComment.hpp"
#include "XmlElement.hpp"
#include "XmlText.hpp"

#ifdef APP_DEBUG
#include <algorithm>
#include <cassert>
#endif

namespace Xml
{
    Element::Element(std::string const & name, Node * parent):
        Node(parent),
        mName(name),
        mAttributes(),
        mChildren()
    {

    }

    Element::~Element()
    {
        // Free memory
        this->clearContent();
    }

    Element::ElementList
    Element::elements() const
    {
        ElementList elements;
        for(auto const & c : mChildren)
        {
            if(c->isElement())
            {
                elements.push_back(static_cast<Element const *>(c));
            }
        }
        return elements;
    }

    Element const *
    Element::parentElement() const
    {
        Node * parent = mParent;
        do
        {
            if(parent->isElement())
            {
                return static_cast<Element const *>(parent);
            }
        }
        while((parent = mParent->parent()) != nullptr);

        return nullptr;
    }

    std::string
    Element::text() const
    {
        std::string content = "";

        for(auto const & c : mChildren)
        {
            if(c != nullptr)
            {
                content += c->contentText();
            }
        }

        return content;
    }

    void
    Element::setContent(std::string const & content)
    {
        this->clearContent();
        this->appendText(content);
    }

    void
    Element::clearContent()
    {
        for(auto & c : mChildren)
        {
            if(c->isElement())
            {
                static_cast<Element *>(c)->clearContent();
            }

            delete c;
        }
    }

    void
    Element::append(Element * element)
    {
        this->appendNode(element);
    }

    void
    Element::appendText(std::string const & text)
    {
        this->appendNode(new Text(text));
    }

    void
    Element::appendComment(std::string const & comment)
    {
        this->appendNode(new Comment(comment));
    }

    void
    Element::appendPI(std::string const & pi)
    {
        (void) pi;
        //TODO
        //this->appendNode(new PI(content));
    }

    std::string const &
    Element::name() const
    {
        return mName;
    }

    void
    Element::setName(std::string const & name)
    {
        mName = name;
    }

    std::string const &
    Element::attribute(std::string const & name) const
    {
        static std::string const notFound = "";

        auto it = mAttributes.find(name);

        return (it != std::end(mAttributes)) ? it->second : notFound;
    }

    void
    Element::setAttribute(std::string const & name, std::string const & value)
    {
        mAttributes[name] = value;
    }

    void
    Element::exportToStream(std::ostream & stream, std::size_t level, std::string const & indent) const
    {
        stream << Utils::repeat(indent, level) << "<" << mName << " ";

        for(auto const & a : mAttributes)
        {
            stream << a.first << "=\"" << a.second << "\" ";
        }

        stream << ">\n";

        for(auto const & c : mChildren)
        {
            exportToStream(stream, level + 1, indent);
        }

        stream << Utils::repeat(indent, level) << "</" << mName << ">\n";
    }

    bool
    Element::isElement() const
    {
        return true;
    }

    void
    Element::appendNode(Node * node)
    {
        #ifdef APP_DEBUG
        assert(node != this);

        assert(
            std::find(std::begin(mChildren), std::end(mChildren), node)
            == std::end(mChildren)
        );
        #endif

        mChildren.push_back(node);
    }
}

<|endoftext|>


<commit_before>/***************************************************************************
 *  io/ufs_file_base.cpp
 *
 *  Part of the STXXL. See http://stxxl.sourceforge.net
 *
 *  Copyright (C) 2002, 2005, 2008 Roman Dementiev <dementiev@mpi-sb.mpg.de>
 *  Copyright (C) 2008 Ilja Andronov <sni4ok@yandex.ru>
 *
 *  Distributed under the Boost Software License, Version 1.0.
 *  (See accompanying file LICENSE_1_0.txt or copy at
 *  http://www.boost.org/LICENSE_1_0.txt)
 **************************************************************************/

#include <stxxl/bits/io/ufs_file_base.h>

#ifdef BOOST_MSVC
 #include <windows.h>
#else
 #include <unistd.h>
 #include <fcntl.h>
#endif

__STXXL_BEGIN_NAMESPACE

const char * ufs_file_base::io_type() const
{
    return "ufs_base";
}

ufs_file_base::ufs_file_base(
    const std::string & filename,
    int mode,
    int disk) : file_request_basic(disk), file_des(-1), mode_(mode), filename(filename)
{
    int fmode = 0;

#ifndef STXXL_DIRECT_IO_OFF
 #ifndef BOOST_MSVC
    if (mode & DIRECT)
        fmode |= O_SYNC | O_RSYNC | O_DSYNC | O_DIRECT;
 #endif
#endif

    if (mode & RDONLY)
        fmode |= O_RDONLY;

    if (mode & WRONLY)
        fmode |= O_WRONLY;

    if (mode & RDWR)
        fmode |= O_RDWR;

    if (mode & CREAT)
        fmode |= O_CREAT;

    if (mode & TRUNC)
        fmode |= O_TRUNC;

#ifdef BOOST_MSVC
    fmode |= O_BINARY;                     // the default in MS is TEXT mode
#endif

#ifdef BOOST_MSVC
    const int flags = S_IREAD | S_IWRITE;
#else
    const int flags = S_IREAD | S_IWRITE | S_IRGRP | S_IWGRP;
#endif

    if ((file_des = ::open(filename.c_str(), fmode, flags)) < 0)
        STXXL_THROW2(io_error, "Filedescriptor=" << file_des << " filename=" << filename << " fmode=" << fmode);
}

ufs_file_base::~ufs_file_base()
{
	close();
}

void ufs_file_base::close()
{
	if (file_des != -1)
	{
		scoped_mutex_lock fd_lock(fd_mutex);
		int res = ::close(file_des);

		// if successful, reset file descriptor
		if (res >= 0)
			file_des = -1;
		else
			stxxl_function_error(io_error);
	}
}

void ufs_file_base::lock()
{
#ifdef BOOST_MSVC
    // not yet implemented
#else
    scoped_mutex_lock fd_lock(fd_mutex);
    struct flock lock_struct;
    lock_struct.l_type = F_RDLCK | F_WRLCK;
    lock_struct.l_whence = SEEK_SET;
    lock_struct.l_start = 0;
    lock_struct.l_len = 0; // lock all bytes
    if ((::fcntl(file_des, F_SETLK, &lock_struct)) < 0)
        STXXL_THROW2(io_error, "Filedescriptor=" << file_des);
#endif
}

file::offset_type ufs_file_base::_size()
{
    struct stat st;
    stxxl_check_ge_0(::fstat(file_des, &st), io_error);
    return st.st_size;
}

file::offset_type ufs_file_base::size()
{
    scoped_mutex_lock fd_lock(fd_mutex);
    return _size();
}

void ufs_file_base::set_size(offset_type newsize)
{
    scoped_mutex_lock fd_lock(fd_mutex);
    offset_type cur_size = _size();

    if (!(mode_ & RDONLY))
    {
#ifdef BOOST_MSVC
        HANDLE hfile;
        stxxl_check_ge_0(hfile = (HANDLE) ::_get_osfhandle(file_des), io_error);

        LARGE_INTEGER desired_pos;
        desired_pos.QuadPart = newsize;

        if (!SetFilePointerEx(hfile, desired_pos, NULL, FILE_BEGIN))
            stxxl_win_lasterror_exit("SetFilePointerEx in ufs_file_base::set_size(..) oldsize=" << cur_size <<
                                     " newsize=" << newsize << " ", io_error);

        if (!SetEndOfFile(hfile))
            stxxl_win_lasterror_exit("SetEndOfFile oldsize=" << cur_size <<
                                     " newsize=" << newsize << " ", io_error);
#else
        stxxl_check_ge_0(::ftruncate(file_des, newsize), io_error);
#endif
    }

    if (newsize > cur_size)
        stxxl_check_ge_0(::lseek(file_des, newsize - 1, SEEK_SET), io_error);
}

void ufs_file_base::remove()
{
	close();
	::remove(filename.c_str());
}

__STXXL_END_NAMESPACE
// vim: et:ts=4:sw=4
<commit_msg>need cstdio for ::remove()<commit_after>/***************************************************************************
 *  io/ufs_file_base.cpp
 *
 *  Part of the STXXL. See http://stxxl.sourceforge.net
 *
 *  Copyright (C) 2002, 2005, 2008 Roman Dementiev <dementiev@mpi-sb.mpg.de>
 *  Copyright (C) 2008 Ilja Andronov <sni4ok@yandex.ru>
 *
 *  Distributed under the Boost Software License, Version 1.0.
 *  (See accompanying file LICENSE_1_0.txt or copy at
 *  http://www.boost.org/LICENSE_1_0.txt)
 **************************************************************************/

#include <stxxl/bits/io/ufs_file_base.h>

#ifdef BOOST_MSVC
 #include <windows.h>
#else
 #include <unistd.h>
 #include <fcntl.h>
#endif
#include <cstdio>

__STXXL_BEGIN_NAMESPACE

const char * ufs_file_base::io_type() const
{
    return "ufs_base";
}

ufs_file_base::ufs_file_base(
    const std::string & filename,
    int mode,
    int disk) : file_request_basic(disk), file_des(-1), mode_(mode), filename(filename)
{
    int fmode = 0;

#ifndef STXXL_DIRECT_IO_OFF
 #ifndef BOOST_MSVC
    if (mode & DIRECT)
        fmode |= O_SYNC | O_RSYNC | O_DSYNC | O_DIRECT;
 #endif
#endif

    if (mode & RDONLY)
        fmode |= O_RDONLY;

    if (mode & WRONLY)
        fmode |= O_WRONLY;

    if (mode & RDWR)
        fmode |= O_RDWR;

    if (mode & CREAT)
        fmode |= O_CREAT;

    if (mode & TRUNC)
        fmode |= O_TRUNC;

#ifdef BOOST_MSVC
    fmode |= O_BINARY;                     // the default in MS is TEXT mode
#endif

#ifdef BOOST_MSVC
    const int flags = S_IREAD | S_IWRITE;
#else
    const int flags = S_IREAD | S_IWRITE | S_IRGRP | S_IWGRP;
#endif

    if ((file_des = ::open(filename.c_str(), fmode, flags)) < 0)
        STXXL_THROW2(io_error, "Filedescriptor=" << file_des << " filename=" << filename << " fmode=" << fmode);
}

ufs_file_base::~ufs_file_base()
{
	close();
}

void ufs_file_base::close()
{
	if (file_des != -1)
	{
		scoped_mutex_lock fd_lock(fd_mutex);
		int res = ::close(file_des);

		// if successful, reset file descriptor
		if (res >= 0)
			file_des = -1;
		else
			stxxl_function_error(io_error);
	}
}

void ufs_file_base::lock()
{
#ifdef BOOST_MSVC
    // not yet implemented
#else
    scoped_mutex_lock fd_lock(fd_mutex);
    struct flock lock_struct;
    lock_struct.l_type = F_RDLCK | F_WRLCK;
    lock_struct.l_whence = SEEK_SET;
    lock_struct.l_start = 0;
    lock_struct.l_len = 0; // lock all bytes
    if ((::fcntl(file_des, F_SETLK, &lock_struct)) < 0)
        STXXL_THROW2(io_error, "Filedescriptor=" << file_des);
#endif
}

file::offset_type ufs_file_base::_size()
{
    struct stat st;
    stxxl_check_ge_0(::fstat(file_des, &st), io_error);
    return st.st_size;
}

file::offset_type ufs_file_base::size()
{
    scoped_mutex_lock fd_lock(fd_mutex);
    return _size();
}

void ufs_file_base::set_size(offset_type newsize)
{
    scoped_mutex_lock fd_lock(fd_mutex);
    offset_type cur_size = _size();

    if (!(mode_ & RDONLY))
    {
#ifdef BOOST_MSVC
        HANDLE hfile;
        stxxl_check_ge_0(hfile = (HANDLE) ::_get_osfhandle(file_des), io_error);

        LARGE_INTEGER desired_pos;
        desired_pos.QuadPart = newsize;

        if (!SetFilePointerEx(hfile, desired_pos, NULL, FILE_BEGIN))
            stxxl_win_lasterror_exit("SetFilePointerEx in ufs_file_base::set_size(..) oldsize=" << cur_size <<
                                     " newsize=" << newsize << " ", io_error);

        if (!SetEndOfFile(hfile))
            stxxl_win_lasterror_exit("SetEndOfFile oldsize=" << cur_size <<
                                     " newsize=" << newsize << " ", io_error);
#else
        stxxl_check_ge_0(::ftruncate(file_des, newsize), io_error);
#endif
    }

    if (newsize > cur_size)
        stxxl_check_ge_0(::lseek(file_des, newsize - 1, SEEK_SET), io_error);
}

void ufs_file_base::remove()
{
	close();
	::remove(filename.c_str());
}

__STXXL_END_NAMESPACE
// vim: et:ts=4:sw=4
<|endoftext|>


<commit_before>/*
 * opencog/util/Logger.cc
 *
 * Copyright (C) 2002-2007 Novamente LLC
 * Copyright (C) 2008 by OpenCog Foundation
 * Copyright (C) 2009, 2011 Linas Vepstas
 * Copyright (C) 2010 OpenCog Foundation
 * All Rights Reserved
 *
 * Written by Andre Senna <senna@vettalabs.com>
 *            Gustavo Gama <gama@vettalabs.com>
 *            Joel Pitt <joel@opencog.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "Logger.h"
#include "Config.h"

#ifndef CYGWIN
#include <cxxabi.h>
#include <execinfo.h>
#endif

#include <iostream>
#include <sstream>

#include <pthread.h>
#include <sched.h>
#include <stdarg.h>
#include <stdlib.h>
#include <time.h>

#ifdef WIN32_NOT_UNIX
#include <winsock2.h>
#undef ERROR
#undef DEBUG
#else
#include <sys/time.h>
#endif

#include <boost/algorithm/string.hpp>

#include <opencog/util/platform.h>

using namespace opencog;

// messages greater than this will be truncated
#define MAX_PRINTF_STYLE_MESSAGE_SIZE (1<<15)
const char* levelStrings[] = {"NONE", "ERROR", "WARN", "INFO", "DEBUG", "FINE"};

#ifndef CYGWIN /// @todo backtrace and backtrace_symbols is UNIX, we
              /// may need a WIN32 version
static void prt_backtrace(std::ostringstream& oss)
{
#define BT_BUFSZ 50
	void *bt_buf[BT_BUFSZ];

	int stack_depth = backtrace(bt_buf, BT_BUFSZ);
	char **syms = backtrace_symbols(bt_buf, stack_depth);

	// Start printing at a bit into the stack, so as to avoid recording
	// the logger functions in the stack trace.
	oss << "\tStack Trace:\n";
	for (int i=2; i < stack_depth; i++)
	{
		// Most things we'll print are mangled C++ names,
		// So demangle them, get them to pretty-print.
		char * begin = strchr(syms[i], '(');
		char * end = strchr(syms[i], '+');
		if (!(begin && end) || end <= begin)
		{
			// Failed to pull apart the symbol names
            oss << "\t" << i << ": " << syms[i] << "\n";
		}
		else
		{
			*begin = 0x0;
			oss << "\t" << i << ": " << syms[i] << " ";
			*begin = '(';
			size_t sz = 250;
			int status;
			char *fname = (char *) malloc(sz);
			*end = 0x0;
			char *rv = abi::__cxa_demangle(begin+1, fname, &sz, &status);
			*end = '+';
			if (rv) fname = rv; // might have re-alloced
			oss << "(" << fname << " " << end << std::endl;
			free(fname);
		}
	}
	oss << std::endl;
	free(syms);
}
#endif

Logger::~Logger()
{
#ifdef ASYNC_LOGGING
    // Wait for queue to empty
    flush();
    stopWriteLoop();
#endif

    if (f != NULL) fclose(f);
}

#ifdef ASYNC_LOGGING
void Logger::startWriteLoop()
{
    pthread_mutex_lock(&lock);
    if (!writingLoopActive)
    {
        writingLoopActive = true;
        m_Thread = boost::thread(&Logger::writingLoop, this);
    }
    pthread_mutex_unlock(&lock);
}

void Logger::stopWriteLoop()
{
    pthread_mutex_lock(&lock);
    pendingMessagesToWrite.cancel();
    // rejoin thread
    m_Thread.join();
    writingLoopActive = false;
    pthread_mutex_unlock(&lock);
}

void Logger::writingLoop()
{
    try
    {
        while (true)
        {
            // Must not pop until *after* the message has been written,
            // as otherwise, the flush() call will race with the write,
            // causing flush to report an empty queue, even though the
            // message has not actually been written yet.
            std::string* msg;
            pendingMessagesToWrite.wait_and_get(msg);
            writeMsg(*msg);
            pendingMessagesToWrite.pop();
            delete msg;
        }
    }
    catch (concurrent_queue< std::string* >::Canceled &e)
    {
        return;
    }
}

void Logger::flush()
{
    while (!pendingMessagesToWrite.empty())
    {
        sched_yield();
        usleep(100);
    }
}
#endif

void Logger::writeMsg(std::string &msg)
{
    pthread_mutex_lock(&lock);
    // delay opening the file until the first logging statement is issued;
    // this allows us to set the main logger's filename without creating
    // a useless log file with the default filename
    if (f == NULL)
    {
        if ((f = fopen(fileName.c_str(), "a")) == NULL)
        {
            fprintf(stderr, "[ERROR] Unable to open log file \"%s\"\n",
                    fileName.c_str());
            pthread_mutex_unlock(&lock);
            disable();
            return;
        }
        else
            enable();
    }

    // write to file
    fprintf(f, "%s", msg.c_str());
    fflush(f);
    pthread_mutex_unlock(&lock);

    // write to stdout
    if (printToStdout)
    {
        std::cout << msg;
        std::cout.flush();
    }
}

Logger::Logger(const std::string &fname, Logger::Level level, bool tsEnabled)
    : error(*this), warn(*this), info(*this), debug(*this), fine(*this)
{
    this->fileName.assign(fname);
    this->currentLevel = level;
    this->backTraceLevel = getLevelFromString(opencog::config()["BACK_TRACE_LOG_LEVEL"]);
    this->timestampEnabled = tsEnabled;
    this->printToStdout = false;

    this->logEnabled = true;
    this->f = NULL;

    pthread_mutex_init(&lock, NULL);
#ifdef ASYNC_LOGGING
    this->writingLoopActive = false;
    startWriteLoop();
#endif // ASYNC_LOGGING
}

Logger::Logger(const Logger& log)
    : error(*this), warn(*this), info(*this), debug(*this), fine(*this)
{
    pthread_mutex_init(&lock, NULL);
    set(log);
}

Logger& Logger::operator=(const Logger& log)
{
#ifdef ASYNC_LOGGING
    this->stopWriteLoop();
    pendingMessagesToWrite.cancel_reset();
#endif // ASYNC_LOGGING
    this->set(log);
    return *this;
}

void Logger::set(const Logger& log)
{
    pthread_mutex_lock(&lock);
    this->fileName.assign(log.fileName);
    this->currentLevel = log.currentLevel;
    this->backTraceLevel = log.backTraceLevel;
    this->timestampEnabled = log.timestampEnabled;
    this->printToStdout = log.printToStdout;

    this->logEnabled = log.logEnabled;
    this->f = log.f;
    pthread_mutex_unlock(&lock);

#ifdef ASYNC_LOGGING
    startWriteLoop();
#endif // ASYNC_LOGGING
}

// ***********************************************/
// API

void Logger::setLevel(Logger::Level newLevel)
{
    currentLevel = newLevel;
}

Logger::Level Logger::getLevel() const
{
    return currentLevel;
}

void Logger::setBackTraceLevel(Logger::Level newLevel)
{
    backTraceLevel = newLevel;
}

Logger::Level Logger::getBackTraceLevel() const
{
    return backTraceLevel;
}

void Logger::setFilename(const std::string& s)
{
    fileName.assign(s);

    pthread_mutex_lock(&lock);
    if (f != NULL) fclose(f);
    f = NULL;
    pthread_mutex_unlock(&lock);

    enable();
}

const std::string& Logger::getFilename()
{
    return fileName;
}

void Logger::setTimestampFlag(bool flag)
{
    timestampEnabled = flag;
}

void Logger::setPrintToStdoutFlag(bool flag)
{
    printToStdout = flag;
}

void Logger::setPrintErrorLevelStdout() {
    setPrintToStdoutFlag(true);
    setLevel(Logger::ERROR);
}

void Logger::enable()
{
    logEnabled = true;
}

void Logger::disable()
{
    logEnabled = false;
}

void Logger::log(Logger::Level level, const std::string &txt)
{
#ifdef ASYNC_LOGGING
    static const unsigned int max_queue_size_allowed = 1024;
#endif
    // Don't log if not enabled, or level is too low.
    if (!logEnabled) return;
    if (level > currentLevel) return;

    std::ostringstream oss;
    if (timestampEnabled)
    {
        struct timeval stv;
        struct tm stm;
        char timestamp[64];
        char timestampStr[256];

        ::gettimeofday(&stv, NULL);
        time_t t = stv.tv_sec;
        gmtime_r(&t, &stm);
        strftime(timestamp, sizeof(timestamp), "%F %T", &stm);
        snprintf(timestampStr, sizeof(timestampStr),
                "[%s:%03ld] ",timestamp, stv.tv_usec / 1000);
        oss << timestampStr;
    }

    oss << "[" << getLevelString(level) << "] " << txt << std::endl;

    if (level <= backTraceLevel)
    {
#ifndef CYGWIN
        prt_backtrace(oss);
#endif
    }
#ifdef ASYNC_LOGGING
    pendingMessagesToWrite.push(new std::string(oss.str()));

    // If the queue gets too full, block until it's flushed to file or
    // stdout
    if (pendingMessagesToWrite.approx_size() > max_queue_size_allowed) {
        flush();
    }
#else
    std::string temp(oss.str());
    writeMsg(temp);
#endif
}

void Logger::logva(Logger::Level level, const char *fmt, va_list args)
{
    if (level <= currentLevel) {
        char buffer[MAX_PRINTF_STYLE_MESSAGE_SIZE];
        vsnprintf(buffer, sizeof(buffer), fmt, args);
        std::string msg = buffer;
        log(level, msg);
    }
}

void Logger::log(Logger::Level level, const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(level, fmt, args); va_end(args);
}
void Logger::Error::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(ERROR, fmt, args); va_end(args);
}
void Logger::Warn::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(WARN,  fmt, args); va_end(args);
}
void Logger::Info::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(INFO,  fmt, args); va_end(args);
}
void Logger::Debug::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(DEBUG, fmt, args); va_end(args);
}
void Logger::Fine::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(FINE,  fmt, args); va_end(args);
}

bool Logger::isEnabled(Level level) const
{
    return level <= currentLevel;
}

bool Logger::isErrorEnabled() const
{
    return ERROR <= currentLevel;
}

bool Logger::isWarnEnabled() const
{
    return WARN <= currentLevel;
}

bool Logger::isInfoEnabled() const
{
    return INFO <= currentLevel;
}

bool Logger::isDebugEnabled() const
{
    return DEBUG <= currentLevel;
}

bool Logger::isFineEnabled() const
{
    return FINE <= currentLevel;
}

const char* Logger::getLevelString(const Logger::Level level)
{
    if (level == BAD_LEVEL)
        return "Bad level";
    else
        return levelStrings[level];
}

const Logger::Level Logger::getLevelFromString(const std::string& levelStr)
{
    unsigned int nLevels = sizeof(levelStrings) / sizeof(levelStrings[0]);
    for (unsigned int i = 0; i < nLevels; ++i) {
        if (boost::iequals(levelStrings[i], levelStr))
            return (Logger::Level) i;
    }
    return BAD_LEVEL;
}

// create and return the single instance
Logger& opencog::logger()
{
    static Logger instance;
    return instance;
}
<commit_msg>util logger: make valgrind tracing easier by ignoring intended races in logger<commit_after>/*
 * opencog/util/Logger.cc
 *
 * Copyright (C) 2002-2007 Novamente LLC
 * Copyright (C) 2008 by OpenCog Foundation
 * Copyright (C) 2009, 2011 Linas Vepstas
 * Copyright (C) 2010 OpenCog Foundation
 * All Rights Reserved
 *
 * Written by Andre Senna <senna@vettalabs.com>
 *            Gustavo Gama <gama@vettalabs.com>
 *            Joel Pitt <joel@opencog.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "Logger.h"
#include "Config.h"

#ifndef CYGWIN
#include <cxxabi.h>
#include <execinfo.h>
#endif

#include <iostream>
#include <sstream>

#include <pthread.h>
#include <sched.h>
#include <stdarg.h>
#include <stdlib.h>
#include <time.h>

#ifdef WIN32_NOT_UNIX
#include <winsock2.h>
#undef ERROR
#undef DEBUG
#else
#include <sys/time.h>
#endif

#ifdef HAVE_VALGRIND
#include <valgrind/drd.h>
#endif
#include <boost/algorithm/string.hpp>

#include <opencog/util/platform.h>

using namespace opencog;

// messages greater than this will be truncated
#define MAX_PRINTF_STYLE_MESSAGE_SIZE (1<<15)
const char* levelStrings[] = {"NONE", "ERROR", "WARN", "INFO", "DEBUG", "FINE"};

#ifndef CYGWIN /// @todo backtrace and backtrace_symbols is UNIX, we
              /// may need a WIN32 version
static void prt_backtrace(std::ostringstream& oss)
{
#define BT_BUFSZ 50
	void *bt_buf[BT_BUFSZ];

	int stack_depth = backtrace(bt_buf, BT_BUFSZ);
	char **syms = backtrace_symbols(bt_buf, stack_depth);

	// Start printing at a bit into the stack, so as to avoid recording
	// the logger functions in the stack trace.
	oss << "\tStack Trace:\n";
	for (int i=2; i < stack_depth; i++)
	{
		// Most things we'll print are mangled C++ names,
		// So demangle them, get them to pretty-print.
		char * begin = strchr(syms[i], '(');
		char * end = strchr(syms[i], '+');
		if (!(begin && end) || end <= begin)
		{
			// Failed to pull apart the symbol names
			oss << "\t" << i << ": " << syms[i] << "\n";
		}
		else
		{
			*begin = 0x0;
			oss << "\t" << i << ": " << syms[i] << " ";
			*begin = '(';
			size_t sz = 250;
			int status;
			char *fname = (char *) malloc(sz);
			*end = 0x0;
			char *rv = abi::__cxa_demangle(begin+1, fname, &sz, &status);
			*end = '+';
			if (rv) fname = rv; // might have re-alloced
			oss << "(" << fname << " " << end << std::endl;
			free(fname);
		}
	}
	oss << std::endl;
	free(syms);
}
#endif

Logger::~Logger()
{
#ifdef ASYNC_LOGGING
    // Wait for queue to empty
    flush();
    stopWriteLoop();
#endif

    if (f != NULL) fclose(f);
}

#ifdef ASYNC_LOGGING
void Logger::startWriteLoop()
{
    pthread_mutex_lock(&lock);
    if (!writingLoopActive)
    {
        writingLoopActive = true;
        m_Thread = boost::thread(&Logger::writingLoop, this);
    }
    pthread_mutex_unlock(&lock);
}

void Logger::stopWriteLoop()
{
    pthread_mutex_lock(&lock);
    pendingMessagesToWrite.cancel();
    // rejoin thread
    m_Thread.join();
    writingLoopActive = false;
    pthread_mutex_unlock(&lock);
}

void Logger::writingLoop()
{
    try
    {
        while (true)
        {
            // Must not pop until *after* the message has been written,
            // as otherwise, the flush() call will race with the write,
            // causing flush to report an empty queue, even though the
            // message has not actually been written yet.
            std::string* msg;
            pendingMessagesToWrite.wait_and_get(msg);
            writeMsg(*msg);
            pendingMessagesToWrite.pop();
            delete msg;
        }
    }
    catch (concurrent_queue< std::string* >::Canceled &e)
    {
        return;
    }
}

void Logger::flush()
{
    while (!pendingMessagesToWrite.empty())
    {
        sched_yield();
        usleep(100);
    }
}
#endif

void Logger::writeMsg(std::string &msg)
{
    pthread_mutex_lock(&lock);
    // delay opening the file until the first logging statement is issued;
    // this allows us to set the main logger's filename without creating
    // a useless log file with the default filename
    if (f == NULL)
    {
        if ((f = fopen(fileName.c_str(), "a")) == NULL)
        {
            fprintf(stderr, "[ERROR] Unable to open log file \"%s\"\n",
                    fileName.c_str());
            pthread_mutex_unlock(&lock);
            disable();
            return;
        }
        else
            enable();
    }

    // write to file
    fprintf(f, "%s", msg.c_str());
    fflush(f);
    pthread_mutex_unlock(&lock);

    // write to stdout
    if (printToStdout)
    {
        std::cout << msg;
        std::cout.flush();
    }
}

Logger::Logger(const std::string &fname, Logger::Level level, bool tsEnabled)
    : error(*this), warn(*this), info(*this), debug(*this), fine(*this)
{
    this->fileName.assign(fname);
    this->currentLevel = level;
    this->backTraceLevel = getLevelFromString(opencog::config()["BACK_TRACE_LOG_LEVEL"]);
    this->timestampEnabled = tsEnabled;
    this->printToStdout = false;

    this->logEnabled = true;
#ifdef HAVE_VALGRIND
    DRD_IGNORE_VAR(this->logEnabled);
#endif
    this->f = NULL;

    pthread_mutex_init(&lock, NULL);
#ifdef ASYNC_LOGGING
#ifdef HAVE_VALGRIND
    DRD_IGNORE_VAR(this->pendingMessagesToWrite);
#endif
    this->writingLoopActive = false;
    startWriteLoop();
#endif // ASYNC_LOGGING
}

Logger::Logger(const Logger& log)
    : error(*this), warn(*this), info(*this), debug(*this), fine(*this)
{
    pthread_mutex_init(&lock, NULL);
    set(log);
}

Logger& Logger::operator=(const Logger& log)
{
#ifdef ASYNC_LOGGING
    this->stopWriteLoop();
    pendingMessagesToWrite.cancel_reset();
#endif // ASYNC_LOGGING
    this->set(log);
    return *this;
}

void Logger::set(const Logger& log)
{
    pthread_mutex_lock(&lock);
    this->fileName.assign(log.fileName);
    this->currentLevel = log.currentLevel;
    this->backTraceLevel = log.backTraceLevel;
    this->timestampEnabled = log.timestampEnabled;
    this->printToStdout = log.printToStdout;

    this->logEnabled = log.logEnabled;
    this->f = log.f;
    pthread_mutex_unlock(&lock);

#ifdef ASYNC_LOGGING
    startWriteLoop();
#endif // ASYNC_LOGGING
}

// ***********************************************/
// API

void Logger::setLevel(Logger::Level newLevel)
{
    currentLevel = newLevel;
}

Logger::Level Logger::getLevel() const
{
    return currentLevel;
}

void Logger::setBackTraceLevel(Logger::Level newLevel)
{
    backTraceLevel = newLevel;
}

Logger::Level Logger::getBackTraceLevel() const
{
    return backTraceLevel;
}

void Logger::setFilename(const std::string& s)
{
    fileName.assign(s);

    pthread_mutex_lock(&lock);
    if (f != NULL) fclose(f);
    f = NULL;
    pthread_mutex_unlock(&lock);

    enable();
}

const std::string& Logger::getFilename()
{
    return fileName;
}

void Logger::setTimestampFlag(bool flag)
{
    timestampEnabled = flag;
}

void Logger::setPrintToStdoutFlag(bool flag)
{
    printToStdout = flag;
}

void Logger::setPrintErrorLevelStdout() {
    setPrintToStdoutFlag(true);
    setLevel(Logger::ERROR);
}

void Logger::enable()
{
    logEnabled = true;
}

void Logger::disable()
{
    logEnabled = false;
}

void Logger::log(Logger::Level level, const std::string &txt)
{
#ifdef ASYNC_LOGGING
    static const unsigned int max_queue_size_allowed = 1024;
#endif
    // Don't log if not enabled, or level is too low.
    if (!logEnabled) return;
    if (level > currentLevel) return;

    std::ostringstream oss;
    if (timestampEnabled)
    {
        struct timeval stv;
        struct tm stm;
        char timestamp[64];
        char timestampStr[256];

        ::gettimeofday(&stv, NULL);
        time_t t = stv.tv_sec;
        gmtime_r(&t, &stm);
        strftime(timestamp, sizeof(timestamp), "%F %T", &stm);
        snprintf(timestampStr, sizeof(timestampStr),
                "[%s:%03ld] ",timestamp, stv.tv_usec / 1000);
        oss << timestampStr;
    }

    oss << "[" << getLevelString(level) << "] " << txt << std::endl;

    if (level <= backTraceLevel)
    {
#ifndef CYGWIN
        prt_backtrace(oss);
#endif
    }
#ifdef ASYNC_LOGGING
    pendingMessagesToWrite.push(new std::string(oss.str()));

    // If the queue gets too full, block until it's flushed to file or
    // stdout
    if (pendingMessagesToWrite.approx_size() > max_queue_size_allowed) {
        flush();
    }
#else
    std::string temp(oss.str());
    writeMsg(temp);
#endif
}

void Logger::logva(Logger::Level level, const char *fmt, va_list args)
{
    if (level <= currentLevel) {
        char buffer[MAX_PRINTF_STYLE_MESSAGE_SIZE];
        vsnprintf(buffer, sizeof(buffer), fmt, args);
        std::string msg = buffer;
        log(level, msg);
    }
}

void Logger::log(Logger::Level level, const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logva(level, fmt, args); va_end(args);
}
void Logger::Error::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(ERROR, fmt, args); va_end(args);
}
void Logger::Warn::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(WARN,  fmt, args); va_end(args);
}
void Logger::Info::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(INFO,  fmt, args); va_end(args);
}
void Logger::Debug::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(DEBUG, fmt, args); va_end(args);
}
void Logger::Fine::operator()(const char *fmt, ...)
{
    va_list args; va_start(args, fmt); logger.logva(FINE,  fmt, args); va_end(args);
}

bool Logger::isEnabled(Level level) const
{
    return level <= currentLevel;
}

bool Logger::isErrorEnabled() const
{
    return ERROR <= currentLevel;
}

bool Logger::isWarnEnabled() const
{
    return WARN <= currentLevel;
}

bool Logger::isInfoEnabled() const
{
    return INFO <= currentLevel;
}

bool Logger::isDebugEnabled() const
{
    return DEBUG <= currentLevel;
}

bool Logger::isFineEnabled() const
{
    return FINE <= currentLevel;
}

const char* Logger::getLevelString(const Logger::Level level)
{
    if (level == BAD_LEVEL)
        return "Bad level";
    else
        return levelStrings[level];
}

const Logger::Level Logger::getLevelFromString(const std::string& levelStr)
{
    unsigned int nLevels = sizeof(levelStrings) / sizeof(levelStrings[0]);
    for (unsigned int i = 0; i < nLevels; ++i) {
        if (boost::iequals(levelStrings[i], levelStr))
            return (Logger::Level) i;
    }
    return BAD_LEVEL;
}

// create and return the single instance
Logger& opencog::logger()
{
    static Logger instance;
    return instance;
}
<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <time.h>
#include <vector>

#include "aggregate_bandwidth.h"
#include "block_size.h"
#include "block_size.h"
#include "derecho/derecho.h"
#include "log_results.h"
#include "rdmc/rdmc.h"
#include "rdmc/util.h"

using std::vector;
using std::map;
using std::cout;
using std::endl;

using namespace derecho;

struct exp_result {
    uint32_t num_nodes;
    uint num_senders_selector;
    long long unsigned int max_msg_size;
    unsigned int window_size;
    int num_messages;
    int send_medium;
    int raw_mode;
    double bw;

    void print(std::ofstream &fout) {
        fout << num_nodes << " " << num_senders_selector << " "
             << max_msg_size << " " << window_size << " "
             << num_messages << " " << send_medium << " "
             << raw_mode << " " << bw << endl;
    }
};

int main(int argc, char *argv[]) {
    try {
        if(argc < 7) {
            cout << "Insufficient number of command line arguments" << endl;
            cout << "Enter max_msg_size, num_senders_selector, window_size, num_messages, send_medium, raw_mode" << endl;
            cout << "Thank you" << endl;
            exit(1);
        }
        pthread_setname_np(pthread_self(), "bw_test");
        srand(time(NULL));

        uint32_t server_rank = 0;
        uint32_t node_rank;
        uint32_t num_nodes;

        map<uint32_t, std::string> node_addresses;

        rdmc::query_addresses(node_addresses, node_rank);
        num_nodes = node_addresses.size();

        vector<uint32_t> members(num_nodes);
        for(uint32_t i = 0; i < num_nodes; ++i) {
            members[i] = i;
        }

        const long long unsigned int max_msg_size = atoll(argv[1]);
        const long long unsigned int block_size = get_block_size(max_msg_size);
        const uint num_senders_selector = atoi(argv[2]);
        const unsigned int window_size = atoi(argv[3]);
        const int num_messages = atoi(argv[4]);
        const int send_medium = atoi(argv[5]);
        const int raw_mode = atoi(argv[6]);

        volatile bool done = false;
        auto stability_callback = [
            &num_messages,
            &done,
            &num_nodes,
            num_senders_selector,
            num_last_received = 0u
        ](uint32_t subgroup, int sender_id, long long int index, char *buf, long long int msg_size) mutable {
            // cout << "In stability callback; sender = " << sender_id
            // << ", index = " << index << endl;
            if(num_senders_selector == 0) {
                if(index == num_messages - 1 && sender_id == (int)num_nodes - 1) {
                    done = true;
                }
            } else if(num_senders_selector == 1) {
                if(index == num_messages - 1) {
                    ++num_last_received;
                }
                if(num_last_received == num_nodes / 2) {
                    done = true;
                }
            } else {
                if(index == num_messages - 1) {
                    done = true;
                }
            }
        };

        derecho::Mode mode = derecho::Mode::ORDERED;
        if(raw_mode) {
            mode = derecho::Mode::RAW;
        }

        auto membership_function = [num_senders_selector, mode, num_nodes](const View &curr_view, int &next_unassigned_rank, bool previous_was_successful) {
            subgroup_shard_layout_t subgroup_vector(1);
            auto num_members = curr_view.members.size();
            if(num_members < num_nodes) {
                throw derecho::subgroup_provisioning_exception();
            }
            if(num_senders_selector == 0) {
                subgroup_vector[0].emplace_back(curr_view.make_subview(curr_view.members, mode));
            } else {
                std::vector<int> is_sender(num_members, 1);
                if(num_senders_selector == 1) {
                    for(uint i = 0; i <= (num_members - 1) / 2; ++i) {
                        is_sender[i] = 0;
                    }
                } else {
                    for(uint i = 0; i < num_members - 1; ++i) {
                        is_sender[i] = 0;
                    }
                }
                subgroup_vector[0].emplace_back(curr_view.make_subview(curr_view.members, mode, is_sender));
            }
	    next_unassigned_rank = curr_view.members.size();
            return subgroup_vector;
        };

        std::map<std::type_index, shard_view_generator_t> subgroup_map = {{std::type_index(typeid(RawObject)), membership_function}};
        derecho::SubgroupInfo one_raw_group(subgroup_map);

        std::unique_ptr<derecho::Group<>> managed_group;
        if(node_rank == server_rank) {
            managed_group = std::make_unique<derecho::Group<>>(
                    node_rank, node_addresses[node_rank],
                    derecho::CallbackSet{stability_callback, nullptr},
                    one_raw_group,
                    derecho::DerechoParams{max_msg_size, block_size, std::string(), window_size});
        } else {
            managed_group = std::make_unique<derecho::Group<>>(
                    node_rank, node_addresses[node_rank],
                    node_addresses[server_rank],
                    derecho::CallbackSet{stability_callback, nullptr},
                    one_raw_group);
        }

        cout << "Finished constructing/joining ManagedGroup" << endl;

        while(managed_group->get_members().size() < num_nodes) {
        }
        auto members_order = managed_group->get_members();
        cout << "The order of members is :" << endl;
        for(auto id : members_order) {
            cout << id << " ";
        }
        cout << endl;

        auto send_all = [&]() {
            RawSubgroup &group_as_subgroup = managed_group->get_subgroup<RawObject>();
            for(int i = 0; i < num_messages; ++i) {
                // cout << "Asking for a buffer" << endl;
                char *buf = group_as_subgroup.get_sendbuffer_ptr(max_msg_size, send_medium);
                while(!buf) {
                    buf = group_as_subgroup.get_sendbuffer_ptr(max_msg_size, send_medium);
                }
                buf[0] = '0' + i;
                // cout << "Obtained a buffer, sending" << endl;
                group_as_subgroup.send();
            }
        };

        struct timespec start_time;
        // start timer
        clock_gettime(CLOCK_REALTIME, &start_time);
        if(num_senders_selector == 0) {
            send_all();
        } else if(num_senders_selector == 1) {
            if(node_rank > (num_nodes - 1) / 2) {
                send_all();
            }
        } else {
            if(node_rank == num_nodes - 1) {
                send_all();
            }
        }
        while(!done) {
        }
        struct timespec end_time;
        clock_gettime(CLOCK_REALTIME, &end_time);
        long long int nanoseconds_elapsed = (end_time.tv_sec - start_time.tv_sec) * (long long int)1e9 + (end_time.tv_nsec - start_time.tv_nsec);
        double bw;
        if(num_senders_selector == 0) {
            bw = (max_msg_size * num_messages * num_nodes + 0.0) / nanoseconds_elapsed;
        } else if(num_senders_selector == 1) {
            bw = (max_msg_size * num_messages * (num_nodes / 2) + 0.0) / nanoseconds_elapsed;
        } else {
            bw = (max_msg_size * num_messages + 0.0) / nanoseconds_elapsed;
        }
        double avg_bw = aggregate_bandwidth(members, node_rank, bw);
        if(node_rank == 0) {
            log_results(exp_result{num_nodes, num_senders_selector, max_msg_size,
                                   window_size, num_messages, send_medium,
                                   raw_mode, avg_bw},
                        "data_derecho_bw");
        }

        managed_group->barrier_sync();
        managed_group->leave();
        sst::verbs_destroy();
        cout << "Finished destroying managed_group" << endl;
        std::this_thread::sleep_for(std::chrono::seconds(10));
    } catch(const std::exception &e) {
        cout << "Exception in main: " << e.what() << endl;
        cout << "main shutting down" << endl;
    }
}
<commit_msg>Small<commit_after>#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <time.h>
#include <vector>

#include "aggregate_bandwidth.h"
#include "block_size.h"
#include "block_size.h"
#include "derecho/derecho.h"
#include "log_results.h"
#include "rdmc/rdmc.h"
#include "rdmc/util.h"

using std::vector;
using std::map;
using std::cout;
using std::endl;

using namespace derecho;

struct exp_result {
    uint32_t num_nodes;
    uint num_senders_selector;
    long long unsigned int max_msg_size;
    unsigned int window_size;
    int num_messages;
    int send_medium;
    int raw_mode;
    double bw;

    void print(std::ofstream &fout) {
        fout << num_nodes << " " << num_senders_selector << " "
             << max_msg_size << " " << window_size << " "
             << num_messages << " " << send_medium << " "
             << raw_mode << " " << bw << endl;
    }
};

int main(int argc, char *argv[]) {
    try {
        if(argc < 7) {
            cout << "Insufficient number of command line arguments" << endl;
            cout << "Enter max_msg_size, num_senders_selector, window_size, num_messages, send_medium, raw_mode" << endl;
            cout << "Thank you" << endl;
            exit(1);
        }
        pthread_setname_np(pthread_self(), "bw_test");
        srand(time(NULL));

        uint32_t server_rank = 0;
        uint32_t node_rank;
        uint32_t num_nodes;

        map<uint32_t, std::string> node_addresses;

        rdmc::query_addresses(node_addresses, node_rank);
        num_nodes = node_addresses.size();

        vector<uint32_t> members(num_nodes);
        for(uint32_t i = 0; i < num_nodes; ++i) {
            members[i] = i;
        }

        const long long unsigned int max_msg_size = atoll(argv[1]);
        const long long unsigned int block_size = get_block_size(max_msg_size);
        const uint num_senders_selector = atoi(argv[2]);
        const unsigned int window_size = atoi(argv[3]);
        const int num_messages = atoi(argv[4]);
        const int send_medium = atoi(argv[5]);
        const int raw_mode = atoi(argv[6]);

        volatile bool done = false;
        auto stability_callback = [
            &num_messages,
            &done,
            &num_nodes,
            num_senders_selector,
            num_last_received = 0u
        ](uint32_t subgroup, int sender_id, long long int index, char *buf, long long int msg_size) mutable {
            // cout << "In stability callback; sender = " << sender_id
            // << ", index = " << index << endl;
            if(num_senders_selector == 0) {
                if(index == num_messages - 1 && sender_id == (int)num_nodes - 1) {
                    done = true;
                }
            } else if(num_senders_selector == 1) {
                if(index == num_messages - 1) {
                    ++num_last_received;
                }
                if(num_last_received == num_nodes / 2) {
                    done = true;
                }
            } else {
                if(index == num_messages - 1) {
                    done = true;
                }
            }
        };

        derecho::Mode mode = derecho::Mode::ORDERED;
        if(raw_mode) {
            mode = derecho::Mode::RAW;
        }

        auto membership_function = [num_senders_selector, mode, num_nodes](const View &curr_view, int &next_unassigned_rank, bool previous_was_successful) {
            subgroup_shard_layout_t subgroup_vector(1);
            auto num_members = curr_view.members.size();
            if(num_members < num_nodes) {
                throw derecho::subgroup_provisioning_exception();
            }
            if(num_senders_selector == 0) {
                subgroup_vector[0].emplace_back(curr_view.make_subview(curr_view.members, mode));
            } else {
                std::vector<int> is_sender(num_members, 1);
                if(num_senders_selector == 1) {
                    for(uint i = 0; i <= (num_members - 1) / 2; ++i) {
                        is_sender[i] = 0;
                    }
                } else {
                    for(uint i = 0; i < num_members - 1; ++i) {
                        is_sender[i] = 0;
                    }
                }
                subgroup_vector[0].emplace_back(curr_view.make_subview(curr_view.members, mode, is_sender));
            }
            next_unassigned_rank = curr_view.members.size();
            return subgroup_vector;
        };

        std::map<std::type_index, shard_view_generator_t> subgroup_map = {{std::type_index(typeid(RawObject)), membership_function}};
        derecho::SubgroupInfo one_raw_group(subgroup_map);

        std::unique_ptr<derecho::Group<>> managed_group;
        if(node_rank == server_rank) {
            managed_group = std::make_unique<derecho::Group<>>(
                    node_rank, node_addresses[node_rank],
                    derecho::CallbackSet{stability_callback, nullptr},
                    one_raw_group,
                    derecho::DerechoParams{max_msg_size, block_size, std::string(), window_size});
        } else {
            managed_group = std::make_unique<derecho::Group<>>(
                    node_rank, node_addresses[node_rank],
                    node_addresses[server_rank],
                    derecho::CallbackSet{stability_callback, nullptr},
                    one_raw_group);
        }

        cout << "Finished constructing/joining ManagedGroup" << endl;

        while(managed_group->get_members().size() < num_nodes) {
        }
        auto members_order = managed_group->get_members();
        cout << "The order of members is :" << endl;
        for(auto id : members_order) {
            cout << id << " ";
        }
        cout << endl;

        auto send_all = [&]() {
            RawSubgroup &group_as_subgroup = managed_group->get_subgroup<RawObject>();
            for(int i = 0; i < num_messages; ++i) {
                // cout << "Asking for a buffer" << endl;
                char *buf = group_as_subgroup.get_sendbuffer_ptr(max_msg_size, send_medium);
                while(!buf) {
                    buf = group_as_subgroup.get_sendbuffer_ptr(max_msg_size, send_medium);
                }
                buf[0] = '0' + i;
                // cout << "Obtained a buffer, sending" << endl;
                group_as_subgroup.send();
            }
        };

        struct timespec start_time;
        // start timer
        clock_gettime(CLOCK_REALTIME, &start_time);
        if(num_senders_selector == 0) {
            send_all();
        } else if(num_senders_selector == 1) {
            if(node_rank > (num_nodes - 1) / 2) {
                send_all();
            }
        } else {
            if(node_rank == num_nodes - 1) {
                send_all();
            }
        }
        while(!done) {
        }
        struct timespec end_time;
        clock_gettime(CLOCK_REALTIME, &end_time);
        long long int nanoseconds_elapsed = (end_time.tv_sec - start_time.tv_sec) * (long long int)1e9 + (end_time.tv_nsec - start_time.tv_nsec);
        double bw;
        if(num_senders_selector == 0) {
            bw = (max_msg_size * num_messages * num_nodes + 0.0) / nanoseconds_elapsed;
        } else if(num_senders_selector == 1) {
            bw = (max_msg_size * num_messages * (num_nodes / 2) + 0.0) / nanoseconds_elapsed;
        } else {
            bw = (max_msg_size * num_messages + 0.0) / nanoseconds_elapsed;
        }
        double avg_bw = aggregate_bandwidth(members, node_rank, bw);
        if(node_rank == 0) {
            log_results(exp_result{num_nodes, num_senders_selector, max_msg_size,
                                   window_size, num_messages, send_medium,
                                   raw_mode, avg_bw},
                        "data_derecho_bw");
        }

        managed_group->barrier_sync();
        // managed_group->leave();
        // sst::verbs_destroy();
        exit(0);
        cout << "Finished destroying managed_group" << endl;
        std::this_thread::sleep_for(std::chrono::seconds(10));
    } catch(const std::exception &e) {
        cout << "Exception in main: " << e.what() << endl;
        cout << "main shutting down" << endl;
    }
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * c7a/data/manager.hpp
 *
 * Part of Project c7a.
 *
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef C7A_DATA_MANAGER_HEADER
#define C7A_DATA_MANAGER_HEADER

#include <c7a/common/logger.hpp>
#include <c7a/data/file.hpp>
#include <c7a/data/iterator.hpp>
#include <c7a/data/output_line_emitter.hpp>
#include <c7a/data/socket_target.hpp>
#include <c7a/data/channel.hpp>
#include <c7a/data/channel_multiplexer.hpp>
#include <c7a/data/repository.hpp>

#include <functional>
#include <map>
#include <memory>
#include <stdexcept>
#include <string>

namespace c7a {
namespace net {
class Group;
}
namespace data {

using FilePtr = std::shared_ptr<File>;

//! Identification for DIAs
using FilePtr = std::shared_ptr<File>
//! Manages all kind of memory for data elements
//!
//!
//! Provides Channel creation for sending / receiving data from other workers.
                class Manager
      {
      public:
          Manager(net::DispatcherThread& dispatcher)
              : cmp_(dispatcher) { }

          //! non-copyable: delete copy-constructor
          Manager(const Manager&) = delete;
          //! non-copyable: delete assignment operator
          Manager& operator = (const Manager&) = delete;

          //! Connect net::Group. Forwarded To ChannelMultiplexer.
          void Connect(net::Group* group) {
              cmp_.Connect(group);
          }

          //! Closes all client connections, files and everything.
          void Close() {
              for (auto& f : files) {
                  f.second.Close();
              }
              cmp_.Close();
          }

          //! returns iterator on requested partition or network channel.
          //!
          //! Data can be emitted into this partition / received on the channel even
          //! after the iterator was created.
          //!
          //! \param id ID of the DIA / Channel - determined by AllocateDIA() / AllocateNetworkChannel()
          template <class T>
          Iterator<T> GetIterator(const ChainId& id) {
              return Iterator<T>(*GetChainOrDie(id));
          }

          BlockReader<BlockSize> GetBlockReader(const DataId& id) {
              return BlockReader<BlockSize>(GetFileOrDie(id));
          }

#if FIXUP_LATER
          //! Docu see net::ChannelMultiplexer::Scatter()
          template <class T>
          void Scatter(const DataId& source, const DataId& target, std::vector<size_t> offsets) {
              assert(source.type == LOCAL);
              assert(target.type == NETWORK);
              assert(files_.Contains(source));
              cmp_.Scatter<T>(files_(source), target, offsets);
          }
#endif      // FIXUP_LATER

          //! Returns a number that uniquely addresses a File
          //! Calls to this method alter the data managers state.
          //! Calls to this method must be in deterministic order for all workers!
          DataId AllocateFileId() {
              return files_.AllocateNext();
          }

          //! Returns a number that uniquely addresses a network channel
          //! Calls to this method alter the data managers state.
          //! Calls to this method must be in deterministic order for all workers!
          //! \param order_preserving indicates if the channel should preserve the order of the receiving packages
          ChannelId AllocateChannelId() {
              return cmp_.AllocateNext();
          }

          //! Returns a reference to an existing Channel.
          std::shared_ptr<net::Channel> GetChannel(const ChannelId id) {
              assert(cmp_.HasChannel(id));
              return std::move(cmp_.GetOrCreateChannel(id));
          }

          //! Returns a reference to a new Channel.
          std::shared_ptr<net::Channel> GetNewChannel() {
              return std::move(cmp_.GetOrCreateChannel(AllocateChannelId()));
          }

          //! Returns a new, anonymous File object containing a sequence of local Blocks.
          FilePtr GetFile() {
              return File();
          }

          //! Returns a named file that has been allocated via \ref AllocateFileId()
          FilePtr GetFile(const DataId& id) {
              return data_(id);
          }

          template <class T>
          std::vector<BlockWriter<T> > GetNetworkEmitters(DataId id) {
              assert(id.type == NETWORK);
              if (!cmp_.HasDataOn(id)) {
                  throw std::runtime_error("target channel id unknown.");
              }
              return cmp_.OpenChannel(id);
          }

      private:
          static const bool debug = false;
          net::ChannelMultiplexer cmp_;
          DataRepository<File> data_;
      };
} // namespace data
} // namespace c7a

#endif // !C7A_DATA_MANAGER_HEADER

/******************************************************************************/
<commit_msg>reset manager to use old stuff<commit_after>/*******************************************************************************
 * c7a/data/manager.hpp
 *
 * Part of Project c7a.
 *
 *
 * This file has no license. Only Chuck Norris can compile it.
 ******************************************************************************/

#pragma once
#ifndef C7A_DATA_MANAGER_HEADER
#define C7A_DATA_MANAGER_HEADER

#include <c7a/api/input_line_iterator.hpp>
#include <c7a/common/logger.hpp>
#include <c7a/data/buffer_chain.hpp>
#include <c7a/data/buffer_chain_manager.hpp>
#include <c7a/data/emitter.hpp>
#include <c7a/data/file.hpp>
#include <c7a/data/iterator.hpp>
#include <c7a/data/output_line_emitter.hpp>
#include <c7a/data/socket_target.hpp>
#include <c7a/data/channel.hpp>
#include <c7a/data/channel_multiplexer.hpp>

#include <functional>
#include <map>
#include <memory>
#include <stdexcept>
#include <string>

namespace c7a {
namespace data {

struct BufferChain;

//! Identification for DIAs
typedef ChainId DIAId;

//! Manages all kind of memory for data elements
//!
//!
//! Provides Channel creation for sending / receiving data from other workers.
class Manager
{
public:
    Manager(net::DispatcherThread& dispatcher)
        : cmp_(dispatcher) { }

    //! non-copyable: delete copy-constructor
    Manager(const Manager&) = delete;
    //! non-copyable: delete assignment operator
    Manager& operator = (const Manager&) = delete;

    //! Connect net::Group. Forwarded To ChannelMultiplexer.
    void Connect(net::Group* group) {
        cmp_.Connect(group);
    }

    //! Closes all client connections. Forwarded To ChannelMultiplexer.
    void Close() {
        cmp_.Close();
    }

    //! returns iterator on requested partition or network channel.
    //!
    //! Data can be emitted into this partition / received on the channel even
    //! after the iterator was created.
    //!
    //! \param id ID of the DIA / Channel - determined by AllocateDIA() / AllocateNetworkChannel()
    template <class T>
    Iterator<T> GetIterator(const ChainId& id) {
        return Iterator<T>(*GetChainOrDie(id));
    }

    //! Returns the number of elements that are stored on this worker
    //! Returns -1 if the channel or dia was not closed (yet)
    //! This call is blocking until the DIA is closed
    //! throws if id is unknown
    size_t GetNumElements(const ChainId& id) {
        std::shared_ptr<BufferChain> chain = GetChainOrDie(id);
        if (!chain->IsClosed())
            chain->WaitUntilClosed();
        return chain->size();
    }

#if FIXUP_LATER
    //! Docu see net::ChannelMultiplexer::Scatter()
    template <class T>
    void Scatter(const ChainId& source, const ChainId& target, std::vector<size_t> offsets) {
        assert(source.type == LOCAL);
        assert(target.type == NETWORK);
        assert(dias_.Contains(source));
        cmp_.Scatter<T>(dias_.Chain(source), target, offsets);
    }
#endif      // FIXUP_LATER

    //! Returns a number that uniquely addresses a DIA
    //! Calls to this method alter the data managers state.
    //! Calls to this method must be in deterministic order for all workers!
    DIAId AllocateDIA() {
        return dias_.AllocateNext();
    }

    //! Returns a number that uniquely addresses a network channel
    //! Calls to this method alter the data managers state.
    //! Calls to this method must be in deterministic order for all workers!
    //! \param order_preserving indicates if the channel should preserve the order of the receiving packages
    ChannelId AllocateChannelId() {
        return cmp_.AllocateNext();
    }

    //! Returns a reference to an existing Channel.
    std::shared_ptr<net::Channel> GetChannel(const ChannelId id) {
        assert(cmp_.HasChannel(id));
        return std::move(cmp_.GetOrCreateChannel(id));
    }

    //! Returns a reference to a new Channel.
    std::shared_ptr<net::Channel> GetNewChannel() {
        return std::move(cmp_.GetOrCreateChannel(AllocateChannelId()));
    }

    //! Returns an emitter that can be used to fill a DIA
    //! Emitters can push data into DIAs even if an intertor was created before.
    //! Data is only visible to the iterator if the emitter was flushed.
    // template <class T>
    // Emitter<T> GetLocalEmitter(DIAId id) {
    //     assert(id.type == LOCAL);
    //     if (!dias_.Contains(id)) {
    //         throw std::runtime_error("target dia id unknown.");
    //     }
    //     return Emitter<T>(dias_.Chain(id));
    // }

    //! Returns a new File object containing a sequence of local Blocks.
    File GetFile() {
        return File();
    }

    template <class T>
    std::vector<Emitter> GetNetworkEmitters(ChannelId id) {
        assert(id.type == NETWORK);
        if (!cmp_.HasDataOn(id)) {
            throw std::runtime_error("target channel id unknown.");
        }
        return cmp_.OpenChannel(id);
    }

private:
    static const bool debug = false;
    net::ChannelMultiplexer cmp_;

    BufferChainManager dias_;

    std::shared_ptr<BufferChain> GetChainOrDie(const ChainId& id) {
        if (id.type == LOCAL) {
            if (!dias_.Contains(id)) {
                throw std::runtime_error("target dia id unknown.");
            }
            return dias_.Chain(id);
        }
        else {
            if (!cmp_.HasDataOn(id)) {
                throw std::runtime_error("target channel id unknown.");
            }
            return cmp_.AccessData(id);
        }
    }
};

} // namespace data
} // namespace c7a

#endif // !C7A_DATA_MANAGER_HEADER

/******************************************************************************/
<|endoftext|>


<commit_before>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/platform/windows/public/flutter_windows.h"

#include <io.h>

#include <algorithm>
#include <cassert>
#include <chrono>
#include <cstdlib>
#include <filesystem>
#include <iostream>
#include <memory>
#include <vector>

#include "flutter/shell/platform/windows/dpi_utils_win32.h"
#include "flutter/shell/platform/windows/flutter_window_win32.h"

// Returns the engine corresponding to the given opaque API handle.
static flutter::FlutterWindowsEngine* EngineFromHandle(
    FlutterDesktopEngineRef ref) {
  return reinterpret_cast<flutter::FlutterWindowsEngine*>(ref);
}

FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate(
    int width,
    int height,
    FlutterDesktopEngineRef engine) {
  std::unique_ptr<flutter::WindowBindingHandler> window_wrapper =
      std::make_unique<flutter::FlutterWindowWin32>(width, height);

  auto state = std::make_unique<FlutterDesktopViewControllerState>();
  state->view =
      std::make_unique<flutter::FlutterWindowsView>(std::move(window_wrapper));
  // Take ownership of the engine, starting it if necessary.
  state->view->SetEngine(
      std::unique_ptr<flutter::FlutterWindowsEngine>(EngineFromHandle(engine)));
  state->view->CreateRenderSurface();
  if (!state->view->GetEngine()->running()) {
    if (!state->view->GetEngine()->RunWithEntrypoint(nullptr)) {
      return nullptr;
    }
  }

  // Must happen after engine is running.
  state->view->SendInitialBounds();
  return state.release();
}

bool FlutterDesktopViewControllerHandleTopLevelWindowProc(
    FlutterDesktopViewControllerRef controller,
    HWND hwnd,
    UINT message,
    WPARAM wparam,
    LPARAM lparam,
    LRESULT* result) {
  std::optional<LRESULT> delegate_result =
      controller->view->GetEngine()
          ->window_proc_delegate_manager()
          ->OnTopLevelWindowProc(hwnd, message, wparam, lparam);
  if (delegate_result) {
    *result = *delegate_result;
  }
  return delegate_result.has_value();
}

uint64_t FlutterDesktopEngineProcessMessages(FlutterDesktopEngineRef engine) {
  return std::numeric_limits<uint64_t>::max();
}

void FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate(
    FlutterDesktopPluginRegistrarRef registrar,
    FlutterDesktopWindowProcCallback delegate,
    void* user_data) {
  registrar->engine->window_proc_delegate_manager()
      ->RegisterTopLevelWindowProcDelegate(delegate, user_data);
}

void FlutterDesktopPluginRegistrarUnregisterTopLevelWindowProcDelegate(
    FlutterDesktopPluginRegistrarRef registrar,
    FlutterDesktopWindowProcCallback delegate) {
  registrar->engine->window_proc_delegate_manager()
      ->UnregisterTopLevelWindowProcDelegate(delegate);
}

UINT FlutterDesktopGetDpiForHWND(HWND hwnd) {
  return flutter::GetDpiForHWND(hwnd);
}

UINT FlutterDesktopGetDpiForMonitor(HMONITOR monitor) {
  return flutter::GetDpiForMonitor(monitor);
}
<commit_msg>Return a maximum nanoseconds value in FlutterDesktopEngineProcessMessages (#26026)<commit_after>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/platform/windows/public/flutter_windows.h"

#include <io.h>

#include <algorithm>
#include <cassert>
#include <chrono>
#include <cstdlib>
#include <filesystem>
#include <iostream>
#include <memory>
#include <vector>

#include "flutter/shell/platform/windows/dpi_utils_win32.h"
#include "flutter/shell/platform/windows/flutter_window_win32.h"

// Returns the engine corresponding to the given opaque API handle.
static flutter::FlutterWindowsEngine* EngineFromHandle(
    FlutterDesktopEngineRef ref) {
  return reinterpret_cast<flutter::FlutterWindowsEngine*>(ref);
}

FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate(
    int width,
    int height,
    FlutterDesktopEngineRef engine) {
  std::unique_ptr<flutter::WindowBindingHandler> window_wrapper =
      std::make_unique<flutter::FlutterWindowWin32>(width, height);

  auto state = std::make_unique<FlutterDesktopViewControllerState>();
  state->view =
      std::make_unique<flutter::FlutterWindowsView>(std::move(window_wrapper));
  // Take ownership of the engine, starting it if necessary.
  state->view->SetEngine(
      std::unique_ptr<flutter::FlutterWindowsEngine>(EngineFromHandle(engine)));
  state->view->CreateRenderSurface();
  if (!state->view->GetEngine()->running()) {
    if (!state->view->GetEngine()->RunWithEntrypoint(nullptr)) {
      return nullptr;
    }
  }

  // Must happen after engine is running.
  state->view->SendInitialBounds();
  return state.release();
}

bool FlutterDesktopViewControllerHandleTopLevelWindowProc(
    FlutterDesktopViewControllerRef controller,
    HWND hwnd,
    UINT message,
    WPARAM wparam,
    LPARAM lparam,
    LRESULT* result) {
  std::optional<LRESULT> delegate_result =
      controller->view->GetEngine()
          ->window_proc_delegate_manager()
          ->OnTopLevelWindowProc(hwnd, message, wparam, lparam);
  if (delegate_result) {
    *result = *delegate_result;
  }
  return delegate_result.has_value();
}

uint64_t FlutterDesktopEngineProcessMessages(FlutterDesktopEngineRef engine) {
  return std::chrono::nanoseconds::max().count();
}

void FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate(
    FlutterDesktopPluginRegistrarRef registrar,
    FlutterDesktopWindowProcCallback delegate,
    void* user_data) {
  registrar->engine->window_proc_delegate_manager()
      ->RegisterTopLevelWindowProcDelegate(delegate, user_data);
}

void FlutterDesktopPluginRegistrarUnregisterTopLevelWindowProcDelegate(
    FlutterDesktopPluginRegistrarRef registrar,
    FlutterDesktopWindowProcCallback delegate) {
  registrar->engine->window_proc_delegate_manager()
      ->UnregisterTopLevelWindowProcDelegate(delegate);
}

UINT FlutterDesktopGetDpiForHWND(HWND hwnd) {
  return flutter::GetDpiForHWND(hwnd);
}

UINT FlutterDesktopGetDpiForMonitor(HMONITOR monitor) {
  return flutter::GetDpiForMonitor(monitor);
}
<|endoftext|>


<commit_before>// Time:  O(m + n)
// Space: O(1)

class Solution {
public:
    /**
     * @param A: An integer matrix
     * @return: The index of the peak
     */
    vector<int> findPeakII(vector<vector<int> > A) {
        int upper = 0, down = A.size() - 1;
        int left = 0, right = A[0].size() - 1;

        while (upper < down && left < right) {
            int height = down - upper + 1;
            int width = right - left + 1;

            // T(m, n) = T(m, n / 2) + O(m) = T(m / 2, n / 2) + O(m) + O(n / 2) = ... = O(2m) + O(2n) = O(max(m, n))
            if (width > height) { // Vertical split.
                int mid_j = left + (right - left) / 2;
                int left_max = 0, central_max = 0, right_max = 0;
                int max_i = -1, max_j = -1;
                for (int i = upper + 1; i < down; ++i) {
                    if (A[i][mid_j] > central_max) {
                        max_i = i, max_j = mid_j;
                        central_max = A[i][mid_j];
                    }
                    left_max = max(left_max, A[i][mid_j - 1]);
                    right_max = max(right_max, A[i][mid_j +  1]);
                }
                if (left_max > central_max && left_max > right_max) { // Find left.
                    right = mid_j;
                } else if (right_max > central_max && right_max > left_max) { // Find right.
                    left = mid_j;
                } else { // Find one peak.
                    return {max_i, max_j};
                }
            } else { // Horizontal split.
                int mid_i = upper + (down - upper) / 2;
                int upper_max = 0, central_max = 0, down_max = 0;
                int max_i = -1, max_j = -1;
                for (int j = left + 1; j < right; ++j) {
                    if (A[mid_i][j] > central_max) {
                        max_i = mid_i, max_j = j;
                        central_max = A[mid_i][j];
                    }
                    upper_max = max(upper_max, A[mid_i - 1][j]);
                    down_max = max(down_max, A[mid_i + 1][j]);
                }
                if (upper_max > central_max && upper_max > down_max) { // Find upper.
                    down = mid_i;
                } else if (down_max > central_max && down_max > upper_max) { // Find down.
                    upper = mid_i;
                } else { // Find one peak.
                    return {max_i, max_j};
                }
            }

        }
        return {-1, -1}; // Not found.
    }
};

// This solution may pass LintCode test cases,
// but it fails to get the peak in the following case:
// A = {{ 1,  2,  3,  4,  5},
//      { 6, 22, 23, 28,  7},
//      { 8, 24, 25, 26,  9},
//      {10, 11, 12, 13, 14}};
class Solution_Wrong {
public:
    /**
     * @param A: An integer matrix
     * @return: The index of the peak
     */
    bool isPeak(const vector<vector<int>> &A, const int i, const int j) {
        if (i < 1 || i >= A.size() - 1 || j < 1 || j >= A[0].size() - 1) {
            return false;
        }

        return A[i][j] > A[i][j - 1] && A[i][j] > A[i - 1][j] &&
               A[i][j] > A[i][j + 1] && A[i][j] > A[i + 1][j];
    }

    vector<int> findPeakII(vector<vector<int> > A) {
        int i = 1, j = 1;
        while (i < A.size() - 1 && j < A[0].size() - 1) {
            if (isPeak(A, i, j)) {
                return {i, j};
            } else {
                if (A[i + 1][j] > A[i][j + 1]) {
                    ++i;
                } else {
                    ++j;
                }
            }
        }
        return {-1, -1};
    }
};

<commit_msg>Update find-peak-element-ii.cpp<commit_after>// Time:  O(m + n)
// Space: O(1)

class Solution {
public:
    /**
     * @param A: An integer matrix
     * @return: The index of the peak
     */
    vector<int> findPeakII(vector<vector<int> > A) {
        int upper = 0, down = A.size() - 1;
        int left = 0, right = A[0].size() - 1;

        while (upper < down && left < right) {
            int height = down - upper + 1;
            int width = right - left + 1;

            // T(m, n) = T(m, n / 2) + O(m) = T(m / 2, n / 2) + O(m) + O(n / 2) = ... = O(2m) + O(2n) = O(max(m, n))
            if (width > height) { // Vertical split.
                int mid_j = left + (right - left) / 2;
                int left_max = 0, central_max = 0, right_max = 0;
                int max_i = -1, max_j = -1;
                for (int i = upper + 1; i < down; ++i) {
                    if (A[i][mid_j] > central_max) {
                        max_i = i, max_j = mid_j;
                        central_max = A[i][mid_j];
                    }
                    left_max = max(left_max, A[i][mid_j - 1]);
                    right_max = max(right_max, A[i][mid_j +  1]);
                }
                if (left_max > central_max && left_max > right_max) { // Find left.
                    right = mid_j;
                } else if (right_max > central_max && right_max > left_max) { // Find right.
                    left = mid_j;
                } else { // Find one peak.
                    return {max_i, max_j};
                }
            } else { // Horizontal split.
                int mid_i = upper + (down - upper) / 2;
                int upper_max = 0, central_max = 0, down_max = 0;
                int max_i = -1, max_j = -1;
                for (int j = left + 1; j < right; ++j) {
                    if (A[mid_i][j] > central_max) {
                        max_i = mid_i, max_j = j;
                        central_max = A[mid_i][j];
                    }
                    upper_max = max(upper_max, A[mid_i - 1][j]);
                    down_max = max(down_max, A[mid_i + 1][j]);
                }
                if (upper_max > central_max && upper_max > down_max) { // Find upper.
                    down = mid_i;
                } else if (down_max > central_max && down_max > upper_max) { // Find down.
                    upper = mid_i;
                } else { // Find one peak.
                    return {max_i, max_j};
                }
            }

        }
        return {-1, -1}; // Not found.
    }
};

// Although this solution passes current LintCode test cases,
// it may fail to find the peak like the following case:
// A = {{ 1,  2,  3,  4,  5},
//      { 6, 22, 23, 28,  7},
//      { 8, 24, 25, 26,  9},
//      {10, 11, 12, 13, 14}};
class Solution_Wrong {
public:
    /**
     * @param A: An integer matrix
     * @return: The index of the peak
     */
    bool isPeak(const vector<vector<int>> &A, const int i, const int j) {
        if (i < 1 || i >= A.size() - 1 || j < 1 || j >= A[0].size() - 1) {
            return false;
        }

        return A[i][j] > A[i][j - 1] && A[i][j] > A[i - 1][j] &&
               A[i][j] > A[i][j + 1] && A[i][j] > A[i + 1][j];
    }

    vector<int> findPeakII(vector<vector<int> > A) {
        int i = 1, j = 1;
        while (i < A.size() - 1 && j < A[0].size() - 1) {
            if (isPeak(A, i, j)) {
                return {i, j};
            } else {
                if (A[i + 1][j] > A[i][j + 1]) {
                    ++i;
                } else {
                    ++j;
                }
            }
        }
        return {-1, -1};
    }
};

<|endoftext|>


<commit_before>/******************************************************************/
/**
**  @file errors.cpp
**  @brief Error-handling routines.
**
**  Created Dec. 97 from earlier routine embedded in child.cpp
**  $Id: errors.cpp,v 1.5 2003-01-17 17:30:25 childcvs Exp $
*/
/******************************************************************/

#include "errors.h"

#include <stdlib.h>
#if !defined(HAVE_NO_NAMESPACE)
# include <iostream>
using namespace std;
#else
# include <iostream.h>
#endif

/*****************************************************************************\
**
**  ReportFatalError:  This is an error-handling routine that prints the
**                     message errMsg then halts the program.
**
**      Parameters:     errMsg -- error message
**      Called by:
**      Created: 12/96 GT
**
\*****************************************************************************/
void ReportFatalError( const char *errMsg )
{
  cout << errMsg <<endl;
  cout << "That was a fatal error, my friend!" <<endl;
  exit(1);
}

<commit_msg>(Arnaud) added CHILD_ABORT_ON_ERROR env. variable<commit_after>/******************************************************************/
/**
**  @file errors.cpp
**  @brief Error-handling routines.
**
**  Created Dec. 97 from earlier routine embedded in child.cpp
**  $Id: errors.cpp,v 1.6 2003-02-10 12:21:02 childcvs Exp $
*/
/******************************************************************/

#include "errors.h"

#include <stdlib.h>
#if !defined(HAVE_NO_NAMESPACE)
# include <iostream>
using namespace std;
#else
# include <iostream.h>
#endif

#define CHILD_ABORT_ON_ERROR "CHILD_ABORT_ON_ERROR"

/*****************************************************************************\
**
**  ReportFatalError:  This is an error-handling routine that prints the
**                     message errMsg then halts the program.
**
**      Parameters:     errMsg -- error message
**      Called by:
**      Created: 12/96 GT
**
\*****************************************************************************/
void ReportFatalError( const char *errMsg )
{
  cout << errMsg <<endl;
  cout << "That was a fatal error, my friend!" <<endl;
  if (getenv(CHILD_ABORT_ON_ERROR) != NULL)
    abort();
  cout << "(Set \"" CHILD_ABORT_ON_ERROR "\" to generate a crash.)" <<endl;
  exit(1);
}

<|endoftext|>


<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * CompressZFP.cpp
 *
 *  Created on: Jul 25, 2017
 *      Author: William F Godoy godoywf@ornl.gov
 */

#include "CompressZFP.h"

#include "adios2/helper/adiosFunctions.h"

namespace adios2
{
namespace core
{
namespace compress
{

CompressZFP::CompressZFP(const Params &parameters, const bool debugMode)
: Operator("zfp", parameters, debugMode)
{
}

size_t CompressZFP::DoBufferMaxSize(const void *dataIn, const Dims &dimensions,
                                    const std::string type,
                                    const Params &parameters) const
{
    zfp_field *field = GetZFPField(dataIn, dimensions, type);
    zfp_stream *stream = GetZFPStream(dimensions, type, parameters);
    const size_t maxSize = zfp_stream_maximum_size(stream, field);
    zfp_field_free(field);
    zfp_stream_close(stream);
    return maxSize;
}

size_t CompressZFP::Compress(const void *dataIn, const Dims &dimensions,
                             const size_t elementSize, const std::string type,
                             void *bufferOut, const Params &parameters,
                             Params &info) const
{

    zfp_field *field = GetZFPField(dataIn, dimensions, type);
    zfp_stream *stream = GetZFPStream(dimensions, type, parameters);
    size_t maxSize = zfp_stream_maximum_size(stream, field);
    // associate bitstream
    bitstream *bitstream = stream_open(bufferOut, maxSize);
    zfp_stream_set_bit_stream(stream, bitstream);
    zfp_stream_rewind(stream);

    size_t sizeOut = zfp_compress(stream, field);

    if (m_DebugMode == true)
    {
        if (sizeOut == 0)
        {
            throw std::invalid_argument("ERROR: zfp failed, compressed buffer "
                                        "size is 0, in call to Compress");
        }
    }

    zfp_field_free(field);
    zfp_stream_close(stream);
    free(bitstream);
    return sizeOut;
}

size_t CompressZFP::Decompress(const void *bufferIn, const size_t sizeIn,
                               void *dataOut, const Dims &dimensions,
                               const std::string type,
                               const Params &parameters) const
{
    auto lf_GetTypeSize = [](const zfp_type zfpType) -> size_t {
        size_t size = 0;
        if (zfpType == zfp_type_int32 || zfpType == zfp_type_float)
        {
            size = 4;
        }
        else if (zfpType == zfp_type_int64 || zfpType == zfp_type_double)
        {
            size = 8;
        }
        return size;
    };

    zfp_field *field = GetZFPField(dataOut, dimensions, type);
    zfp_stream *stream = GetZFPStream(dimensions, type, parameters);

    // associate bitstream
    bitstream *bitstream = stream_open(const_cast<void *>(bufferIn), sizeIn);
    zfp_stream_set_bit_stream(stream, bitstream);
    zfp_stream_rewind(stream);

    int status = zfp_decompress(stream, field);

    if (m_DebugMode)
    {
        if (!status)
        {
            throw std::invalid_argument(
                "ERROR: zfp failed with status " + std::to_string(status) +
                ", in call to CompressZfp Decompress\n");
        }
    }

    zfp_field_free(field);
    zfp_stream_close(stream);
    stream_close(bitstream);

    const size_t typeSizeBytes = lf_GetTypeSize(GetZfpType(type));
    const size_t dataSizeBytes =
        helper::GetTotalSize(dimensions) * typeSizeBytes;

    return dataSizeBytes;
}

// PRIVATE
zfp_type CompressZFP::GetZfpType(const std::string type) const
{
    zfp_type zfpType = zfp_type_none;

    if (type == helper::GetType<double>())
    {
        zfpType = zfp_type_double;
    }
    else if (type == helper::GetType<float>())
    {
        zfpType = zfp_type_float;
    }
    else if (type == helper::GetType<int64_t>())
    {
        zfpType = zfp_type_int64;
    }
    else if (type == helper::GetType<int32_t>())
    {
        zfpType = zfp_type_int32;
    }
    else
    {
        if (m_DebugMode)
        {

            throw std::invalid_argument(
                "ERROR: type " + type +
                " not supported by zfp, only "
                "signed int32_t, signed int64_t, float, and "
                "double types are acceptable, from class "
                "CompressZfp Transform\n");
        }
    }

    return zfpType;
}

zfp_field *CompressZFP::GetZFPField(const void *data, const Dims &dimensions,
                                    const std::string type) const
{
    auto lf_CheckField = [](const zfp_field *field,
                            const std::string zfpFieldFunction,
                            const std::string type) {
        if (field == nullptr || field == NULL)
        {
            throw std::invalid_argument(
                "ERROR: " + zfpFieldFunction + " failed for data of type " +
                type +
                ", data pointer might be corrupted, from "
                "class CompressZfp Transform\n");
        }
    };

    zfp_type zfpType = GetZfpType(type);
    zfp_field *field = nullptr;

    if (dimensions.size() == 1)
    {
        field = zfp_field_1d(const_cast<void *>(data), zfpType, dimensions[0]);
        if (m_DebugMode)
        {
            lf_CheckField(field, "zfp_field_1d", type);
        }
    }
    else if (dimensions.size() == 2)
    {
        field = zfp_field_2d(const_cast<void *>(data), zfpType, dimensions[0],
                             dimensions[1]);
        if (m_DebugMode)
        {
            lf_CheckField(field, "zfp_field_2d", type);
        }
    }
    else if (dimensions.size() == 3)
    {
        field = zfp_field_3d(const_cast<void *>(data), zfpType, dimensions[0],
                             dimensions[1], dimensions[2]);
        if (m_DebugMode)
        {
            lf_CheckField(field, "zfp_field_3d", type);
        }
    }
    else
    {
        if (m_DebugMode)
        {
            throw std::invalid_argument(
                "ERROR: zfp_field* failed for data of type " + type +
                ", only 1D, 2D and 3D dimensions are supported, from "
                "class CompressZfp Transform\n");
        }
    }

    return field;
}

zfp_stream *CompressZFP::GetZFPStream(const Dims &dimensions,
                                      const std::string type,
                                      const Params &parameters) const
{
    auto lf_HasKey = [](Params::const_iterator itKey,
                        const Params &parameters) -> bool {
        bool hasKey = false;
        if (itKey != parameters.end())
        {
            hasKey = true;
        }
        return hasKey;
    };

    zfp_stream *stream = zfp_stream_open(NULL);

    auto itAccuracy = parameters.find("accuracy");
    const bool hasAccuracy = lf_HasKey(itAccuracy, parameters);

    auto itRate = parameters.find("rate");
    const bool hasRate = lf_HasKey(itRate, parameters);

    auto itPrecision = parameters.find("precision");
    const bool hasPrecision = lf_HasKey(itPrecision, parameters);

    if (m_DebugMode)
    {
        if ((hasAccuracy && hasRate) || (hasAccuracy && hasPrecision) ||
            (hasRate && hasPrecision) ||
            !(hasAccuracy || hasRate || hasPrecision))
        {
            throw std::invalid_argument("ERROR: zfp parameters accuracy, "
                                        "rate, and precision are mutually "
                                        "exclusive, only one of them is "
                                        "mandatory, from "
                                        "operator CompressZfp\n");
        }
    }

    if (hasAccuracy)
    {
        const double accuracy = helper::StringTo<double>(
            itAccuracy->second, m_DebugMode,
            "setting accuracy in call to CompressZfp\n");

        zfp_stream_set_accuracy(stream, accuracy);
    }
    else if (hasRate)
    {
        const double rate =
            helper::StringTo<double>(itRate->second, m_DebugMode,
                                     "setting Rate in call to CompressZfp\n");
        // TODO support last argument write random access?
        zfp_stream_set_rate(stream, rate, GetZfpType(type),
                            static_cast<unsigned int>(dimensions.size()), 0);
    }
    else if (hasPrecision)
    {
        const unsigned int precision =
            static_cast<unsigned int>(helper::StringTo<uint32_t>(
                itPrecision->second, m_DebugMode,
                "setting Precision in call to CompressZfp\n"));
        zfp_stream_set_precision(stream, precision);
    }

    return stream;
}

} // end namespace compress
} // end namespace core
} // end namespace adios2
<commit_msg>Free the bitstream pointer with the correct ZFP call.<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * CompressZFP.cpp
 *
 *  Created on: Jul 25, 2017
 *      Author: William F Godoy godoywf@ornl.gov
 */

#include "CompressZFP.h"

#include "adios2/helper/adiosFunctions.h"

namespace adios2
{
namespace core
{
namespace compress
{

CompressZFP::CompressZFP(const Params &parameters, const bool debugMode)
: Operator("zfp", parameters, debugMode)
{
}

size_t CompressZFP::DoBufferMaxSize(const void *dataIn, const Dims &dimensions,
                                    const std::string type,
                                    const Params &parameters) const
{
    zfp_field *field = GetZFPField(dataIn, dimensions, type);
    zfp_stream *stream = GetZFPStream(dimensions, type, parameters);
    const size_t maxSize = zfp_stream_maximum_size(stream, field);
    zfp_field_free(field);
    zfp_stream_close(stream);
    return maxSize;
}

size_t CompressZFP::Compress(const void *dataIn, const Dims &dimensions,
                             const size_t elementSize, const std::string type,
                             void *bufferOut, const Params &parameters,
                             Params &info) const
{

    zfp_field *field = GetZFPField(dataIn, dimensions, type);
    zfp_stream *stream = GetZFPStream(dimensions, type, parameters);
    size_t maxSize = zfp_stream_maximum_size(stream, field);
    // associate bitstream
    bitstream *bitstream = stream_open(bufferOut, maxSize);
    zfp_stream_set_bit_stream(stream, bitstream);
    zfp_stream_rewind(stream);

    size_t sizeOut = zfp_compress(stream, field);

    if (m_DebugMode == true)
    {
        if (sizeOut == 0)
        {
            throw std::invalid_argument("ERROR: zfp failed, compressed buffer "
                                        "size is 0, in call to Compress");
        }
    }

    zfp_field_free(field);
    zfp_stream_close(stream);
    stream_close(bitstream);
    return sizeOut;
}

size_t CompressZFP::Decompress(const void *bufferIn, const size_t sizeIn,
                               void *dataOut, const Dims &dimensions,
                               const std::string type,
                               const Params &parameters) const
{
    auto lf_GetTypeSize = [](const zfp_type zfpType) -> size_t {
        size_t size = 0;
        if (zfpType == zfp_type_int32 || zfpType == zfp_type_float)
        {
            size = 4;
        }
        else if (zfpType == zfp_type_int64 || zfpType == zfp_type_double)
        {
            size = 8;
        }
        return size;
    };

    zfp_field *field = GetZFPField(dataOut, dimensions, type);
    zfp_stream *stream = GetZFPStream(dimensions, type, parameters);

    // associate bitstream
    bitstream *bitstream = stream_open(const_cast<void *>(bufferIn), sizeIn);
    zfp_stream_set_bit_stream(stream, bitstream);
    zfp_stream_rewind(stream);

    int status = zfp_decompress(stream, field);

    if (m_DebugMode)
    {
        if (!status)
        {
            throw std::invalid_argument(
                "ERROR: zfp failed with status " + std::to_string(status) +
                ", in call to CompressZfp Decompress\n");
        }
    }

    zfp_field_free(field);
    zfp_stream_close(stream);
    stream_close(bitstream);

    const size_t typeSizeBytes = lf_GetTypeSize(GetZfpType(type));
    const size_t dataSizeBytes =
        helper::GetTotalSize(dimensions) * typeSizeBytes;

    return dataSizeBytes;
}

// PRIVATE
zfp_type CompressZFP::GetZfpType(const std::string type) const
{
    zfp_type zfpType = zfp_type_none;

    if (type == helper::GetType<double>())
    {
        zfpType = zfp_type_double;
    }
    else if (type == helper::GetType<float>())
    {
        zfpType = zfp_type_float;
    }
    else if (type == helper::GetType<int64_t>())
    {
        zfpType = zfp_type_int64;
    }
    else if (type == helper::GetType<int32_t>())
    {
        zfpType = zfp_type_int32;
    }
    else
    {
        if (m_DebugMode)
        {

            throw std::invalid_argument(
                "ERROR: type " + type +
                " not supported by zfp, only "
                "signed int32_t, signed int64_t, float, and "
                "double types are acceptable, from class "
                "CompressZfp Transform\n");
        }
    }

    return zfpType;
}

zfp_field *CompressZFP::GetZFPField(const void *data, const Dims &dimensions,
                                    const std::string type) const
{
    auto lf_CheckField = [](const zfp_field *field,
                            const std::string zfpFieldFunction,
                            const std::string type) {
        if (field == nullptr || field == NULL)
        {
            throw std::invalid_argument(
                "ERROR: " + zfpFieldFunction + " failed for data of type " +
                type +
                ", data pointer might be corrupted, from "
                "class CompressZfp Transform\n");
        }
    };

    zfp_type zfpType = GetZfpType(type);
    zfp_field *field = nullptr;

    if (dimensions.size() == 1)
    {
        field = zfp_field_1d(const_cast<void *>(data), zfpType, dimensions[0]);
        if (m_DebugMode)
        {
            lf_CheckField(field, "zfp_field_1d", type);
        }
    }
    else if (dimensions.size() == 2)
    {
        field = zfp_field_2d(const_cast<void *>(data), zfpType, dimensions[0],
                             dimensions[1]);
        if (m_DebugMode)
        {
            lf_CheckField(field, "zfp_field_2d", type);
        }
    }
    else if (dimensions.size() == 3)
    {
        field = zfp_field_3d(const_cast<void *>(data), zfpType, dimensions[0],
                             dimensions[1], dimensions[2]);
        if (m_DebugMode)
        {
            lf_CheckField(field, "zfp_field_3d", type);
        }
    }
    else
    {
        if (m_DebugMode)
        {
            throw std::invalid_argument(
                "ERROR: zfp_field* failed for data of type " + type +
                ", only 1D, 2D and 3D dimensions are supported, from "
                "class CompressZfp Transform\n");
        }
    }

    return field;
}

zfp_stream *CompressZFP::GetZFPStream(const Dims &dimensions,
                                      const std::string type,
                                      const Params &parameters) const
{
    auto lf_HasKey = [](Params::const_iterator itKey,
                        const Params &parameters) -> bool {
        bool hasKey = false;
        if (itKey != parameters.end())
        {
            hasKey = true;
        }
        return hasKey;
    };

    zfp_stream *stream = zfp_stream_open(NULL);

    auto itAccuracy = parameters.find("accuracy");
    const bool hasAccuracy = lf_HasKey(itAccuracy, parameters);

    auto itRate = parameters.find("rate");
    const bool hasRate = lf_HasKey(itRate, parameters);

    auto itPrecision = parameters.find("precision");
    const bool hasPrecision = lf_HasKey(itPrecision, parameters);

    if (m_DebugMode)
    {
        if ((hasAccuracy && hasRate) || (hasAccuracy && hasPrecision) ||
            (hasRate && hasPrecision) ||
            !(hasAccuracy || hasRate || hasPrecision))
        {
            throw std::invalid_argument("ERROR: zfp parameters accuracy, "
                                        "rate, and precision are mutually "
                                        "exclusive, only one of them is "
                                        "mandatory, from "
                                        "operator CompressZfp\n");
        }
    }

    if (hasAccuracy)
    {
        const double accuracy = helper::StringTo<double>(
            itAccuracy->second, m_DebugMode,
            "setting accuracy in call to CompressZfp\n");

        zfp_stream_set_accuracy(stream, accuracy);
    }
    else if (hasRate)
    {
        const double rate =
            helper::StringTo<double>(itRate->second, m_DebugMode,
                                     "setting Rate in call to CompressZfp\n");
        // TODO support last argument write random access?
        zfp_stream_set_rate(stream, rate, GetZfpType(type),
                            static_cast<unsigned int>(dimensions.size()), 0);
    }
    else if (hasPrecision)
    {
        const unsigned int precision =
            static_cast<unsigned int>(helper::StringTo<uint32_t>(
                itPrecision->second, m_DebugMode,
                "setting Precision in call to CompressZfp\n"));
        zfp_stream_set_precision(stream, precision);
    }

    return stream;
}

} // end namespace compress
} // end namespace core
} // end namespace adios2
<|endoftext|>