<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/accessors/p9_get_mvpd_ring.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
// $Id: p9_get_mvpd_ring.H,v 1.1 2012/07/19 22:00:38 mjjones Exp $
/**
 *  @file p9_get_mvpd_ring.H
 *
 *  @brief Prototype for getMvpdRing() -
 *          get a repair ring from a MVPD record
 */

#ifndef    _HWP_GETMVPDRING_
#define    _HWP_GETMVPDRING_

#include   <fapi2.H>

namespace fapi2
{

// function pointer typedef definition for HWP call support
typedef ReturnCode (*getMvpdRing_FP_t) (
    MvpdRecord,
    MvpdKeyword,
    const Target<TARGET_TYPE_PROC_CHIP>&,
    const uint8_t,
    const uint64_t,
    const uint8_t,
    uint8_t*,
    uint32_t& );

extern "C"
{
    /**
     * @brief   get specified ring from MVPD for the specified target CPU.
     *
     * A Ring Id Chiplet Id should be unique in the mvpd Record.
     * The code does not validate. No assumption should be made on which would
     * be returned if there are multiple.
     *
     * @param i_record          -   Record enumerator
     * @param i_keyword         -   Keyword enumerator
     * Supported Rings are:
     *                   MVPD_RECORD_CP00 - MVPD_KEYWORD_PDR
     *                   MVPD_RECORD_CP00 - MVPD_KEYWORD_PDG
     * @param i_fapiTarget      -   cpu target
     * @param i_chipletId       -   Chiplet ID
     * @param i_evenOdd         -   Even (0) or odd (1) EX. Disregarded for other chiplets.
     * @param i_ringId          -   Ring ID
     * @param i_pRingBuf        -   pointer to a buffer allocated by the caller
     *                              to receive the ring header and data.
     *                              if NULL, the size of the min buffer required
     *                              buffer will be returned in io_rRingBufsize
     *                              with rc FAPI_RC_SUCCESS.
     * @param io_rRingBufsize   -   in:     size of ring buffer that caller has
     *                                      allocated
     *                              out:    number of BYTES that were copied to the
     *                                      output buffer.
     *                                      If the ring was not found, an error
     *                                      will be returned and this will be 0.
     *                                      If the output buffer is not big enough,
     *                                      an error will be returned and this will
     *                                      be the minimum size required.
     *                              The buffer contains the CompressedScanData
     *                              structure followed by compressed data. The
     *                              caller does compression and decompression.
     *  Buffer:   io_rRingBufsize returns xNN.
     *    byte x0  CompressedScanData structure (rs4 header)
     *    byte x0C compressed data (sizeof CompressedScanData is 0x0C)
     *    byte xNN last byte of compressed data
     *
     * @return fapi2::ReturnCode -   FAPI_RC_SUCCESS if success,
     *                               relevant error code for failure.
     */
    ReturnCode getMvpdRing( MvpdRecord     i_record,
                            MvpdKeyword    i_keyword,
                            const Target<TARGET_TYPE_PROC_CHIP>&
                            i_fapiTarget,
                            const uint8_t  i_chipletId,
                            const uint8_t  i_evenOdd,
                            const uint8_t  i_ringId,
                            uint8_t*       io_pRingBuf,
                            uint32_t&      io_rRingBufsize );

}
}
#endif
<commit_msg>Reverting RS4v3 changes<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/accessors/p9_get_mvpd_ring.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
// $Id: p9_get_mvpd_ring.H,v 1.1 2012/07/19 22:00:38 mjjones Exp $
/**
 *  @file p9_get_mvpd_ring.H
 *
 *  @brief Prototype for getMvpdRing() -
 *          get a repair ring from a MVPD record
 */

#ifndef    _HWP_GETMVPDRING_
#define    _HWP_GETMVPDRING_

#include   <fapi2.H>

namespace fapi2
{

// function pointer typedef definition for HWP call support
typedef ReturnCode (*getMvpdRing_FP_t) (
    MvpdRecord,
    MvpdKeyword,
    const Target<TARGET_TYPE_PROC_CHIP>&,
    const uint8_t,
    const uint64_t,
    const uint8_t,
    uint8_t*,
    uint32_t& );

extern "C"
{
    /**
     * @brief   get specified ring from MVPD for the specified target CPU.
     *
     * A Ring Id Chiplet Id should be unique in the mvpd Record.
     * The code does not validate. No assumption should be made on which would
     * be returned if there are multiple.
     *
     * @param i_record          -   Record enumerator
     * @param i_keyword         -   Keyword enumerator
     * Supported Rings are:
     *                   MVPD_RECORD_CP00 - MVPD_KEYWORD_PDR
     *                   MVPD_RECORD_CP00 - MVPD_KEYWORD_PDG
     * @param i_fapiTarget      -   cpu target
     * @param i_chipletId       -   Chiplet ID
     * @param i_evenOddMask     -   Mask to choose even or odd EX. O for all other chiplets
     * @param i_ringId          -   Ring ID
     * @param i_pRingBuf        -   pointer to a buffer allocated by the caller
     *                              to receive the ring header and data.
     *                              if NULL, the size of the min buffer required
     *                              buffer will be returned in io_rRingBufsize
     *                              with rc FAPI_RC_SUCCESS.
     * @param io_rRingBufsize   -   in:     size of ring buffer that caller has
     *                                      allocated
     *                              out:    number of BYTES that were copied to the
     *                                      output buffer.
     *                                      If the ring was not found, an error
     *                                      will be returned and this will be 0.
     *                                      If the output buffer is not big enough,
     *                                      an error will be returned and this will
     *                                      be the minimum size required.
     *                              The buffer contains the CompressedScanData
     *                              structure followed by compressed data. The
     *                              caller does compression and decompression.
     *  Buffer:   io_rRingBufsize returns xNN.
     *    byte x0  CompressedScanData structure (rs4 header)
     *    byte x18 compressed data (sizeof CompressedScanData is 0x18)
     *    byte xNN last byte of compressed data
     *
     * @return fapi2::ReturnCode -   FAPI_RC_SUCCESS if success,
     *                               relevant error code for failure.
     */
    ReturnCode getMvpdRing( MvpdRecord     i_record,
                            MvpdKeyword    i_keyword,
                            const Target<TARGET_TYPE_PROC_CHIP>&
                            i_fapiTarget,
                            const uint8_t  i_chipletId,
                            const uint64_t i_evenOddMask,
                            const uint8_t  i_ringId,
                            uint8_t*       io_pRingBuf,
                            uint32_t&      io_rRingBufsize );

}
}
#endif
<|endoftext|>


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

#include <inviwo/qt/widgets/properties/stringmultilinepropertywidgetqt.h>
#include <inviwo/qt/widgets/properties/compositepropertywidgetqt.h>
#include <warn/push>
#include <warn/ignore/all>
#include <QFontMetrics>
#include <warn/pop>

namespace inviwo {

StringMultilinePropertyWidgetQt::StringMultilinePropertyWidgetQt(StringProperty *property)
    : PropertyWidgetQt(property), property_(property) {
    generateWidget();
    updateFromProperty();
}

void StringMultilinePropertyWidgetQt::generateWidget() {
    QHBoxLayout *hLayout = new QHBoxLayout;
    setSpacingAndMargins(hLayout);

    // QVBoxLayout* vLayout = new QVBoxLayout;
    // vLayout->setContentsMargins(0, 0, 0, 0);
    // vLayout->setSpacing(0);

    label_ = new EditableLabelQt(this, property_);
    // vLayout->addWidget(label_);
    // vLayout->addStretch();
    // hLayout->addLayout(vLayout);

    hLayout->addWidget(label_);

    textEdit_ = new MultilineTextEdit;
    // if(property_->getSemantics().getString() == "Password"){
    //    textEdit_->setEchoMode(QLineEdit::PasswordEchoOnEdit);
    //}

    QSizePolicy sp = textEdit_->sizePolicy();
    sp.setHorizontalStretch(3);
    sp.setVerticalPolicy(QSizePolicy::Preferred);
    textEdit_->setSizePolicy(sp);

    hLayout->addWidget(textEdit_);

    setLayout(hLayout);
    connect(textEdit_, SIGNAL(editingFinished()), this, SLOT(setPropertyValue()));
}

void StringMultilinePropertyWidgetQt::setPropertyValue() {
    std::string valueStr = textEdit_->toPlainText().toLocal8Bit().constData();
    property_->setInitiatingWidget(this);
    property_->set(valueStr);
    property_->clearInitiatingWidget();
}

void StringMultilinePropertyWidgetQt::updateFromProperty() {
    QString text(textEdit_->toPlainText());
    QString newContents(QString::fromStdString(property_->get()));
    if (text != newContents) {
        textEdit_->setPlainText(newContents);
        textEdit_->moveCursor(QTextCursor::Start);

        textEdit_->adjustHeight();
    }
}

MultilineTextEdit::MultilineTextEdit(QWidget *parent)
    : QPlainTextEdit(parent), minLineCount_(2), maxLineCount_(10), showContextMenu_(false) {
    QFontMetrics fontMetric(font());
    lineHeight_ = fontMetric.lineSpacing() * 1.5;

    // enable focus switch by tab (leaving the editor and committing the changes)
    setTabChangesFocus(true);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
    // need to enable the scrollbar for adjusting to its contents
    setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
#endif
    // make the text edit show at least n lines of text
    setMinimumHeight(minLineCount_ * lineHeight_);
    setMaximumHeight(maxLineCount_ * lineHeight_);
}
MultilineTextEdit::~MultilineTextEdit() {}

void MultilineTextEdit::focusOutEvent(QFocusEvent *e) {
    if (showContextMenu_) {
        return;
    }

    emit editingFinished();
    adjustHeight();
    // clear text selection
    QTextCursor cursor(textCursor());
    cursor.clearSelection();
    setTextCursor(cursor);

    QPlainTextEdit::focusOutEvent(e);
}

void MultilineTextEdit::resizeEvent(QResizeEvent *e) {
    QPlainTextEdit::resizeEvent(e);
    adjustHeight();
}

void MultilineTextEdit::keyPressEvent(QKeyEvent *e) {
    // commit text changes when pressing CTRL + Return or Enter
    if (((e->key() == Qt::Key_Return) || (e->key() == Qt::Key_Enter)) &&
        (e->modifiers() & Qt::ControlModifier)) {
        emit editingFinished();
        adjustHeight();
        e->accept();
    } else {
        QPlainTextEdit::keyPressEvent(e);
    }
}

void MultilineTextEdit::contextMenuEvent(QContextMenuEvent *e) {
    showContextMenu_ = true;
    QPlainTextEdit::contextMenuEvent(e);
    showContextMenu_ = false;
}

void MultilineTextEdit::adjustHeight() {
    qreal textHeight =
        glm::clamp(static_cast<int>(document()->size().height()), minLineCount_, maxLineCount_) *
        lineHeight_;
    QMargins margins(contentsMargins());
    setFixedHeight(static_cast<int>(textHeight + margins.top() + margins.bottom()));
}

}  // namespace
<commit_msg>QT: Removed warning<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2016 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/qt/widgets/properties/stringmultilinepropertywidgetqt.h>
#include <inviwo/qt/widgets/properties/compositepropertywidgetqt.h>
#include <warn/push>
#include <warn/ignore/all>
#include <QFontMetrics>
#include <warn/pop>

namespace inviwo {

StringMultilinePropertyWidgetQt::StringMultilinePropertyWidgetQt(StringProperty *property)
    : PropertyWidgetQt(property), property_(property) {
    generateWidget();
    updateFromProperty();
}

void StringMultilinePropertyWidgetQt::generateWidget() {
    QHBoxLayout *hLayout = new QHBoxLayout;
    setSpacingAndMargins(hLayout);

    // QVBoxLayout* vLayout = new QVBoxLayout;
    // vLayout->setContentsMargins(0, 0, 0, 0);
    // vLayout->setSpacing(0);

    label_ = new EditableLabelQt(this, property_);
    // vLayout->addWidget(label_);
    // vLayout->addStretch();
    // hLayout->addLayout(vLayout);

    hLayout->addWidget(label_);

    textEdit_ = new MultilineTextEdit;
    // if(property_->getSemantics().getString() == "Password"){
    //    textEdit_->setEchoMode(QLineEdit::PasswordEchoOnEdit);
    //}

    QSizePolicy sp = textEdit_->sizePolicy();
    sp.setHorizontalStretch(3);
    sp.setVerticalPolicy(QSizePolicy::Preferred);
    textEdit_->setSizePolicy(sp);

    hLayout->addWidget(textEdit_);

    setLayout(hLayout);
    connect(textEdit_, SIGNAL(editingFinished()), this, SLOT(setPropertyValue()));
}

void StringMultilinePropertyWidgetQt::setPropertyValue() {
    std::string valueStr = textEdit_->toPlainText().toLocal8Bit().constData();
    property_->setInitiatingWidget(this);
    property_->set(valueStr);
    property_->clearInitiatingWidget();
}

void StringMultilinePropertyWidgetQt::updateFromProperty() {
    QString text(textEdit_->toPlainText());
    QString newContents(QString::fromStdString(property_->get()));
    if (text != newContents) {
        textEdit_->setPlainText(newContents);
        textEdit_->moveCursor(QTextCursor::Start);

        textEdit_->adjustHeight();
    }
}

MultilineTextEdit::MultilineTextEdit(QWidget *parent)
    : QPlainTextEdit(parent), minLineCount_(2), maxLineCount_(10), showContextMenu_(false) {
    QFontMetrics fontMetric(font());
    lineHeight_ = static_cast<int>( fontMetric.lineSpacing() * 1.5);

    // enable focus switch by tab (leaving the editor and committing the changes)
    setTabChangesFocus(true);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
    // need to enable the scrollbar for adjusting to its contents
    setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
#endif
    // make the text edit show at least n lines of text
    setMinimumHeight(minLineCount_ * lineHeight_);
    setMaximumHeight(maxLineCount_ * lineHeight_);
}
MultilineTextEdit::~MultilineTextEdit() {}

void MultilineTextEdit::focusOutEvent(QFocusEvent *e) {
    if (showContextMenu_) {
        return;
    }

    emit editingFinished();
    adjustHeight();
    // clear text selection
    QTextCursor cursor(textCursor());
    cursor.clearSelection();
    setTextCursor(cursor);

    QPlainTextEdit::focusOutEvent(e);
}

void MultilineTextEdit::resizeEvent(QResizeEvent *e) {
    QPlainTextEdit::resizeEvent(e);
    adjustHeight();
}

void MultilineTextEdit::keyPressEvent(QKeyEvent *e) {
    // commit text changes when pressing CTRL + Return or Enter
    if (((e->key() == Qt::Key_Return) || (e->key() == Qt::Key_Enter)) &&
        (e->modifiers() & Qt::ControlModifier)) {
        emit editingFinished();
        adjustHeight();
        e->accept();
    } else {
        QPlainTextEdit::keyPressEvent(e);
    }
}

void MultilineTextEdit::contextMenuEvent(QContextMenuEvent *e) {
    showContextMenu_ = true;
    QPlainTextEdit::contextMenuEvent(e);
    showContextMenu_ = false;
}

void MultilineTextEdit::adjustHeight() {
    qreal textHeight =
        glm::clamp(static_cast<int>(document()->size().height()), minLineCount_, maxLineCount_) *
        lineHeight_;
    QMargins margins(contentsMargins());
    setFixedHeight(static_cast<int>(textHeight + margins.top() + margins.bottom()));
}

}  // namespace
<|endoftext|>


<commit_before>/*
 * File:   TableOpenHelper.cpp
 * Author: uli
 *
 * Created on 6. April 2013, 18:15
 */

#include "TableOpenHelper.hpp"
#include <thread>

/**
 * Main function for table open worker thread
 * @param pointerToDatabases A pointer to an array of leveldb::DB* instances that is managed by this method.
 * The array is automatically initialized and resized on demand
 */
static void tableOpenWorkerThread(zctx_t* context, TableOpenHelper::LevelDBArray* pointerToDatabases) {
    void* repSocket = zsocket_new(context, ZMQ_REQ);
    zsocket_connect(repSocket, "inproc://tableOpenWorker");
    while(true) {
        zmsg_t* msg = zmsg_recv(repSocket);
        //Msg only contains one frame
        zframe_t* frame = zmsg_first(msg);
    }
}

TableOpenHelper::TableOpenHelper(zctx_t* context, LevelDBArray* databases) {
    //Initialize the table open helper

    //Initialize the REQ socket
    reqSocket = zsocket_new(context, ZMQ_REQ);
    zsocket_bind(reqSocket, "inproc://tableOpenWorker");
}<commit_msg>Fix stuff<commit_after>/*
 * File:   TableOpenHelper.cpp
 * Author: uli
 *
 * Created on 6. April 2013, 18:15
 */

#include "TableOpenHelper.hpp"
#include <thread>
#include <cassert>

/**
 * Main function for table open worker thread
 * @param pointerToDatabases A pointer to an array of leveldb::DB* instances that is managed by this method.
 * The array is automatically initialized and resized on demand
 */
static void tableOpenWorkerThread(zctx_t* context, TableOpenHelper::LevelDBArray* pointerToDatabases) {
    void* repSocket = zsocket_new(context, ZMQ_REQ);
    zsocket_connect(repSocket, "inproc://tableOpenWorker");
    while(true) {
        zmsg_t* msg = zmsg_recv(repSocket);
        //Msg only contains one frame
        zframe_t* frame = zmsg_pop(msg);
        assert(zframe_size(frame) == 4);
        uint32_t index = *((uint32_t*)zframe_data(frame));
        //Only open the
    }
}

TableOpenHelper::TableOpenHelper(zctx_t* context, LevelDBArray* databases) {
    //Initialize the table open helper

    //Initialize the REQ socket
    reqSocket = zsocket_new(context, ZMQ_REQ);
    zsocket_bind(reqSocket, "inproc://tableOpenWorker");
}<|endoftext|>


<commit_before>#include <tiramisu/expr.h>
#include <tiramisu/core.h>

namespace tiramisu
{

tiramisu::expr& tiramisu::expr::operator=(tiramisu::expr const & e)
{
    this->_operator = e._operator;
    this->op = e.op;
    this->access_vector = e.access_vector;
    this->argument_vector = e.argument_vector;
    this->defined = e.defined;
    this->name = e.name;
    this->dtype = e.dtype;
    this->etype = e.etype;

    // Copy the integer value
    if (e.get_expr_type() == tiramisu::e_val)
    {
        if (e.get_data_type() == tiramisu::p_uint8)
        {
            this->uint8_value = e.get_uint8_value();
        }
        else if (e.get_data_type() == tiramisu::p_int8)
        {
            this->int8_value = e.get_int8_value();
        }
        else if (e.get_data_type() == tiramisu::p_uint16)
        {
            this->uint16_value = e.get_uint16_value();
        }
        else if (e.get_data_type() == tiramisu::p_int16)
        {
            this->int16_value = e.get_int16_value();
        }
        else if (e.get_data_type() == tiramisu::p_uint32)
        {
            this->uint32_value = e.get_uint32_value();
        }
        else if (e.get_data_type() == tiramisu::p_int32)
        {
            this->int32_value = e.get_int32_value();
        }
        else if (e.get_data_type() == tiramisu::p_uint64)
        {
            this->uint64_value = e.get_uint64_value();
        }
        else if (e.get_data_type() == tiramisu::p_int64)
        {
            this->int64_value = e.get_int64_value();
        }
        else if (e.get_data_type() == tiramisu::p_float32)
        {
            this->float32_value = e.get_float32_value();
        }
        else if (e.get_data_type() == tiramisu::p_float64)
        {
            this->float64_value = e.get_float64_value();
        }
    }
    return *this;
}

tiramisu::expr tiramisu::expr::substitute(std::vector<std::pair<var, expr>> substitutions) const
{
    for (auto &substitution: substitutions)
        if (this->is_equal(substitution.first))
            return substitution.second;

    return apply_to_operands([&substitutions](const expr& e){
        return e.substitute(substitutions);
    });
}

tiramisu::expr tiramisu::expr::substitute_access(std::string original, std::string substitute) const {
    expr && result = this->apply_to_operands([&original, &substitute](const expr& e){
        return e.substitute_access(original, substitute);
    });
    if (result.get_op_type() == o_access && result.name == original)
    {
        result.name = substitute;
    }
    return result;
}

tiramisu::var::var(std::string name, bool save)
{
    assert(!name.empty());

    auto declared = var::declared_vars.find(name);

    if (declared != var::declared_vars.end())
    {
        *this = declared->second;
    }
    else
    {
        this->name = name;
        this->etype = tiramisu::e_var;
        this->dtype = global::get_loop_iterator_data_type();
        this->defined = true;
        if (save)
        {
            var::declared_vars.insert(std::make_pair(name, *this));
            DEBUG(3, std::cout << "Saved variable " << this->name << " of type " << str_from_tiramisu_type_primitive(this->dtype));
        }
    }
}

tiramisu::var::var(tiramisu::primitive_t type, std::string name, bool save)
{
    assert(!name.empty());

    auto declared = var::declared_vars.find(name);

    if (declared != var::declared_vars.end())
    {
        assert(declared->second.dtype == type);
        *this = declared->second;
    }
    else
    {
        this->name = name;
        this->etype = tiramisu::e_var;
        this->dtype = type;
        this->defined = true;
        if (save)
        {
            var::declared_vars.insert(std::make_pair(name, *this));
            DEBUG(10, std::cout << "Saved variable " << this->name << " of type " << str_from_tiramisu_type_primitive(this->dtype));
        }
    }
}

tiramisu::expr tiramisu::expr::copy() const
{
    return (*this);
}

std::unordered_map<std::string, var> tiramisu::var::declared_vars;

expr cast(primitive_t tT, const expr & e) {
    if (e.get_data_type() == tT)
        return e;
    return expr{o_cast, tT, e};
}

expr tiramisu::expr::operator+(tiramisu::expr other) const {
    return tiramisu::expr{o_add, *this, other};
}

expr tiramisu::expr::operator-(tiramisu::expr other) const {
    return tiramisu::expr{o_sub, *this, other};
}

expr tiramisu::expr::operator*(tiramisu::expr other) const {
    return tiramisu::expr{o_mul, *this, other};
}

expr tiramisu::expr::operator/(tiramisu::expr other) const {
    return tiramisu::expr{o_div, *this, other};
}

expr tiramisu::expr::operator%(tiramisu::expr other) const {
    return tiramisu::expr{o_mod, *this, other};
}

expr tiramisu::expr::operator>>(tiramisu::expr other) const {
    return tiramisu::expr{o_right_shift, *this, other};
}

expr tiramisu::expr::operator<<(tiramisu::expr other) const {
    return tiramisu::expr{o_left_shift, *this, other};
}

expr memcpy(const buffer &from, const buffer &to) {
    return expr(o_memcpy, var(p_void_ptr, from.get_name()), var(p_void_ptr, to.get_name()));
}

expr allocate(const buffer &b)
{
    return expr{o_allocate, b.get_name()};
}

expr cublas_gemm(const buffer &A, const buffer &B, buffer &C,
                 expr M, expr N, expr K,
                 expr alpha, expr beta,
                 expr ldA, expr ldB, expr ldC,
                 expr offsetA, expr offsetB, expr offsetC,
                 expr transposeA, expr transposeB)
{
    if (A.get_location() != cuda_ast::memory_location::global ||
        B.get_location() != cuda_ast::memory_location::global ||
        C.get_location() != cuda_ast::memory_location::global) {
        ERROR("Buffers must be on GPU global memory", true);
    }
    std::string fname;
    expr alpha_expr;
    expr beta_expr;
    if (A.get_elements_type() == p_float32 &&
        B.get_elements_type() == p_float32 &&
        C.get_elements_type() == p_float32) {
        fname = "tiramisu_cublas_sgemm";
        alpha_expr = cast(p_float32, alpha);
        beta_expr = cast(p_float32, beta);
    } else if (A.get_elements_type() == p_float64 &&
               B.get_elements_type() == p_float64 &&
               C.get_elements_type() == p_float64) {
        fname = "tiramisu_cublas_dgemm";
        alpha_expr = cast(p_float64, alpha);
        beta_expr = cast(p_float64, beta);
    } else {
        ERROR("All input buffers should be of same type and either p_float32 or p_float64", true);
    }
    return expr(o_call, fname,
            {
                var(p_void_ptr, A.get_name()),
                var(p_void_ptr, B.get_name()),
                var(p_void_ptr, C.get_name()),
                cast(p_uint64, M), cast(p_uint64, N), cast(p_uint64, K),
                alpha_expr, beta_expr,
                cast(p_uint64, ldA), cast(p_uint64, ldB), cast(p_uint64, ldC),
                cast(p_uint64, offsetA), cast(p_uint64, offsetB), cast(p_uint64, offsetC),
                cast(p_boolean, transposeA), cast(p_boolean, transposeB)
            },
            tiramisu::p_uint8);
}

expr cuda_stream_synchronize()
{
    return expr(o_call, "tiramisu_cuda_stream_synchronize", {int32_t(0)}, tiramisu::p_int32);
}

extern "C"
int tiramisu_cblas_sgemm(float *A, float *B, float *C,
                          uint64_t M, uint64_t N, uint64_t K,
                          float alpha, float beta,
                          uint64_t ldA, uint64_t ldB, uint64_t ldC,
                          uint64_t offsetA, uint64_t offsetB, uint64_t offsetC,
                          bool transposeA, bool transposeB)
{
    // Default values for tight packing:
    if (ldA == 0) {
        ldA = transposeA ? M : K;
    }
    if (ldB == 0) {
        ldB = transposeB ? K : N;
    }
    if (ldC == 0) {
        ldC = N;
    }

    cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
                M, N, K, alpha, A+offsetA, K, B+ offsetB, N, beta, C+ offsetC, N);
    return 0;
}

extern "C"
int tiramisu_cblas_dgemm(double *A, double *B, double *C,
                          uint64_t M, uint64_t N, uint64_t K,
                          double alpha, double beta,
                          uint64_t ldA, uint64_t ldB, uint64_t ldC,
                          uint64_t offsetA, uint64_t offsetB, uint64_t offsetC,
                          bool transposeA, bool transposeB)
{
    // Default values for tight packing:
    if (ldA == 0) {
        ldA = transposeA ? M : K;
    }
    if (ldB == 0) {
        ldB = transposeB ? K : N;
    }
    if (ldC == 0) {
        ldC = N;
    }

    cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
                M, N, K, alpha, A+offsetA, K, B+ offsetB, N, beta, C+ offsetC, N);
    return 0;
}

expr cblas_gemm_call(const buffer &A, const buffer &B, buffer &C,
                 expr M, expr N, expr K,
                 expr alpha, expr beta,
                 expr ldA, expr ldB, expr ldC,
                 expr offsetA, expr offsetB, expr offsetC,
                 expr transposeA, expr transposeB)
{
    std::string fname;
    expr alpha_expr;
    expr beta_expr;
    if (A.get_elements_type() == p_float32 &&
        B.get_elements_type() == p_float32 &&
        C.get_elements_type() == p_float32) {
        fname = "tiramisu_cblas_sgemm";
        alpha_expr = cast(p_float32, alpha);
        beta_expr = cast(p_float32, beta);
    } else if (A.get_elements_type() == p_float64 &&
               B.get_elements_type() == p_float64 &&
               C.get_elements_type() == p_float64) {
        fname = "tiramisu_cblas_dgemm";
        alpha_expr = cast(p_float64, alpha);
        beta_expr = cast(p_float64, beta);
    } else {
        ERROR("All input buffers should be of same type and either p_float32 or p_float64", true);
    }
    return expr(o_call, fname,
            {
                var(p_void_ptr, A.get_name()),
                var(p_void_ptr, B.get_name()),
                var(p_void_ptr, C.get_name()),
                cast(p_uint64, M), cast(p_uint64, N), cast(p_uint64, K),
                alpha_expr, beta_expr,
                cast(p_uint64, ldA), cast(p_uint64, ldB), cast(p_uint64, ldC),
                cast(p_uint64, offsetA), cast(p_uint64, offsetB), cast(p_uint64, offsetC),
                cast(p_boolean, transposeA), cast(p_boolean, transposeB)
            },
            tiramisu::p_uint8);
}

}
<commit_msg>Comment out BLAS specific code from tiramisu_expr.cpp<commit_after>#include <tiramisu/expr.h>
#include <tiramisu/core.h>

namespace tiramisu
{

tiramisu::expr& tiramisu::expr::operator=(tiramisu::expr const & e)
{
    this->_operator = e._operator;
    this->op = e.op;
    this->access_vector = e.access_vector;
    this->argument_vector = e.argument_vector;
    this->defined = e.defined;
    this->name = e.name;
    this->dtype = e.dtype;
    this->etype = e.etype;

    // Copy the integer value
    if (e.get_expr_type() == tiramisu::e_val)
    {
        if (e.get_data_type() == tiramisu::p_uint8)
        {
            this->uint8_value = e.get_uint8_value();
        }
        else if (e.get_data_type() == tiramisu::p_int8)
        {
            this->int8_value = e.get_int8_value();
        }
        else if (e.get_data_type() == tiramisu::p_uint16)
        {
            this->uint16_value = e.get_uint16_value();
        }
        else if (e.get_data_type() == tiramisu::p_int16)
        {
            this->int16_value = e.get_int16_value();
        }
        else if (e.get_data_type() == tiramisu::p_uint32)
        {
            this->uint32_value = e.get_uint32_value();
        }
        else if (e.get_data_type() == tiramisu::p_int32)
        {
            this->int32_value = e.get_int32_value();
        }
        else if (e.get_data_type() == tiramisu::p_uint64)
        {
            this->uint64_value = e.get_uint64_value();
        }
        else if (e.get_data_type() == tiramisu::p_int64)
        {
            this->int64_value = e.get_int64_value();
        }
        else if (e.get_data_type() == tiramisu::p_float32)
        {
            this->float32_value = e.get_float32_value();
        }
        else if (e.get_data_type() == tiramisu::p_float64)
        {
            this->float64_value = e.get_float64_value();
        }
    }
    return *this;
}

tiramisu::expr tiramisu::expr::substitute(std::vector<std::pair<var, expr>> substitutions) const
{
    for (auto &substitution: substitutions)
        if (this->is_equal(substitution.first))
            return substitution.second;

    return apply_to_operands([&substitutions](const expr& e){
        return e.substitute(substitutions);
    });
}

tiramisu::expr tiramisu::expr::substitute_access(std::string original, std::string substitute) const {
    expr && result = this->apply_to_operands([&original, &substitute](const expr& e){
        return e.substitute_access(original, substitute);
    });
    if (result.get_op_type() == o_access && result.name == original)
    {
        result.name = substitute;
    }
    return result;
}

tiramisu::var::var(std::string name, bool save)
{
    assert(!name.empty());

    auto declared = var::declared_vars.find(name);

    if (declared != var::declared_vars.end())
    {
        *this = declared->second;
    }
    else
    {
        this->name = name;
        this->etype = tiramisu::e_var;
        this->dtype = global::get_loop_iterator_data_type();
        this->defined = true;
        if (save)
        {
            var::declared_vars.insert(std::make_pair(name, *this));
            DEBUG(3, std::cout << "Saved variable " << this->name << " of type " << str_from_tiramisu_type_primitive(this->dtype));
        }
    }
}

tiramisu::var::var(tiramisu::primitive_t type, std::string name, bool save)
{
    assert(!name.empty());

    auto declared = var::declared_vars.find(name);

    if (declared != var::declared_vars.end())
    {
        assert(declared->second.dtype == type);
        *this = declared->second;
    }
    else
    {
        this->name = name;
        this->etype = tiramisu::e_var;
        this->dtype = type;
        this->defined = true;
        if (save)
        {
            var::declared_vars.insert(std::make_pair(name, *this));
            DEBUG(10, std::cout << "Saved variable " << this->name << " of type " << str_from_tiramisu_type_primitive(this->dtype));
        }
    }
}

tiramisu::expr tiramisu::expr::copy() const
{
    return (*this);
}

//std::unordered_map<std::string, var> tiramisu::var::declared_vars;

expr cast(primitive_t tT, const expr & e) {
    if (e.get_data_type() == tT)
        return e;
    return expr{o_cast, tT, e};
}

expr tiramisu::expr::operator+(tiramisu::expr other) const {
    return tiramisu::expr{o_add, *this, other};
}

expr tiramisu::expr::operator-(tiramisu::expr other) const {
    return tiramisu::expr{o_sub, *this, other};
}

expr tiramisu::expr::operator*(tiramisu::expr other) const {
    return tiramisu::expr{o_mul, *this, other};
}

expr tiramisu::expr::operator/(tiramisu::expr other) const {
    return tiramisu::expr{o_div, *this, other};
}

expr tiramisu::expr::operator%(tiramisu::expr other) const {
    return tiramisu::expr{o_mod, *this, other};
}

expr tiramisu::expr::operator>>(tiramisu::expr other) const {
    return tiramisu::expr{o_right_shift, *this, other};
}

expr tiramisu::expr::operator<<(tiramisu::expr other) const {
    return tiramisu::expr{o_left_shift, *this, other};
}

expr memcpy(const buffer &from, const buffer &to) {
    return expr(o_memcpy, var(p_void_ptr, from.get_name()), var(p_void_ptr, to.get_name()));
}

expr allocate(const buffer &b)
{
    return expr{o_allocate, b.get_name()};
}

expr cublas_gemm(const buffer &A, const buffer &B, buffer &C,
                 expr M, expr N, expr K,
                 expr alpha, expr beta,
                 expr ldA, expr ldB, expr ldC,
                 expr offsetA, expr offsetB, expr offsetC,
                 expr transposeA, expr transposeB)
{
    if (A.get_location() != cuda_ast::memory_location::global ||
        B.get_location() != cuda_ast::memory_location::global ||
        C.get_location() != cuda_ast::memory_location::global) {
        ERROR("Buffers must be on GPU global memory", true);
    }
    std::string fname;
    expr alpha_expr;
    expr beta_expr;
    if (A.get_elements_type() == p_float32 &&
        B.get_elements_type() == p_float32 &&
        C.get_elements_type() == p_float32) {
        fname = "tiramisu_cublas_sgemm";
        alpha_expr = cast(p_float32, alpha);
        beta_expr = cast(p_float32, beta);
    } else if (A.get_elements_type() == p_float64 &&
               B.get_elements_type() == p_float64 &&
               C.get_elements_type() == p_float64) {
        fname = "tiramisu_cublas_dgemm";
        alpha_expr = cast(p_float64, alpha);
        beta_expr = cast(p_float64, beta);
    } else {
        ERROR("All input buffers should be of same type and either p_float32 or p_float64", true);
    }
    return expr(o_call, fname,
            {
                var(p_void_ptr, A.get_name()),
                var(p_void_ptr, B.get_name()),
                var(p_void_ptr, C.get_name()),
                cast(p_uint64, M), cast(p_uint64, N), cast(p_uint64, K),
                alpha_expr, beta_expr,
                cast(p_uint64, ldA), cast(p_uint64, ldB), cast(p_uint64, ldC),
                cast(p_uint64, offsetA), cast(p_uint64, offsetB), cast(p_uint64, offsetC),
                cast(p_boolean, transposeA), cast(p_boolean, transposeB)
            },
            tiramisu::p_uint8);
}

expr cuda_stream_synchronize()
{
    return expr(o_call, "tiramisu_cuda_stream_synchronize", {int32_t(0)}, tiramisu::p_int32);
}

#if 0
extern "C"
int tiramisu_cblas_sgemm(float *A, float *B, float *C,
                          uint64_t M, uint64_t N, uint64_t K,
                          float alpha, float beta,
                          uint64_t ldA, uint64_t ldB, uint64_t ldC,
                          uint64_t offsetA, uint64_t offsetB, uint64_t offsetC,
                          bool transposeA, bool transposeB)
{
    // Default values for tight packing:
    if (ldA == 0) {
        ldA = transposeA ? M : K;
    }
    if (ldB == 0) {
        ldB = transposeB ? K : N;
    }
    if (ldC == 0) {
        ldC = N;
    }

    cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
                M, N, K, alpha, A+offsetA, K, B+ offsetB, N, beta, C+ offsetC, N);
    return 0;
}

extern "C"
int tiramisu_cblas_dgemm(double *A, double *B, double *C,
                          uint64_t M, uint64_t N, uint64_t K,
                          double alpha, double beta,
                          uint64_t ldA, uint64_t ldB, uint64_t ldC,
                          uint64_t offsetA, uint64_t offsetB, uint64_t offsetC,
                          bool transposeA, bool transposeB)
{
    // Default values for tight packing:
    if (ldA == 0) {
        ldA = transposeA ? M : K;
    }
    if (ldB == 0) {
        ldB = transposeB ? K : N;
    }
    if (ldC == 0) {
        ldC = N;
    }

    cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
                M, N, K, alpha, A+offsetA, K, B+ offsetB, N, beta, C+ offsetC, N);
    return 0;
}

expr cblas_gemm_call(const buffer &A, const buffer &B, buffer &C,
                 expr M, expr N, expr K,
                 expr alpha, expr beta,
                 expr ldA, expr ldB, expr ldC,
                 expr offsetA, expr offsetB, expr offsetC,
                 expr transposeA, expr transposeB)
{
    std::string fname;
    expr alpha_expr;
    expr beta_expr;
    if (A.get_elements_type() == p_float32 &&
        B.get_elements_type() == p_float32 &&
        C.get_elements_type() == p_float32) {
        fname = "tiramisu_cblas_sgemm";
        alpha_expr = cast(p_float32, alpha);
        beta_expr = cast(p_float32, beta);
    } else if (A.get_elements_type() == p_float64 &&
               B.get_elements_type() == p_float64 &&
               C.get_elements_type() == p_float64) {
        fname = "tiramisu_cblas_dgemm";
        alpha_expr = cast(p_float64, alpha);
        beta_expr = cast(p_float64, beta);
    } else {
        ERROR("All input buffers should be of same type and either p_float32 or p_float64", true);
    }
    return expr(o_call, fname,
            {
                var(p_void_ptr, A.get_name()),
                var(p_void_ptr, B.get_name()),
                var(p_void_ptr, C.get_name()),
                cast(p_uint64, M), cast(p_uint64, N), cast(p_uint64, K),
                alpha_expr, beta_expr,
                cast(p_uint64, ldA), cast(p_uint64, ldB), cast(p_uint64, ldC),
                cast(p_uint64, offsetA), cast(p_uint64, offsetB), cast(p_uint64, offsetC),
                cast(p_boolean, transposeA), cast(p_boolean, transposeB)
            },
            tiramisu::p_uint8);
}
#endif

}
<|endoftext|>


<commit_before>/*
 * Logger.cpp
 *
 * Copyright (C) 2019 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant to the terms of a commercial license agreement
 * with RStudio, then this program is licensed to you under the following terms:
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include <shared_core/Logger.hpp>

#include <boost/noncopyable.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/optional.hpp>

#include <sstream>

#include <shared_core/Error.hpp>
#include <shared_core/DateTime.hpp>
#include <shared_core/ILogDestination.hpp>

namespace rstudio {
namespace core {
namespace log {

typedef std::map<unsigned int, std::shared_ptr<ILogDestination> > LogMap;
typedef std::map<LogSection, LogMap> SectionLogMap;

namespace {

constexpr const char* s_occurredAt = "OCCURRED AT";
constexpr const char* s_loggedFrom = "LOGGED FROM";
constexpr const char* s_causedBy = "CAUSED BY";

std::ostream& operator<<(std::ostream& io_ostream, LogLevel in_logLevel)
{
   switch (in_logLevel)
   {
      case LogLevel::ERR:
      {
         io_ostream << "ERROR";
         break;
      }
      case LogLevel::WARN:
      {
         io_ostream << "WARNING";
         break;
      }
      case LogLevel::DEBUG:
      {
         io_ostream << "DEBUG";
         break;
      }
      case LogLevel::INFO:
      {
         io_ostream << "INFO";
         break;
      }
      case LogLevel::OFF:
      {
         io_ostream << "OFF";
         break;
      }
      default:
      {
         assert(false); // This shouldn't be possible
         if (in_logLevel > LogLevel::INFO)
            io_ostream << "INFO";
         else
            io_ostream << "OFF";
      }
   }

   return io_ostream;
}

std::string formatLogMessage(
   LogLevel in_logLevel,
   const std::string& in_message,
   const std::string& in_programId,
   const ErrorLocation& in_loggedFrom = ErrorLocation(),
   bool in_formatForSyslog = false)
{
   // Add the time.
   using namespace boost::posix_time;
   ptime time = microsec_clock::universal_time();

   std::ostringstream oss;
   oss << system::date_time::format(time, "%d %b %Y %H:%M:%S")
       << " [" << in_programId << "] "
       << in_logLevel
       << " "
       << in_message;

   if (in_loggedFrom.hasLocation())
      oss << s_delim << " " << s_loggedFrom << ": " << cleanDelims(in_loggedFrom.asString());

   oss << std::endl;

   return oss.str();
}

} // anonymous namespace

// Log Section =========================================================================================================
struct LogSection::Impl
{
   std::string Name;
   boost::optional<LogLevel> MaxLogLevel;
};

LogSection::LogSection(const std::string& in_name) :
   m_impl(new Impl())
{
   m_impl->Name = in_name;
}

LogSection::LogSection(const std::string& in_name, LogLevel in_logLevel) :
   m_impl(new Impl())
{
   m_impl->Name = in_name;
   m_impl->MaxLogLevel = in_logLevel;
}

bool LogSection::operator<(const LogSection& in_other) const
{
   return m_impl->Name < in_other.m_impl->Name;
}

bool LogSection::operator==(const LogSection& in_other) const
{
   return m_impl->Name == in_other.m_impl->Name;
}

LogLevel LogSection::getMaxLogLevel(LogLevel in_defaultLevel) const
{
   return boost::get_optional_value_or(m_impl->MaxLogLevel, in_defaultLevel);
}

const std::string& LogSection::getName() const
{
   return m_impl->Name;
}

// Logger Object =======================================================================================================
/**
 * @brief Class which logs messages to destinations.
 *
 * Multiple destinations may be added to this logger in order to write the same message to each destination.
 * The default log level is ERROR.
 */
struct Logger : boost::noncopyable
{
public:
   /**
    * @brief Writes a pre-formatted message to all registered destinations.
    *
    * @param in_logLevel    The log level of the message, which is passed to the destination for informational purposes.
    * @param in_message     The pre-formatted message.
 * @param in_loggedFrom         The location from which the error message was logged.
    */
   void writeMessageToDestinations(
      LogLevel in_logLevel,
      const std::string& in_message,
      const std::string& in_section = std::string(),
      const ErrorLocation& in_loggedFrom = ErrorLocation());

   /**
    * @brief Constructor to prevent multiple instances of Logger.
    */
   Logger() :
      MaxLogLevel(LogLevel::OFF),
      DefaultLogLevel(LogLevel::OFF),
      ProgramId("")
   { };

   // The maximum level of message to write across all log sections.
   LogLevel MaxLogLevel;

   // The default maximum level of message to write.
   LogLevel DefaultLogLevel;

   // The ID of the program fr which to write logs.
   std::string ProgramId;

   // The registered default log destinations. Any logs without a section or with an unregistered section will be logged
   // to these destinations.
   LogMap DefaultLogDestinations;

   // The registered sectioned log destinations. Any logs with a registered section will be logged to the destinations
   // assigned to that section.
   SectionLogMap SectionedLogDestinations;
};

Logger& logger()
{
   static Logger logger;
   return logger;
}

void Logger::writeMessageToDestinations(
   LogLevel in_logLevel,
   const std::string& in_message,
   const std::string& in_section,
   const ErrorLocation& in_loggedFrom)
{
   LogLevel maxLogLevel = DefaultLogLevel;
   LogMap* logMap = &DefaultLogDestinations;
   if (!in_section.empty())
   {
      // Don't log anything if there is no logger for this section.
      if (SectionedLogDestinations.find(in_section) == SectionedLogDestinations.end())
         return;
      auto logDestIter = SectionedLogDestinations.find(in_section);
      logMap = &logDestIter->second;
      maxLogLevel = logDestIter->first.getMaxLogLevel(maxLogLevel);
   }

   // Don't log this message, it's too detailed for the configuration.
   if (in_logLevel > maxLogLevel)
      return;

   // Preformat the message for non-syslog loggers.
   std::string formattedMessage = formatLogMessage(in_logLevel, in_message, ProgramId, in_loggedFrom);

   const auto destEnd = logMap->end();
   for (auto iter = logMap->begin(); iter != destEnd; ++iter)
   {
      iter->second->writeLog(in_logLevel, formattedMessage);
   }
}

// Logging functions
void setProgramId(const std::string& in_programId)
{
   if (!logger().ProgramId.empty() && (logger().ProgramId != in_programId))
      logWarningMessage("Changing the program id from " + logger().ProgramId + " to " + in_programId);

   logger().ProgramId = in_programId;
}

void setLogLevel(LogLevel in_logLevel)
{
   logger().DefaultLogLevel = in_logLevel;
   if (in_logLevel > logger().MaxLogLevel)
      logger().MaxLogLevel = in_logLevel;
}

void addLogDestination(const std::shared_ptr<ILogDestination>& in_destination)
{
   LogMap& logMap = logger().DefaultLogDestinations;
   if (logMap.find(in_destination->getId()) == logMap.end())
      logMap.insert(std::make_pair(in_destination->getId(), in_destination));
   else {
      logDebugMessage(
         "Attempted to register a log destination that has already been registered with id " +
          std::to_string(in_destination->getId()));
   }
}

void addLogDestination(const std::shared_ptr<ILogDestination>& in_destination, const LogSection& in_section)
{
   Logger& log = logger();
   SectionLogMap& secLogMap =log.SectionedLogDestinations;
   if (secLogMap.find(in_section) == secLogMap.end())
      secLogMap.insert(std::make_pair(in_section, LogMap()));

   LogMap& logMap = secLogMap.find(in_section)->second;

   if (logMap.find(in_destination->getId()) == logMap.end())
      logMap.insert(std::make_pair(in_destination->getId(), in_destination));
   else
   {
      logDebugMessage(
         "Attempted to register a log destination that has already been registered with id " +
         std::to_string(in_destination->getId()) +
         " to section " +
         in_section.getName());
   }

   if (in_section.getMaxLogLevel(log.DefaultLogLevel) > log.MaxLogLevel)
      log.MaxLogLevel = in_section.getMaxLogLevel(log.DefaultLogLevel);
}

std::string cleanDelims(const std::string& in_toClean)
{
   std::string toClean(in_toClean);
   std::replace(toClean.begin(), toClean.end(), s_delim, ' ');
   return toClean;
}

void logError(const Error& in_error)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::ERR)
   {
      log.writeMessageToDestinations(LogLevel::ERR, in_error.asString());
   }
}

void logError(const Error& in_error, const ErrorLocation& in_location)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::ERR)
      log.writeMessageToDestinations(LogLevel::ERR, in_error.asString(), "", in_location);
}

void logErrorAsWarning(const Error& in_error)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::WARN)
   {
      log.writeMessageToDestinations(LogLevel::WARN, in_error.asString());
   }
}

void logErrorAsInfo(const Error& in_error)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::INFO)
   {
      log.writeMessageToDestinations(LogLevel::INFO, in_error.asString());
   }
}

void logErrorAsDebug(const Error& in_error)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::DEBUG)
   {
      log.writeMessageToDestinations(LogLevel::DEBUG, in_error.asString());
   }
}

void logErrorMessage(const std::string& in_message, const std::string& in_section)
{
   logErrorMessage(in_message, in_section, ErrorLocation());
}

void logErrorMessage(const std::string& in_message, const ErrorLocation& in_loggedFrom)
{
   logErrorMessage(in_message, "", in_loggedFrom);
}

void logErrorMessage(const std::string& in_message, const std::string& in_section, const ErrorLocation& in_loggedFrom)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::ERR)
      log.writeMessageToDestinations(LogLevel::ERR, in_message, in_section, in_loggedFrom);
}

void logWarningMessage(const std::string& in_message, const std::string& in_section)
{
   logWarningMessage(in_message, in_section, ErrorLocation());
}

void logWarningMessage(const std::string& in_message, const ErrorLocation& in_loggedFrom)
{
   logWarningMessage(in_message, "", in_loggedFrom);
}

void logWarningMessage(const std::string& in_message, const std::string& in_section, const ErrorLocation& in_loggedFrom)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::WARN)
      log.writeMessageToDestinations(LogLevel::WARN, in_message, in_section, in_loggedFrom);
}

void logDebugMessage(const std::string& in_message, const std::string& in_section)
{
   logDebugMessage(in_message, in_section, ErrorLocation());
}

void logDebugMessage(const std::string& in_message, const ErrorLocation& in_loggedFrom)
{
   logDebugMessage(in_message, "", in_loggedFrom);
}

void logDebugMessage(const std::string& in_message, const std::string& in_section, const ErrorLocation& in_loggedFrom)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::DEBUG)
      log.writeMessageToDestinations(LogLevel::DEBUG, in_message, in_section, in_loggedFrom);
}

void logInfoMessage(const std::string& in_message, const std::string& in_section)
{
   logInfoMessage(in_message, in_section, ErrorLocation());
}

void logInfoMessage(const std::string& in_message, const ErrorLocation& in_loggedFrom)
{
   logInfoMessage(in_message, "", in_loggedFrom);
}

void logInfoMessage(const std::string& in_message, const std::string& in_section, const ErrorLocation& in_loggedFrom)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::INFO)
      log.writeMessageToDestinations(LogLevel::INFO, in_message, in_section, in_loggedFrom);
}

void removeLogDestination(unsigned int in_destinationId, const std::string& in_section)
{
   Logger& log = logger();
   if (in_section.empty())
   {
      // Remove the log from default destinations if it's found. Keep track of whether we find it for logging purposes.
      bool found = false;
      auto iter = log.DefaultLogDestinations.find(in_destinationId);
      if (iter != log.DefaultLogDestinations.end())
      {
         found = true;
         log.DefaultLogDestinations.erase(iter);
      }

      // Remove it from any sections it may have been registered to.
      std::vector<LogSection> sectionsToRemove;
      for (auto secIter: log.SectionedLogDestinations)
      {
         iter = secIter.second.find(in_destinationId);
         if (iter != secIter.second.end())
         {
            found = true;
            secIter.second.erase(iter);
         }

         if (secIter.second.empty())
            sectionsToRemove.push_back(secIter.first);
      }

      // Clean up any empty sections.
      for (const LogSection& toRemove: sectionsToRemove)
         log.SectionedLogDestinations.erase(log.SectionedLogDestinations.find(toRemove));

      // Log a debug message if this destination wasn't registered.
      if (!found)
      {
         logDebugMessage(
            "Attempted to unregister a log destination that has not been registered with id" +
            std::to_string(in_destinationId));
      }
   }
   else if (log.SectionedLogDestinations.find(in_section) != log.SectionedLogDestinations.end())
      {
         auto secIter = log.SectionedLogDestinations.find(in_section);
         auto iter = secIter->second.find(in_destinationId);
         if (iter != secIter->second.end())
         {
            secIter->second.erase(iter);
            if (secIter->second.empty())
               log.SectionedLogDestinations.erase(secIter);
         }
         else
         {
            logDebugMessage(
               "Attempted to unregister a log destination that has not been registered to the specified section (" +
               in_section +
               ") with id " +
               std::to_string(in_destinationId));
         }
      }
}

std::ostream& writeError(const Error& in_error, std::ostream& io_os)
{
   return io_os << writeError(in_error);
}

std::string writeError(const Error& in_error)
{
   return formatLogMessage(LogLevel::ERR, in_error.asString(), logger().ProgramId);
}

} // namespace log
} // namespace core
} // namespace rstudio
<commit_msg>fix a comment that was missing a param<commit_after>/*
 * Logger.cpp
 *
 * Copyright (C) 2019 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant to the terms of a commercial license agreement
 * with RStudio, then this program is licensed to you under the following terms:
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include <shared_core/Logger.hpp>

#include <boost/noncopyable.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/optional.hpp>

#include <sstream>

#include <shared_core/Error.hpp>
#include <shared_core/DateTime.hpp>
#include <shared_core/ILogDestination.hpp>

namespace rstudio {
namespace core {
namespace log {

typedef std::map<unsigned int, std::shared_ptr<ILogDestination> > LogMap;
typedef std::map<LogSection, LogMap> SectionLogMap;

namespace {

constexpr const char* s_occurredAt = "OCCURRED AT";
constexpr const char* s_loggedFrom = "LOGGED FROM";
constexpr const char* s_causedBy = "CAUSED BY";

std::ostream& operator<<(std::ostream& io_ostream, LogLevel in_logLevel)
{
   switch (in_logLevel)
   {
      case LogLevel::ERR:
      {
         io_ostream << "ERROR";
         break;
      }
      case LogLevel::WARN:
      {
         io_ostream << "WARNING";
         break;
      }
      case LogLevel::DEBUG:
      {
         io_ostream << "DEBUG";
         break;
      }
      case LogLevel::INFO:
      {
         io_ostream << "INFO";
         break;
      }
      case LogLevel::OFF:
      {
         io_ostream << "OFF";
         break;
      }
      default:
      {
         assert(false); // This shouldn't be possible
         if (in_logLevel > LogLevel::INFO)
            io_ostream << "INFO";
         else
            io_ostream << "OFF";
      }
   }

   return io_ostream;
}

std::string formatLogMessage(
   LogLevel in_logLevel,
   const std::string& in_message,
   const std::string& in_programId,
   const ErrorLocation& in_loggedFrom = ErrorLocation(),
   bool in_formatForSyslog = false)
{
   // Add the time.
   using namespace boost::posix_time;
   ptime time = microsec_clock::universal_time();

   std::ostringstream oss;
   oss << system::date_time::format(time, "%d %b %Y %H:%M:%S")
       << " [" << in_programId << "] "
       << in_logLevel
       << " "
       << in_message;

   if (in_loggedFrom.hasLocation())
      oss << s_delim << " " << s_loggedFrom << ": " << cleanDelims(in_loggedFrom.asString());

   oss << std::endl;

   return oss.str();
}

} // anonymous namespace

// Log Section =========================================================================================================
struct LogSection::Impl
{
   std::string Name;
   boost::optional<LogLevel> MaxLogLevel;
};

LogSection::LogSection(const std::string& in_name) :
   m_impl(new Impl())
{
   m_impl->Name = in_name;
}

LogSection::LogSection(const std::string& in_name, LogLevel in_logLevel) :
   m_impl(new Impl())
{
   m_impl->Name = in_name;
   m_impl->MaxLogLevel = in_logLevel;
}

bool LogSection::operator<(const LogSection& in_other) const
{
   return m_impl->Name < in_other.m_impl->Name;
}

bool LogSection::operator==(const LogSection& in_other) const
{
   return m_impl->Name == in_other.m_impl->Name;
}

LogLevel LogSection::getMaxLogLevel(LogLevel in_defaultLevel) const
{
   return boost::get_optional_value_or(m_impl->MaxLogLevel, in_defaultLevel);
}

const std::string& LogSection::getName() const
{
   return m_impl->Name;
}

// Logger Object =======================================================================================================
/**
 * @brief Class which logs messages to destinations.
 *
 * Multiple destinations may be added to this logger in order to write the same message to each destination.
 * The default log level is ERROR.
 */
struct Logger : boost::noncopyable
{
public:
   /**
    * @brief Writes a pre-formatted message to all registered destinations.
    *
    * @param in_logLevel        The log level of the message, which is passed to the destination for informational purposes.
    * @param in_message         The pre-formatted message.
    * @param in_section         The section to which to log this message.
    * @param in_loggedFrom      The location from which the error message was logged.
    */
   void writeMessageToDestinations(
      LogLevel in_logLevel,
      const std::string& in_message,
      const std::string& in_section = std::string(),
      const ErrorLocation& in_loggedFrom = ErrorLocation());

   /**
    * @brief Constructor to prevent multiple instances of Logger.
    */
   Logger() :
      MaxLogLevel(LogLevel::OFF),
      DefaultLogLevel(LogLevel::OFF),
      ProgramId("")
   { };

   // The maximum level of message to write across all log sections.
   LogLevel MaxLogLevel;

   // The default maximum level of message to write.
   LogLevel DefaultLogLevel;

   // The ID of the program fr which to write logs.
   std::string ProgramId;

   // The registered default log destinations. Any logs without a section or with an unregistered section will be logged
   // to these destinations.
   LogMap DefaultLogDestinations;

   // The registered sectioned log destinations. Any logs with a registered section will be logged to the destinations
   // assigned to that section.
   SectionLogMap SectionedLogDestinations;
};

Logger& logger()
{
   static Logger logger;
   return logger;
}

void Logger::writeMessageToDestinations(
   LogLevel in_logLevel,
   const std::string& in_message,
   const std::string& in_section,
   const ErrorLocation& in_loggedFrom)
{
   LogLevel maxLogLevel = DefaultLogLevel;
   LogMap* logMap = &DefaultLogDestinations;
   if (!in_section.empty())
   {
      // Don't log anything if there is no logger for this section.
      if (SectionedLogDestinations.find(in_section) == SectionedLogDestinations.end())
         return;
      auto logDestIter = SectionedLogDestinations.find(in_section);
      logMap = &logDestIter->second;
      maxLogLevel = logDestIter->first.getMaxLogLevel(maxLogLevel);
   }

   // Don't log this message, it's too detailed for the configuration.
   if (in_logLevel > maxLogLevel)
      return;

   // Preformat the message for non-syslog loggers.
   std::string formattedMessage = formatLogMessage(in_logLevel, in_message, ProgramId, in_loggedFrom);

   const auto destEnd = logMap->end();
   for (auto iter = logMap->begin(); iter != destEnd; ++iter)
   {
      iter->second->writeLog(in_logLevel, formattedMessage);
   }
}

// Logging functions
void setProgramId(const std::string& in_programId)
{
   if (!logger().ProgramId.empty() && (logger().ProgramId != in_programId))
      logWarningMessage("Changing the program id from " + logger().ProgramId + " to " + in_programId);

   logger().ProgramId = in_programId;
}

void setLogLevel(LogLevel in_logLevel)
{
   logger().DefaultLogLevel = in_logLevel;
   if (in_logLevel > logger().MaxLogLevel)
      logger().MaxLogLevel = in_logLevel;
}

void addLogDestination(const std::shared_ptr<ILogDestination>& in_destination)
{
   LogMap& logMap = logger().DefaultLogDestinations;
   if (logMap.find(in_destination->getId()) == logMap.end())
      logMap.insert(std::make_pair(in_destination->getId(), in_destination));
   else {
      logDebugMessage(
         "Attempted to register a log destination that has already been registered with id " +
          std::to_string(in_destination->getId()));
   }
}

void addLogDestination(const std::shared_ptr<ILogDestination>& in_destination, const LogSection& in_section)
{
   Logger& log = logger();
   SectionLogMap& secLogMap =log.SectionedLogDestinations;
   if (secLogMap.find(in_section) == secLogMap.end())
      secLogMap.insert(std::make_pair(in_section, LogMap()));

   LogMap& logMap = secLogMap.find(in_section)->second;

   if (logMap.find(in_destination->getId()) == logMap.end())
      logMap.insert(std::make_pair(in_destination->getId(), in_destination));
   else
   {
      logDebugMessage(
         "Attempted to register a log destination that has already been registered with id " +
         std::to_string(in_destination->getId()) +
         " to section " +
         in_section.getName());
   }

   if (in_section.getMaxLogLevel(log.DefaultLogLevel) > log.MaxLogLevel)
      log.MaxLogLevel = in_section.getMaxLogLevel(log.DefaultLogLevel);
}

std::string cleanDelims(const std::string& in_toClean)
{
   std::string toClean(in_toClean);
   std::replace(toClean.begin(), toClean.end(), s_delim, ' ');
   return toClean;
}

void logError(const Error& in_error)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::ERR)
   {
      log.writeMessageToDestinations(LogLevel::ERR, in_error.asString());
   }
}

void logError(const Error& in_error, const ErrorLocation& in_location)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::ERR)
      log.writeMessageToDestinations(LogLevel::ERR, in_error.asString(), "", in_location);
}

void logErrorAsWarning(const Error& in_error)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::WARN)
   {
      log.writeMessageToDestinations(LogLevel::WARN, in_error.asString());
   }
}

void logErrorAsInfo(const Error& in_error)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::INFO)
   {
      log.writeMessageToDestinations(LogLevel::INFO, in_error.asString());
   }
}

void logErrorAsDebug(const Error& in_error)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::DEBUG)
   {
      log.writeMessageToDestinations(LogLevel::DEBUG, in_error.asString());
   }
}

void logErrorMessage(const std::string& in_message, const std::string& in_section)
{
   logErrorMessage(in_message, in_section, ErrorLocation());
}

void logErrorMessage(const std::string& in_message, const ErrorLocation& in_loggedFrom)
{
   logErrorMessage(in_message, "", in_loggedFrom);
}

void logErrorMessage(const std::string& in_message, const std::string& in_section, const ErrorLocation& in_loggedFrom)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::ERR)
      log.writeMessageToDestinations(LogLevel::ERR, in_message, in_section, in_loggedFrom);
}

void logWarningMessage(const std::string& in_message, const std::string& in_section)
{
   logWarningMessage(in_message, in_section, ErrorLocation());
}

void logWarningMessage(const std::string& in_message, const ErrorLocation& in_loggedFrom)
{
   logWarningMessage(in_message, "", in_loggedFrom);
}

void logWarningMessage(const std::string& in_message, const std::string& in_section, const ErrorLocation& in_loggedFrom)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::WARN)
      log.writeMessageToDestinations(LogLevel::WARN, in_message, in_section, in_loggedFrom);
}

void logDebugMessage(const std::string& in_message, const std::string& in_section)
{
   logDebugMessage(in_message, in_section, ErrorLocation());
}

void logDebugMessage(const std::string& in_message, const ErrorLocation& in_loggedFrom)
{
   logDebugMessage(in_message, "", in_loggedFrom);
}

void logDebugMessage(const std::string& in_message, const std::string& in_section, const ErrorLocation& in_loggedFrom)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::DEBUG)
      log.writeMessageToDestinations(LogLevel::DEBUG, in_message, in_section, in_loggedFrom);
}

void logInfoMessage(const std::string& in_message, const std::string& in_section)
{
   logInfoMessage(in_message, in_section, ErrorLocation());
}

void logInfoMessage(const std::string& in_message, const ErrorLocation& in_loggedFrom)
{
   logInfoMessage(in_message, "", in_loggedFrom);
}

void logInfoMessage(const std::string& in_message, const std::string& in_section, const ErrorLocation& in_loggedFrom)
{
   Logger& log = logger();
   if (log.MaxLogLevel >= LogLevel::INFO)
      log.writeMessageToDestinations(LogLevel::INFO, in_message, in_section, in_loggedFrom);
}

void removeLogDestination(unsigned int in_destinationId, const std::string& in_section)
{
   Logger& log = logger();
   if (in_section.empty())
   {
      // Remove the log from default destinations if it's found. Keep track of whether we find it for logging purposes.
      bool found = false;
      auto iter = log.DefaultLogDestinations.find(in_destinationId);
      if (iter != log.DefaultLogDestinations.end())
      {
         found = true;
         log.DefaultLogDestinations.erase(iter);
      }

      // Remove it from any sections it may have been registered to.
      std::vector<LogSection> sectionsToRemove;
      for (auto secIter: log.SectionedLogDestinations)
      {
         iter = secIter.second.find(in_destinationId);
         if (iter != secIter.second.end())
         {
            found = true;
            secIter.second.erase(iter);
         }

         if (secIter.second.empty())
            sectionsToRemove.push_back(secIter.first);
      }

      // Clean up any empty sections.
      for (const LogSection& toRemove: sectionsToRemove)
         log.SectionedLogDestinations.erase(log.SectionedLogDestinations.find(toRemove));

      // Log a debug message if this destination wasn't registered.
      if (!found)
      {
         logDebugMessage(
            "Attempted to unregister a log destination that has not been registered with id" +
            std::to_string(in_destinationId));
      }
   }
   else if (log.SectionedLogDestinations.find(in_section) != log.SectionedLogDestinations.end())
      {
         auto secIter = log.SectionedLogDestinations.find(in_section);
         auto iter = secIter->second.find(in_destinationId);
         if (iter != secIter->second.end())
         {
            secIter->second.erase(iter);
            if (secIter->second.empty())
               log.SectionedLogDestinations.erase(secIter);
         }
         else
         {
            logDebugMessage(
               "Attempted to unregister a log destination that has not been registered to the specified section (" +
               in_section +
               ") with id " +
               std::to_string(in_destinationId));
         }
      }
}

std::ostream& writeError(const Error& in_error, std::ostream& io_os)
{
   return io_os << writeError(in_error);
}

std::string writeError(const Error& in_error)
{
   return formatLogMessage(LogLevel::ERR, in_error.asString(), logger().ProgramId);
}

} // namespace log
} // namespace core
} // namespace rstudio
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium 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 "chrome/test/ui/ui_test.h"

#include "base/environment.h"
#include "build/build_config.h"

class LocaleTestsBase : public UITest {
 public:
  LocaleTestsBase() : UITest(), old_lc_all_(NULL) {
  }

 protected:
  void RestoreLcAllEnvironment() {
#if defined(OS_LINUX)
    scoped_ptr<base::Environment> env(base::Environment::Create());
    if (old_lc_all_) {
      env->SetVar("LC_ALL", old_lc_all_);
    } else {
      env->UnSetVar("LC_ALL");
    }
#endif
  };

  const char* old_lc_all_;
};

class LocaleTestsDa : public LocaleTestsBase {
 public:
  LocaleTestsDa() : LocaleTestsBase() {
    launch_arguments_.AppendSwitchASCII("lang", "da");

    // Linux doesn't use --lang, it only uses environment variables to set the
    // language.
#if defined(OS_LINUX)
    old_lc_all_ = getenv("LC_ALL");
    setenv("LC_ALL", "da_DK.UTF-8", 1);
#endif
  }
};

class LocaleTestsHe : public LocaleTestsBase {
 public:
  LocaleTestsHe() : LocaleTestsBase() {
    launch_arguments_.AppendSwitchASCII("lang", "he");
#if defined(OS_LINUX)
    old_lc_all_ = getenv("LC_ALL");
    setenv("LC_ALL", "he_IL.UTF-8", 1);
#endif
  }
};

class LocaleTestsZhTw : public LocaleTestsBase {
 public:
  LocaleTestsZhTw() : LocaleTestsBase() {
    launch_arguments_.AppendSwitchASCII("lang", "zh-TW");
#if defined(OS_LINUX)
    old_lc_all_ = getenv("LC_ALL");
    setenv("LC_ALL", "zh_TW.UTF-8", 1);
#endif
  }
};

TEST_F(LocaleTestsDa, TestStart) {
  // Just making sure we can start/shutdown cleanly.
  RestoreLcAllEnvironment();
}

TEST_F(LocaleTestsHe, TestStart) {
  // Just making sure we can start/shutdown cleanly.
  RestoreLcAllEnvironment();
}

TEST_F(LocaleTestsZhTw, TestStart) {
  // Just making sure we can start/shutdown cleanly.
  RestoreLcAllEnvironment();
}
<commit_msg>Change locale uitests so that the language environment will be restored even if an assertion occurs in SetUp().<commit_after>// Copyright (c) 2010 The Chromium 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 "chrome/test/ui/ui_test.h"

#include "base/environment.h"
#include "build/build_config.h"

class LocaleTestsBase : public UITest {
 public:
  LocaleTestsBase() : UITest(), old_lc_all_(NULL) {
  }

  virtual void TearDown() {
#if defined(OS_LINUX)
    scoped_ptr<base::Environment> env(base::Environment::Create());
    if (old_lc_all_) {
      env->SetVar("LC_ALL", old_lc_all_);
    } else {
      env->UnSetVar("LC_ALL");
    }
#endif
    UITest::TearDown();
  }

 protected:
  const char* old_lc_all_;
};

class LocaleTestsDa : public LocaleTestsBase {
 public:
  LocaleTestsDa() : LocaleTestsBase() {
    launch_arguments_.AppendSwitchASCII("lang", "da");

    // Linux doesn't use --lang, it only uses environment variables to set the
    // language.
#if defined(OS_LINUX)
    old_lc_all_ = getenv("LC_ALL");
    setenv("LC_ALL", "da_DK.UTF-8", 1);
#endif
  }
};

class LocaleTestsHe : public LocaleTestsBase {
 public:
  LocaleTestsHe() : LocaleTestsBase() {
    launch_arguments_.AppendSwitchASCII("lang", "he");
#if defined(OS_LINUX)
    old_lc_all_ = getenv("LC_ALL");
    setenv("LC_ALL", "he_IL.UTF-8", 1);
#endif
  }
};

class LocaleTestsZhTw : public LocaleTestsBase {
 public:
  LocaleTestsZhTw() : LocaleTestsBase() {
    launch_arguments_.AppendSwitchASCII("lang", "zh-TW");
#if defined(OS_LINUX)
    old_lc_all_ = getenv("LC_ALL");
    setenv("LC_ALL", "zh_TW.UTF-8", 1);
#endif
  }
};

TEST_F(LocaleTestsDa, TestStart) {
  // Just making sure we can start/shutdown cleanly.
}

TEST_F(LocaleTestsHe, TestStart) {
  // Just making sure we can start/shutdown cleanly.
}

TEST_F(LocaleTestsZhTw, TestStart) {
  // Just making sure we can start/shutdown cleanly.
}
<|endoftext|>