<commit_before>#include "filebrowserwidget.h"

#include <QApplication>
#include <QDesktopServices>
#include <QFileSystemModel>
#include <QHeaderView>
#include <QMouseEvent>
#include <QSettings>

static const QString SettingsColumnWidth = "_ColumnWidth";
static const QString SettingsInitialPath = "_InitialPath";
static const QString SettingsSortColumn  = "_SortColumn";
static const QString SettingsSortOrder   = "_SortOrder";

FileBrowserWidget::FileBrowserWidget(QWidget *pParent) :
    QTreeView(pParent),
    CommonWidget(pParent),
    mNeedDefColWidth(true)
{
    mFileSystemModel = new QFileSystemModel;

    // We want acces to the full, but filtered, file system

    mFileSystemModel->setRootPath("");
    mFileSystemModel->setFilter(QDir::AllEntries|QDir::NoDotAndDotDot|QDir::NoSymLinks);

    // Set some properties for the file browser widget itself

#ifdef Q_WS_MAC
    setAttribute(Qt::WA_MacShowFocusRect, 0);   // Remove the focus border since
                                                // it messes up our toolbar
#endif
    setModel(mFileSystemModel);   // Associate ourselves to mFileSystemModel
    setSortingEnabled(true);      // Allow sorting
    setUniformRowHeights(true);   // Everything ought to be of the same height,
                                  // so set this property to true since it can
                                  // only speed things up which can't harm!

    // Connection to keep track of the directory loading progress of
    // mFileSystemModel

    connect(mFileSystemModel, SIGNAL(directoryLoaded(const QString &)),
            this, SLOT(directoryLoaded(const QString &)));
}

FileBrowserWidget::~FileBrowserWidget()
{
    delete mFileSystemModel;
}

void FileBrowserWidget::loadSettings(const QSettings &pSettings,
                                     const QString &pKey)
{
    // Retrieve the width of each column

    QString columnWidthKey;

    for (int i = 0; i < header()->count(); ++i) {
        columnWidthKey = pKey+SettingsColumnWidth+QString::number(i);

        mNeedDefColWidth =     mNeedDefColWidth
                           && !pSettings.contains(columnWidthKey);

        setColumnWidth(i, pSettings.value(columnWidthKey,
                                          columnWidth(i)).toInt());
    }

    // Retrieve the sorting information

    sortByColumn(pSettings.value(pKey+SettingsSortColumn, 0).toInt(),
                 Qt::SortOrder(pSettings.value(pKey+SettingsSortOrder,
                                               Qt::AscendingOrder).toInt()));

    // Retrieve the initial path

    mInitPath = pSettings.value(pKey+SettingsInitialPath,
                                QDir::homePath()).toString();

    QFileInfo initPathFileInfo = mInitPath;

    if (!initPathFileInfo.exists()) {
        // The initial path doesn't exist, so just revert to the home path

        mInitPathDir = QDir::homePath();
        mInitPath    = "";
    } else {
        // The initial path exists, so retrieve some information about the
        // folder and/or file (depending on whether the initial path refers to
        // a file or not)
        // Note: indeed, should mInitPath refer to a file, then to directly set
        //       the current index of the tree view to that of a file won't give
        //       us the expected behaviour (i.e. the parent folder being open
        //       and expanded, and the file selected), so instead one must set
        //       the current index to that of the parent folder and then select
        //       the file

        if (initPathFileInfo.isDir()) {
            // We are dealing with a folder, so...

            mInitPathDir = initPathFileInfo.canonicalFilePath();
            mInitPath    = "";
        } else {
            // We are dealing with a file, so...

            mInitPathDir = initPathFileInfo.canonicalPath();
            mInitPath    = initPathFileInfo.canonicalFilePath();
        }
    }

    // Set the current index to that of the folder (and file, if it exists) we
    // are interested in
    // Note: this will result in the directoryLoaded signal to be emitted and,
    //       us, to take advantage of it to scroll to the right directory/file

    setCurrentIndex(mFileSystemModel->index(mInitPathDir));

    if (!mInitPath.isEmpty())
        // The initial path is that of a file, so...

        setCurrentIndex(mFileSystemModel->index(mInitPath));
}

void FileBrowserWidget::saveSettings(QSettings &pSettings, const QString &pKey)
{
    // Retrieve the width of each column

    for (int i = 0; i < header()->count(); ++i)
        pSettings.setValue(pKey+SettingsColumnWidth+QString::number(i),
                           columnWidth(i));

    // Keep track of the sorting information

    pSettings.setValue(pKey+SettingsSortColumn,
                       header()->sortIndicatorSection());
    pSettings.setValue(pKey+SettingsSortOrder, header()->sortIndicatorOrder());

    // Keep track of what will be our future initial folder/file path

    pSettings.setValue(pKey+SettingsInitialPath,
                       mFileSystemModel->filePath(currentIndex()));
}

QSize FileBrowserWidget::sizeHint() const
{
    // Suggest a default size for the file browser widget
    // Note: this is critical if we want a docked widget, with a file browser
    //       widget on it, to have a decent size when docked to the main window

    return defaultSize(0.15);
}

bool FileBrowserWidget::viewportEvent(QEvent *pEvent)
{
    if (pEvent->type() == QEvent::ToolTip) {
        // We need to show a tool tip, so make sure that it's up to date by
        // setting it to the file path of the current item

        QHelpEvent *helpEvent = static_cast<QHelpEvent *>(pEvent);

        setToolTip(QDir::toNativeSeparators(mFileSystemModel->filePath(indexAt(QPoint(helpEvent->x(),
                                                                                helpEvent->y())))));
    }

    // Default handling of the event

    return QTreeView::viewportEvent(pEvent);
}

void FileBrowserWidget::mousePressEvent(QMouseEvent *pEvent)
{
    if (pEvent->button() == Qt::RightButton)
        // We are pressing the right mouse button which may be used to display a
        // context menu and we don't want the row beneath the mouse to be
        // selected (in case it isn't already), so...

        pEvent->accept();
    else
        // We are not pressing the right mouse button, so carry on with the
        // default handling of the event

        QTreeView::mousePressEvent(pEvent);
}

void FileBrowserWidget::directoryLoaded(const QString &pPath)
{
    static bool needInitializing = true;

    if (needInitializing
        && (   ( mInitPath.isEmpty() && mInitPathDir.contains(pPath))
            || (!mInitPath.isEmpty() && mInitPath.contains(pPath)))) {
        // mFileSystemModel is still loading the initial path, so we try to
        // expand it and scroll to it, but first we process any pending event
        // (indeed, Windows doesn't need this, but Linux and Mac OS X definitely
        // do and it can't harm having it for all three environments, so...)

        qApp->processEvents();

        QModelIndex initPathDirModelIndex = mFileSystemModel->index(mInitPathDir);

        setExpanded(initPathDirModelIndex, true);
        scrollTo(initPathDirModelIndex);

        if (!mInitPath.isEmpty()) {
            // The initial path is that of a file and it exists, so select it

            QModelIndex initPathModelIndex = mFileSystemModel->index(mInitPath);

            setExpanded(initPathModelIndex, true);
            scrollTo(initPathModelIndex);
        }

        // Set the default width of the columns so that it fits their contents

        if (mNeedDefColWidth) {
            header()->setResizeMode(QHeaderView::ResizeToContents);

            qApp->processEvents();
            // Note: this ensures that the columns actually get resized

            header()->setResizeMode(QHeaderView::Interactive);
        }
    } else {
        // We are done initializing, so...

        needInitializing = false;
    }
}

void FileBrowserWidget::showCurrentPath()
{
    // Show the current path by scrolling to it

    scrollTo(currentIndex());
}

bool FileBrowserWidget::gotoPath(const QString &pPath, const bool &pExpand)
{
    // Set the current index to that of the provided path

    QModelIndex pathModelIndex = mFileSystemModel->index(pPath);

    if (pathModelIndex != QModelIndex()) {
        // The path exists, so we can go to it

        setCurrentIndex(pathModelIndex);

        if (pExpand)
            setExpanded(pathModelIndex, true);

        scrollTo(pathModelIndex);

        return true;
    } else {
        // The path doesn't exist, so...

        return false;
    }
}

QString FileBrowserWidget::homeFolder()
{
    // Return the path to the home folder

    return QDir::homePath();
}

void FileBrowserWidget::gotoHomeFolder(const bool &pExpand)
{
    // Go to the home folder

    gotoPath(QDir::homePath(), pExpand);
}

QString FileBrowserWidget::currentPath()
{
    // Return the current path

    return mFileSystemModel->filePath(currentIndex());
}

QString FileBrowserWidget::currentPathDir()
{
    // Return the directory of the current path

    QString crtIndexPath  = mFileSystemModel->filePath(currentIndex());
    QFileInfo crtIndexFileInfo  = crtIndexPath;

    return crtIndexFileInfo.isDir()?
               crtIndexPath:
               crtIndexFileInfo.dir().canonicalPath();
}

QString FileBrowserWidget::currentPathParent()
{
    // Return the current path parent, if any

    QModelIndex crtIndexParent = currentIndex().parent();

    return (crtIndexParent != QModelIndex())?
               mFileSystemModel->filePath(crtIndexParent):
               "";
}

bool FileBrowserWidget::isCurrentPathVisible()
{
    // Return whether the current path is visible or not, i.e. whether all of
    // the parent nodes are expanded or not

    bool result = true;
    QModelIndex crtIndex = currentIndex();

    while (result && (crtIndex.parent() != QModelIndex())) {
        crtIndex = crtIndex.parent();

        if (!isExpanded(crtIndex))
            // The current parent is not expanded, meaning the current path
            // cannot be visible, so...

            result = false;
    }

    return result;
}

bool FileBrowserWidget::isCurrentPathDirWritable()
{
    // Return whether the directory of the current path is writable or not

    return QFileInfo(currentPathDir()).isWritable();
}

bool FileBrowserWidget::isCurrentPathWritable()
{
    // Return whether the current path is writable or not

    return QFileInfo(currentPath()).isWritable();
}
<commit_msg>File browser window: made symbolic links visible, since they are common on Linux / Mac OS X.<commit_after>#include "filebrowserwidget.h"

#include <QApplication>
#include <QDesktopServices>
#include <QFileSystemModel>
#include <QHeaderView>
#include <QMouseEvent>
#include <QSettings>

static const QString SettingsColumnWidth = "_ColumnWidth";
static const QString SettingsInitialPath = "_InitialPath";
static const QString SettingsSortColumn  = "_SortColumn";
static const QString SettingsSortOrder   = "_SortOrder";

FileBrowserWidget::FileBrowserWidget(QWidget *pParent) :
    QTreeView(pParent),
    CommonWidget(pParent),
    mNeedDefColWidth(true)
{
    mFileSystemModel = new QFileSystemModel;

    // We want acces to the full file system

    mFileSystemModel->setRootPath("");

    // Set some properties for the file browser widget itself

#ifdef Q_WS_MAC
    setAttribute(Qt::WA_MacShowFocusRect, 0);   // Remove the focus border since
                                                // it messes up our toolbar
#endif
    setModel(mFileSystemModel);   // Associate ourselves to mFileSystemModel
    setSortingEnabled(true);      // Allow sorting
    setUniformRowHeights(true);   // Everything ought to be of the same height,
                                  // so set this property to true since it can
                                  // only speed things up which can't harm!

    // Connection to keep track of the directory loading progress of
    // mFileSystemModel

    connect(mFileSystemModel, SIGNAL(directoryLoaded(const QString &)),
            this, SLOT(directoryLoaded(const QString &)));
}

FileBrowserWidget::~FileBrowserWidget()
{
    delete mFileSystemModel;
}

void FileBrowserWidget::loadSettings(const QSettings &pSettings,
                                     const QString &pKey)
{
    // Retrieve the width of each column

    QString columnWidthKey;

    for (int i = 0; i < header()->count(); ++i) {
        columnWidthKey = pKey+SettingsColumnWidth+QString::number(i);

        mNeedDefColWidth =     mNeedDefColWidth
                           && !pSettings.contains(columnWidthKey);

        setColumnWidth(i, pSettings.value(columnWidthKey,
                                          columnWidth(i)).toInt());
    }

    // Retrieve the sorting information

    sortByColumn(pSettings.value(pKey+SettingsSortColumn, 0).toInt(),
                 Qt::SortOrder(pSettings.value(pKey+SettingsSortOrder,
                                               Qt::AscendingOrder).toInt()));

    // Retrieve the initial path

    mInitPath = pSettings.value(pKey+SettingsInitialPath,
                                QDir::homePath()).toString();

    QFileInfo initPathFileInfo = mInitPath;

    if (!initPathFileInfo.exists()) {
        // The initial path doesn't exist, so just revert to the home path

        mInitPathDir = QDir::homePath();
        mInitPath    = "";
    } else {
        // The initial path exists, so retrieve some information about the
        // folder and/or file (depending on whether the initial path refers to
        // a file or not)
        // Note: indeed, should mInitPath refer to a file, then to directly set
        //       the current index of the tree view to that of a file won't give
        //       us the expected behaviour (i.e. the parent folder being open
        //       and expanded, and the file selected), so instead one must set
        //       the current index to that of the parent folder and then select
        //       the file

        if (initPathFileInfo.isDir()) {
            // We are dealing with a folder, so...

            mInitPathDir = initPathFileInfo.canonicalFilePath();
            mInitPath    = "";
        } else {
            // We are dealing with a file, so...

            mInitPathDir = initPathFileInfo.canonicalPath();
            mInitPath    = initPathFileInfo.canonicalFilePath();
        }
    }

    // Set the current index to that of the folder (and file, if it exists) we
    // are interested in
    // Note: this will result in the directoryLoaded signal to be emitted and,
    //       us, to take advantage of it to scroll to the right directory/file

    setCurrentIndex(mFileSystemModel->index(mInitPathDir));

    if (!mInitPath.isEmpty())
        // The initial path is that of a file, so...

        setCurrentIndex(mFileSystemModel->index(mInitPath));
}

void FileBrowserWidget::saveSettings(QSettings &pSettings, const QString &pKey)
{
    // Retrieve the width of each column

    for (int i = 0; i < header()->count(); ++i)
        pSettings.setValue(pKey+SettingsColumnWidth+QString::number(i),
                           columnWidth(i));

    // Keep track of the sorting information

    pSettings.setValue(pKey+SettingsSortColumn,
                       header()->sortIndicatorSection());
    pSettings.setValue(pKey+SettingsSortOrder, header()->sortIndicatorOrder());

    // Keep track of what will be our future initial folder/file path

    pSettings.setValue(pKey+SettingsInitialPath,
                       mFileSystemModel->filePath(currentIndex()));
}

QSize FileBrowserWidget::sizeHint() const
{
    // Suggest a default size for the file browser widget
    // Note: this is critical if we want a docked widget, with a file browser
    //       widget on it, to have a decent size when docked to the main window

    return defaultSize(0.15);
}

bool FileBrowserWidget::viewportEvent(QEvent *pEvent)
{
    if (pEvent->type() == QEvent::ToolTip) {
        // We need to show a tool tip, so make sure that it's up to date by
        // setting it to the file path of the current item

        QHelpEvent *helpEvent = static_cast<QHelpEvent *>(pEvent);

        setToolTip(QDir::toNativeSeparators(mFileSystemModel->filePath(indexAt(QPoint(helpEvent->x(),
                                                                                helpEvent->y())))));
    }

    // Default handling of the event

    return QTreeView::viewportEvent(pEvent);
}

void FileBrowserWidget::mousePressEvent(QMouseEvent *pEvent)
{
    if (pEvent->button() == Qt::RightButton)
        // We are pressing the right mouse button which may be used to display a
        // context menu and we don't want the row beneath the mouse to be
        // selected (in case it isn't already), so...

        pEvent->accept();
    else
        // We are not pressing the right mouse button, so carry on with the
        // default handling of the event

        QTreeView::mousePressEvent(pEvent);
}

void FileBrowserWidget::directoryLoaded(const QString &pPath)
{
    static bool needInitializing = true;

    if (needInitializing
        && (   ( mInitPath.isEmpty() && mInitPathDir.contains(pPath))
            || (!mInitPath.isEmpty() && mInitPath.contains(pPath)))) {
        // mFileSystemModel is still loading the initial path, so we try to
        // expand it and scroll to it, but first we process any pending event
        // (indeed, Windows doesn't need this, but Linux and Mac OS X definitely
        // do and it can't harm having it for all three environments, so...)

        qApp->processEvents();

        QModelIndex initPathDirModelIndex = mFileSystemModel->index(mInitPathDir);

        setExpanded(initPathDirModelIndex, true);
        scrollTo(initPathDirModelIndex);

        if (!mInitPath.isEmpty()) {
            // The initial path is that of a file and it exists, so select it

            QModelIndex initPathModelIndex = mFileSystemModel->index(mInitPath);

            setExpanded(initPathModelIndex, true);
            scrollTo(initPathModelIndex);
        }

        // Set the default width of the columns so that it fits their contents

        if (mNeedDefColWidth) {
            header()->setResizeMode(QHeaderView::ResizeToContents);

            qApp->processEvents();
            // Note: this ensures that the columns actually get resized

            header()->setResizeMode(QHeaderView::Interactive);
        }
    } else {
        // We are done initializing, so...

        needInitializing = false;
    }
}

void FileBrowserWidget::showCurrentPath()
{
    // Show the current path by scrolling to it

    scrollTo(currentIndex());
}

bool FileBrowserWidget::gotoPath(const QString &pPath, const bool &pExpand)
{
    // Set the current index to that of the provided path

    QModelIndex pathModelIndex = mFileSystemModel->index(pPath);

    if (pathModelIndex != QModelIndex()) {
        // The path exists, so we can go to it

        setCurrentIndex(pathModelIndex);

        if (pExpand)
            setExpanded(pathModelIndex, true);

        scrollTo(pathModelIndex);

        return true;
    } else {
        // The path doesn't exist, so...

        return false;
    }
}

QString FileBrowserWidget::homeFolder()
{
    // Return the path to the home folder

    return QDir::homePath();
}

void FileBrowserWidget::gotoHomeFolder(const bool &pExpand)
{
    // Go to the home folder

    gotoPath(QDir::homePath(), pExpand);
}

QString FileBrowserWidget::currentPath()
{
    // Return the current path

    return mFileSystemModel->filePath(currentIndex());
}

QString FileBrowserWidget::currentPathDir()
{
    // Return the directory of the current path

    QString crtIndexPath  = mFileSystemModel->filePath(currentIndex());
    QFileInfo crtIndexFileInfo  = crtIndexPath;

    return crtIndexFileInfo.isDir()?
               crtIndexPath:
               crtIndexFileInfo.dir().canonicalPath();
}

QString FileBrowserWidget::currentPathParent()
{
    // Return the current path parent, if any

    QModelIndex crtIndexParent = currentIndex().parent();

    return (crtIndexParent != QModelIndex())?
               mFileSystemModel->filePath(crtIndexParent):
               "";
}

bool FileBrowserWidget::isCurrentPathVisible()
{
    // Return whether the current path is visible or not, i.e. whether all of
    // the parent nodes are expanded or not

    bool result = true;
    QModelIndex crtIndex = currentIndex();

    while (result && (crtIndex.parent() != QModelIndex())) {
        crtIndex = crtIndex.parent();

        if (!isExpanded(crtIndex))
            // The current parent is not expanded, meaning the current path
            // cannot be visible, so...

            result = false;
    }

    return result;
}

bool FileBrowserWidget::isCurrentPathDirWritable()
{
    // Return whether the directory of the current path is writable or not

    return QFileInfo(currentPathDir()).isWritable();
}

bool FileBrowserWidget::isCurrentPathWritable()
{
    // Return whether the current path is writable or not

    return QFileInfo(currentPath()).isWritable();
}
<|endoftext|>


<commit_before>/*++
 Copyright (c) 2015 Microsoft Corporation

 Module Name:

  model_constructor.cpp

 Abstract:

 Author:

 Mikolas Janota

 Revision History:
--*/
#include"lackr_model_constructor.h"
#include"model_evaluator.h"
#include"ast_smt2_pp.h"
#include"ackr_info.h"
#include"for_each_expr.h"
#include"bv_rewriter.h"
#include"bool_rewriter.h"

struct lackr_model_constructor::imp {
    public:
        imp(ast_manager & m,
            ackr_info_ref info,
            model_ref & abstr_model,
            conflict_list & conflicts)
            : m_m(m)
            , m_info(info)
            , m_abstr_model(abstr_model)
            , m_conflicts(conflicts)
            , m_b_rw(m)
            , m_bv_rw(m)
            , m_empty_model(m)
            , m_ackr_helper(m)
        {}

        ~imp() {
            {
                values2val_t::iterator i = m_values2val.begin();
                const values2val_t::iterator e = m_values2val.end();
                for (; i != e; ++i) {
                    m_m.dec_ref(i->m_key);
                    m_m.dec_ref(i->m_value.value);
                    m_m.dec_ref(i->m_value.source_term);
                }
            }
            {
                app2val_t::iterator i = m_app2val.begin();
                const app2val_t::iterator e = m_app2val.end();
                for (; i != e; ++i) {
                    m_m.dec_ref(i->m_value);
                    m_m.dec_ref(i->m_key);
                }
            }
        }

        //
        // Returns true iff model was successfully constructed.
        // Conflicts are saved as a side effect.
        //
        bool check() {
            bool retv = true;
            for (unsigned i = 0; i < m_abstr_model->get_num_constants(); i++) {
                func_decl * const c = m_abstr_model->get_constant(i);
                app * const  _term = m_info->find_term(c);
                expr * const term  = _term ? _term : m_m.mk_const(c);
                if (!check_term(term)) retv = false;
            }
            return retv;
        }

        void make_model(model_ref& destination) {
            {
                for (unsigned i = 0; i < m_abstr_model->get_num_uninterpreted_sorts(); i++) {
                    sort * const s = m_abstr_model->get_uninterpreted_sort(i);
                    ptr_vector<expr> u = m_abstr_model->get_universe(s);
                    destination->register_usort(s, u.size(), u.c_ptr());
                }
            }
            for (unsigned i = 0; i < m_abstr_model->get_num_functions(); i++) {
                func_decl * const fd = m_abstr_model->get_function(i);
                func_interp * const fi = m_abstr_model->get_func_interp(fd);
                destination->register_decl(fd, fi);
            }

            {
                const app2val_t::iterator e = m_app2val.end();
                app2val_t::iterator i = m_app2val.end();
                for (; i != e; ++i) {
                    app * a = i->m_key;
                    if (a->get_num_args()) continue;
                    destination->register_decl(a->get_decl(), i->m_value);
                }
            }

            obj_map<func_decl, func_interp*> interpretations;
            {
                const values2val_t::iterator e = m_values2val.end();
                values2val_t::iterator i = m_values2val.end();
                for (; i != e; ++i) add_entry(i->m_key, i->m_value.value, interpretations);
            }

            {
                obj_map<func_decl, func_interp*>::iterator ie = interpretations.end();
                obj_map<func_decl, func_interp*>::iterator ii = interpretations.begin();
                for (; ii != ie; ++ii) {
                    func_decl* const fd = ii->m_key;
                    func_interp* const fi = ii->get_value();
                    fi->set_else(m_m.get_some_value(fd->get_range()));
                    destination->register_decl(fd, fi);
                }
            }
        }

        void add_entry(app* term, expr* value,
            obj_map<func_decl, func_interp*>& interpretations) {
            func_interp* fi = 0;
            func_decl * const declaration = term->get_decl();
            const unsigned sz = declaration->get_arity();
            SASSERT(sz == term->get_num_args());
            if (!interpretations.find(declaration, fi)) {
                fi = alloc(func_interp, m_m, sz);
                interpretations.insert(declaration, fi);
            }
            fi->insert_new_entry(term->get_args(), value);
        }
    private:
        ast_manager&                    m_m;
        ackr_info_ref                   m_info;
        model_ref&                      m_abstr_model;
        conflict_list&                  m_conflicts;
        bool_rewriter                   m_b_rw;
        bv_rewriter                     m_bv_rw;
        scoped_ptr<model_evaluator>     m_evaluator;
        model                           m_empty_model;
    private:
        struct val_info { expr * value; app * source_term; };
        typedef obj_map<app, expr *> app2val_t;
        typedef obj_map<app, val_info> values2val_t;
        values2val_t     m_values2val;
        app2val_t        m_app2val;
        ptr_vector<expr> m_stack;
        ackr_helper      m_ackr_helper;
        expr_mark        m_visited;

        static inline val_info mk_val_info(expr* value, app* source_term) {
            val_info rv;
            rv.value = value;
            rv.source_term = source_term;
            return rv;
        }

        // Performs congruence check on a given term.
        bool check_term(expr * term) {
            m_stack.push_back(term);
            const bool rv = _check_stack();
            m_stack.reset();
            return rv;
        }

        // Performs congruence check on terms on the stack.
        // Stops upon the first failure.
        // Returns true if and only if all congruence checks succeeded.
        bool _check_stack() {
            if (m_evaluator == NULL) m_evaluator = alloc(model_evaluator, m_empty_model);
            expr *  curr;
            while (!m_stack.empty()) {
                curr = m_stack.back();
                if (m_visited.is_marked(curr)) {
                    m_stack.pop_back();
                    continue;
                }

                switch (curr->get_kind()) {
                    case AST_VAR:
                        UNREACHABLE();
                        return false;
                    case AST_APP: {
                            app * a = to_app(curr);
                            if (for_each_expr_args(m_stack, m_visited, a->get_num_args(), a->get_args())) {
                                m_visited.mark(a, true);
                                m_stack.pop_back();
                                if (!mk_value(a)) return false;
                            }
                    }
                        break;
                    case AST_QUANTIFIER:
                        UNREACHABLE();
                        return false;
                    default:
                        UNREACHABLE();
                        return false;
                }
            }
            return true;
        }

        inline bool is_val(expr * e) { return m_m.is_value(e); }

        inline bool eval_cached(app * a, expr *& val) {
            if (is_val(a)) { val = a; return true; }
            return m_app2val.find(a, val);
        }

        bool evaluate(app * const a, expr_ref& result) {
            SASSERT(!is_val(a));
            const unsigned num = a->get_num_args();
            if (num == 0) { // handle constants
                make_value_constant(a, result);
                return true;
            }
            // evaluate arguments
            expr_ref_vector values(m_m);
            values.reserve(num);
            expr * const * args = a->get_args();
            for (unsigned i = 0; i < num; ++i) {
                expr * val;
                const bool b = eval_cached(to_app(args[i]), val); // TODO: OK conversion to_app?
                CTRACE("model_constructor", !b, tout << "fail arg val(\n" << mk_ismt2_pp(args[i], m_m, 2); );
                TRACE("model_constructor", tout <<
                    "arg val " << i << "(\n" << mk_ismt2_pp(args[i], m_m, 2)
                    << " : " << mk_ismt2_pp(val, m_m, 2) << '\n'; );
                SASSERT(b);
                values[i] = val;
            }
            // handle functions
            if (m_ackr_helper.should_ackermannize(a)) { // handle uninterpreted
                app_ref key(m_m.mk_app(a->get_decl(), values.c_ptr()), m_m);
                if (!make_value_uninterpreted_function(a, values, key.get(), result)) {
                    return false;
                }
            }
            else { // handle interpreted
                make_value_interpreted_function(a, values, result);
            }
            return true;
        }

        //
        // Check and record the value for a given term, given that all arguments are already checked.
        //
        bool mk_value(app * a) {
            if (is_val(a)) return true; // skip numerals
            TRACE("model_constructor", tout << "mk_value(\n" << mk_ismt2_pp(a, m_m, 2) << ")\n";);
            SASSERT(!m_app2val.contains(a));
            expr_ref result(m_m);
            if (!evaluate(a, result)) return false;
            SASSERT(is_val(result));
            TRACE("model_constructor",
                tout << "map term(\n" << mk_ismt2_pp(a, m_m, 2) << "\n->"
                << mk_ismt2_pp(result.get(), m_m, 2)<< ")\n"; );
            CTRACE("model_constructor",
                !is_val(result.get()),
                tout << "eval fail\n" << mk_ismt2_pp(a, m_m, 2) << mk_ismt2_pp(result, m_m, 2) << "\n";
            );
            SASSERT(is_val(result.get()));
            m_app2val.insert(a, result.get()); // memoize
            m_m.inc_ref(a);
            m_m.inc_ref(result.get());
            return true;
        }

        // Constants from the abstract model are directly mapped to the concrete one.
        void make_value_constant(app * const a, expr_ref& result) {
            SASSERT(a->get_num_args() == 0);
            func_decl * const fd = a->get_decl();
            expr * val = m_abstr_model->get_const_interp(fd);
            if (val == 0) { // TODO: avoid model completetion?
                sort * s = fd->get_range();
                val = m_abstr_model->get_some_value(s);
            }
            result = val;
        }

        bool make_value_uninterpreted_function(app* a,
                expr_ref_vector& values,
                app* key,
                expr_ref& result) {
            // get ackermann constant
            app * const ac = m_info->get_abstr(a);
            func_decl * const a_fd = a->get_decl();
            SASSERT(ac->get_num_args() == 0);
            SASSERT(a_fd->get_range() == ac->get_decl()->get_range());
            expr_ref value(m_m);
            value = m_abstr_model->get_const_interp(ac->get_decl());
            // get ackermann constant's interpretation
            if (value.get() == 0) { // TODO: avoid model completion?
                sort * s = a_fd->get_range();
                value = m_abstr_model->get_some_value(s);
            }
            // check congruence
            val_info vi;
            if(m_values2val.find(key,vi)) { // already is mapped to a value
                SASSERT(vi.source_term);
                const bool ok =  vi.value == value;
                if (!ok) {
                    TRACE("model_constructor",
                        tout << "already mapped by(\n" << mk_ismt2_pp(vi.source_term, m_m, 2) << "\n->"
                             << mk_ismt2_pp(vi.value, m_m, 2) << ")\n"; );
                    m_conflicts.push_back(std::make_pair(a, vi.source_term));
                }
                result = vi.value;
                return ok;
            } else {                        // new value
                result = value;
                vi.value = value;
                vi.source_term = a;
                m_values2val.insert(key,vi);
                m_m.inc_ref(vi.source_term);
                m_m.inc_ref(vi.value);
                m_m.inc_ref(key);
                return true;
            }
            UNREACHABLE();
            return true;
        }

        void make_value_interpreted_function(app* a,
                expr_ref_vector& values,
                expr_ref& result) {
            const unsigned num = values.size();
            func_decl * const fd = a->get_decl();
            const family_id fid = fd->get_family_id();
            expr_ref term(m_m);
            term = m_m.mk_app(a->get_decl(), num, values.c_ptr());
            m_evaluator->operator() (term, result);
            TRACE("model_constructor",
                tout << "eval(\n" << mk_ismt2_pp(term.get(), m_m, 2) << "\n->"
                << mk_ismt2_pp(result.get(), m_m, 2) << ")\n"; );
            return;
            if (fid == m_b_rw.get_fid()) {
                decl_kind k = fd->get_decl_kind();
                if (k == OP_EQ) {
                    // theory dispatch for =
                    SASSERT(num == 2);
                    family_id s_fid = m_m.get_sort(values.get(0))->get_family_id();
                    if (s_fid == m_bv_rw.get_fid())
                        m_bv_rw.mk_eq_core(values.get(0), values.get(1), result);
                } else {
                    m_b_rw.mk_app_core(fd, num, values.c_ptr(), result);
                }
            } else {
                if (fid == m_bv_rw.get_fid()) {
                    m_bv_rw.mk_app_core(fd, num, values.c_ptr(), result);
                }
                else {
                    UNREACHABLE();
                }
            }
        }
};

lackr_model_constructor::lackr_model_constructor(ast_manager& m, ackr_info_ref info)
    : m_imp(0)
    , m_m(m)
    , m_state(UNKNOWN)
    , m_info(info)
    , m_ref_count(0)
{}

lackr_model_constructor::~lackr_model_constructor() {
    if (m_imp) dealloc(m_imp);
}

bool lackr_model_constructor::check(model_ref& abstr_model) {
    m_conflicts.reset();
    if (m_imp) {
        dealloc(m_imp);
        m_imp = 0;
    }
    m_imp = alloc(lackr_model_constructor::imp, m_m, m_info, abstr_model, m_conflicts);
    const bool rv = m_imp->check();
    m_state = rv ? CHECKED : CONFLICT;
    return rv;
}

void lackr_model_constructor::make_model(model_ref& model) {
    SASSERT(m_state == CHECKED);
    m_imp->make_model(model);
}
<commit_msg>Fix in lackr_model_constructor.<commit_after>/*++
 Copyright (c) 2015 Microsoft Corporation

 Module Name:

  model_constructor.cpp

 Abstract:

 Author:

 Mikolas Janota

 Revision History:
--*/
#include"lackr_model_constructor.h"
#include"model_evaluator.h"
#include"ast_smt2_pp.h"
#include"ackr_info.h"
#include"for_each_expr.h"
#include"bv_rewriter.h"
#include"bool_rewriter.h"

struct lackr_model_constructor::imp {
    public:
        imp(ast_manager & m,
            ackr_info_ref info,
            model_ref & abstr_model,
            conflict_list & conflicts)
            : m_m(m)
            , m_info(info)
            , m_abstr_model(abstr_model)
            , m_conflicts(conflicts)
            , m_b_rw(m)
            , m_bv_rw(m)
            , m_evaluator(NULL)
            , m_empty_model(m)
            , m_ackr_helper(m)
        {}

        ~imp() {
            if (m_evaluator) dealloc(m_evaluator);
            {
                values2val_t::iterator i = m_values2val.begin();
                const values2val_t::iterator e = m_values2val.end();
                for (; i != e; ++i) {
                    m_m.dec_ref(i->m_key);
                    m_m.dec_ref(i->m_value.value);
                    m_m.dec_ref(i->m_value.source_term);
                }
            }
            {
                app2val_t::iterator i = m_app2val.begin();
                const app2val_t::iterator e = m_app2val.end();
                for (; i != e; ++i) {
                    m_m.dec_ref(i->m_value);
                    m_m.dec_ref(i->m_key);
                }
            }
        }

        //
        // Returns true iff model was successfully constructed.
        // Conflicts are saved as a side effect.
        //
        bool check() {
            bool retv = true;
            for (unsigned i = 0; i < m_abstr_model->get_num_constants(); i++) {
                func_decl * const c = m_abstr_model->get_constant(i);
                app * const  _term = m_info->find_term(c);
                expr * const term  = _term ? _term : m_m.mk_const(c);
                if (!check_term(term)) retv = false;
            }
            return retv;
        }

        void make_model(model_ref& destination) {
            {
                for (unsigned i = 0; i < m_abstr_model->get_num_uninterpreted_sorts(); i++) {
                    sort * const s = m_abstr_model->get_uninterpreted_sort(i);
                    ptr_vector<expr> u = m_abstr_model->get_universe(s);
                    destination->register_usort(s, u.size(), u.c_ptr());
                }
            }
            for (unsigned i = 0; i < m_abstr_model->get_num_functions(); i++) {
                func_decl * const fd = m_abstr_model->get_function(i);
                func_interp * const fi = m_abstr_model->get_func_interp(fd);
                destination->register_decl(fd, fi);
            }

            {
                const app2val_t::iterator e = m_app2val.end();
                app2val_t::iterator i = m_app2val.end();
                for (; i != e; ++i) {
                    app * a = i->m_key;
                    if (a->get_num_args()) continue;
                    destination->register_decl(a->get_decl(), i->m_value);
                }
            }

            obj_map<func_decl, func_interp*> interpretations;
            {
                const values2val_t::iterator e = m_values2val.end();
                values2val_t::iterator i = m_values2val.end();
                for (; i != e; ++i) add_entry(i->m_key, i->m_value.value, interpretations);
            }

            {
                obj_map<func_decl, func_interp*>::iterator ie = interpretations.end();
                obj_map<func_decl, func_interp*>::iterator ii = interpretations.begin();
                for (; ii != ie; ++ii) {
                    func_decl* const fd = ii->m_key;
                    func_interp* const fi = ii->get_value();
                    fi->set_else(m_m.get_some_value(fd->get_range()));
                    destination->register_decl(fd, fi);
                }
            }
        }

        void add_entry(app* term, expr* value,
            obj_map<func_decl, func_interp*>& interpretations) {
            func_interp* fi = 0;
            func_decl * const declaration = term->get_decl();
            const unsigned sz = declaration->get_arity();
            SASSERT(sz == term->get_num_args());
            if (!interpretations.find(declaration, fi)) {
                fi = alloc(func_interp, m_m, sz);
                interpretations.insert(declaration, fi);
            }
            fi->insert_new_entry(term->get_args(), value);
        }
    private:
        ast_manager&                    m_m;
        ackr_info_ref                   m_info;
        model_ref&                      m_abstr_model;
        conflict_list&                  m_conflicts;
        bool_rewriter                   m_b_rw;
        bv_rewriter                     m_bv_rw;
        model_evaluator *               m_evaluator;
        model                           m_empty_model;
    private:
        struct val_info { expr * value; app * source_term; };
        typedef obj_map<app, expr *> app2val_t;
        typedef obj_map<app, val_info> values2val_t;
        values2val_t     m_values2val;
        app2val_t        m_app2val;
        ptr_vector<expr> m_stack;
        ackr_helper      m_ackr_helper;
        expr_mark        m_visited;

        static inline val_info mk_val_info(expr* value, app* source_term) {
            val_info rv;
            rv.value = value;
            rv.source_term = source_term;
            return rv;
        }

        // Performs congruence check on a given term.
        bool check_term(expr * term) {
            m_stack.push_back(term);
            const bool rv = _check_stack();
            m_stack.reset();
            return rv;
        }

        // Performs congruence check on terms on the stack.
        // Stops upon the first failure.
        // Returns true if and only if all congruence checks succeeded.
        bool _check_stack() {
            if (m_evaluator == NULL) m_evaluator = alloc(model_evaluator, m_empty_model);
            expr *  curr;
            while (!m_stack.empty()) {
                curr = m_stack.back();
                if (m_visited.is_marked(curr)) {
                    m_stack.pop_back();
                    continue;
                }

                switch (curr->get_kind()) {
                    case AST_VAR:
                        UNREACHABLE();
                        return false;
                    case AST_APP: {
                            app * a = to_app(curr);
                            if (for_each_expr_args(m_stack, m_visited, a->get_num_args(), a->get_args())) {
                                m_visited.mark(a, true);
                                m_stack.pop_back();
                                if (!mk_value(a)) return false;
                            }
                    }
                        break;
                    case AST_QUANTIFIER:
                        UNREACHABLE();
                        return false;
                    default:
                        UNREACHABLE();
                        return false;
                }
            }
            return true;
        }

        inline bool is_val(expr * e) { return m_m.is_value(e); }

        inline bool eval_cached(app * a, expr *& val) {
            if (is_val(a)) { val = a; return true; }
            return m_app2val.find(a, val);
        }

        bool evaluate(app * const a, expr_ref& result) {
            SASSERT(!is_val(a));
            const unsigned num = a->get_num_args();
            if (num == 0) { // handle constants
                make_value_constant(a, result);
                return true;
            }
            // evaluate arguments
            expr_ref_vector values(m_m);
            values.reserve(num);
            expr * const * args = a->get_args();
            for (unsigned i = 0; i < num; ++i) {
                expr * val;
                const bool b = eval_cached(to_app(args[i]), val); // TODO: OK conversion to_app?
                CTRACE("model_constructor", m_conflicts.empty() && !b, tout << "fail arg val(\n" << mk_ismt2_pp(args[i], m_m, 2) << '\n'; );
                if (!b) {
                    // bailing out because args eval failed previously
                    return false;
                }
                TRACE("model_constructor", tout <<
                    "arg val " << i << "(\n" << mk_ismt2_pp(args[i], m_m, 2)
                    << " : " << mk_ismt2_pp(val, m_m, 2) << '\n'; );
                SASSERT(b);
                values[i] = val;
            }
            // handle functions
            if (m_ackr_helper.should_ackermannize(a)) { // handle uninterpreted
                app_ref key(m_m.mk_app(a->get_decl(), values.c_ptr()), m_m);
                if (!make_value_uninterpreted_function(a, values, key.get(), result)) {
                    return false;
                }
            }
            else { // handle interpreted
                make_value_interpreted_function(a, values, result);
            }
            return true;
        }

        //
        // Check and record the value for a given term, given that all arguments are already checked.
        //
        bool mk_value(app * a) {
            if (is_val(a)) return true; // skip numerals
            TRACE("model_constructor", tout << "mk_value(\n" << mk_ismt2_pp(a, m_m, 2) << ")\n";);
            SASSERT(!m_app2val.contains(a));
            expr_ref result(m_m);
            if (!evaluate(a, result)) return false;
            SASSERT(is_val(result));
            TRACE("model_constructor",
                tout << "map term(\n" << mk_ismt2_pp(a, m_m, 2) << "\n->"
                << mk_ismt2_pp(result.get(), m_m, 2)<< ")\n"; );
            CTRACE("model_constructor",
                !is_val(result.get()),
                tout << "eval fail\n" << mk_ismt2_pp(a, m_m, 2) << mk_ismt2_pp(result, m_m, 2) << "\n";
            );
            SASSERT(is_val(result.get()));
            m_app2val.insert(a, result.get()); // memoize
            m_m.inc_ref(a);
            m_m.inc_ref(result.get());
            return true;
        }

        // Constants from the abstract model are directly mapped to the concrete one.
        void make_value_constant(app * const a, expr_ref& result) {
            SASSERT(a->get_num_args() == 0);
            func_decl * const fd = a->get_decl();
            expr * val = m_abstr_model->get_const_interp(fd);
            if (val == 0) { // TODO: avoid model completetion?
                sort * s = fd->get_range();
                val = m_abstr_model->get_some_value(s);
            }
            result = val;
        }

        bool make_value_uninterpreted_function(app* a,
                expr_ref_vector& values,
                app* key,
                expr_ref& result) {
            // get ackermann constant
            app * const ac = m_info->get_abstr(a);
            func_decl * const a_fd = a->get_decl();
            SASSERT(ac->get_num_args() == 0);
            SASSERT(a_fd->get_range() == ac->get_decl()->get_range());
            expr_ref value(m_m);
            value = m_abstr_model->get_const_interp(ac->get_decl());
            // get ackermann constant's interpretation
            if (value.get() == 0) { // TODO: avoid model completion?
                sort * s = a_fd->get_range();
                value = m_abstr_model->get_some_value(s);
            }
            // check congruence
            val_info vi;
            if(m_values2val.find(key,vi)) { // already is mapped to a value
                SASSERT(vi.source_term);
                const bool ok =  vi.value == value;
                if (!ok) {
                    TRACE("model_constructor",
                        tout << "already mapped by(\n" << mk_ismt2_pp(vi.source_term, m_m, 2) << "\n->"
                             << mk_ismt2_pp(vi.value, m_m, 2) << ")\n"; );
                    m_conflicts.push_back(std::make_pair(a, vi.source_term));
                }
                result = vi.value;
                return ok;
            } else {                        // new value
                result = value;
                vi.value = value;
                vi.source_term = a;
                m_values2val.insert(key,vi);
                m_m.inc_ref(vi.source_term);
                m_m.inc_ref(vi.value);
                m_m.inc_ref(key);
                return true;
            }
            UNREACHABLE();
            return true;
        }

        void make_value_interpreted_function(app* a,
                expr_ref_vector& values,
                expr_ref& result) {
            const unsigned num = values.size();
            func_decl * const fd = a->get_decl();
            const family_id fid = fd->get_family_id();
            expr_ref term(m_m);
            term = m_m.mk_app(a->get_decl(), num, values.c_ptr());
            m_evaluator->operator() (term, result);
            TRACE("model_constructor",
                tout << "eval(\n" << mk_ismt2_pp(term.get(), m_m, 2) << "\n->"
                << mk_ismt2_pp(result.get(), m_m, 2) << ")\n"; );
            return;
            if (fid == m_b_rw.get_fid()) {
                decl_kind k = fd->get_decl_kind();
                if (k == OP_EQ) {
                    // theory dispatch for =
                    SASSERT(num == 2);
                    family_id s_fid = m_m.get_sort(values.get(0))->get_family_id();
                    if (s_fid == m_bv_rw.get_fid())
                        m_bv_rw.mk_eq_core(values.get(0), values.get(1), result);
                } else {
                    m_b_rw.mk_app_core(fd, num, values.c_ptr(), result);
                }
            } else {
                if (fid == m_bv_rw.get_fid()) {
                    m_bv_rw.mk_app_core(fd, num, values.c_ptr(), result);
                }
                else {
                    UNREACHABLE();
                }
            }
        }
};

lackr_model_constructor::lackr_model_constructor(ast_manager& m, ackr_info_ref info)
    : m_imp(0)
    , m_m(m)
    , m_state(UNKNOWN)
    , m_info(info)
    , m_ref_count(0)
{}

lackr_model_constructor::~lackr_model_constructor() {
    if (m_imp) dealloc(m_imp);
}

bool lackr_model_constructor::check(model_ref& abstr_model) {
    m_conflicts.reset();
    if (m_imp) {
        dealloc(m_imp);
        m_imp = 0;
    }
    m_imp = alloc(lackr_model_constructor::imp, m_m, m_info, abstr_model, m_conflicts);
    const bool rv = m_imp->check();
    m_state = rv ? CHECKED : CONFLICT;
    return rv;
}

void lackr_model_constructor::make_model(model_ref& model) {
    SASSERT(m_state == CHECKED);
    m_imp->make_model(model);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: remote.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: svesik $ $Date: 2004-04-21 13:43:58 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#if OSL_DEBUG_LEVEL == 0
#  ifndef NDEBUG
#    define NDEBUG
#  endif
#endif
#include <assert.h>
#include <bridges/remote/remote.hxx>
#include <bridges/remote/counter.hxx>

#if OSL_DEBUG_LEVEL > 1
static MyCounter thisCounter( "DEBUG : Remote2RemoteStub");
#endif

namespace bridges_remote {

Remote2RemoteStub::Remote2RemoteStub( rtl_uString *pOid,
                                      typelib_InterfaceTypeDescription *pType,
                                      uno_Environment *pEnvRemote,
                                      requestClientSideDispatcher dispatch ) :
    m_sOid( pOid ),
    m_pType( (typelib_InterfaceTypeDescription * ) pType ),
    m_nRef( 1 ),
    m_pEnvRemote( pEnvRemote ),
    m_dispatch( dispatch ),
    m_nReleaseRemote( 1 )
{
    typelib_typedescription_acquire( ( typelib_TypeDescription * ) m_pType );
    m_pEnvRemote->acquire( m_pEnvRemote );

    acquire = thisAcquire;
    release = thisRelease;
    pDispatcher = thisDispatch;
#if OSL_DEBUG_LEVEL > 1
    thisCounter.acquire();
#endif
}

Remote2RemoteStub::~Remote2RemoteStub()
{

    // send a release via the connection !
    sal_Bool bNeedsRelease = sal_False;
    if( ! m_pType->aBase.bComplete )
    {
        // m_pType may be exchanged during complete, so it needs to be acquired
        // (MT : Another thread may use m_pType during e.g. dispatch ! ).
        typelib_typedescription_acquire( (typelib_TypeDescription*)m_pType );
        bNeedsRelease = sal_True;
        typelib_typedescription_complete( (typelib_TypeDescription **) &m_pType );
    }

    uno_Any any;
    uno_Any *pAny = &any;

    typelib_TypeDescription *pReleaseMethod = 0;
    typelib_typedescriptionreference_getDescription(
        &pReleaseMethod ,
        m_pType->ppAllMembers[REMOTE_RELEASE_METHOD_INDEX] );
    for( int i = 0 ; i < m_nReleaseRemote ; i ++ )
    {
        thisDispatch( this,
                      pReleaseMethod,
                      0,
                      0,
                      &pAny );
    }
    typelib_typedescription_release( pReleaseMethod );
    if( bNeedsRelease )
    {
        typelib_typedescription_release( (typelib_TypeDescription * ) m_pType );
    }

    typelib_typedescription_release( (typelib_TypeDescription * ) m_pType );
    m_pEnvRemote->release( m_pEnvRemote );
#if OSL_DEBUG_LEVEL > 1
    thisCounter.release();
#endif
}

void Remote2RemoteStub::thisFree( uno_ExtEnvironment *pEnvUno , void *pThis )
{
    delete (Remote2RemoteStub *) pThis;
}
void Remote2RemoteStub::releaseRemote()
{
    osl_incrementInterlockedCount( &m_nReleaseRemote );
}

void Remote2RemoteStub::thisAcquire( remote_Interface *pThis )
{
    Remote2RemoteStub *p = ( Remote2RemoteStub * ) pThis;
    if( 1 == osl_incrementInterlockedCount( &(p->m_nRef) ) )
    {
        p->m_pEnvRemote->pExtEnv->registerProxyInterface(
            p->m_pEnvRemote->pExtEnv,
            (void**)&pThis,
            Remote2RemoteStub::thisFree,
            p->m_sOid.pData,
            p->m_pType );
        assert( (remote_Interface *)p == pThis );
    }
}

void Remote2RemoteStub::thisRelease( remote_Interface *pThis )
{
    Remote2RemoteStub *p = ( Remote2RemoteStub * ) pThis;
     if (! osl_decrementInterlockedCount( &(p->m_nRef) ))
    {
        p->m_pEnvRemote->pExtEnv->revokeInterface( p->m_pEnvRemote->pExtEnv, pThis );

    }
}

void Remote2RemoteStub::thisDispatch(
    remote_Interface * pRemoteI,
    typelib_TypeDescription * pMemberType,
    void * pReturn,
    void * pArgs[],
    uno_Any ** ppException )
{
    Remote2RemoteStub *pThis = ( Remote2RemoteStub * ) pRemoteI;

    pThis->m_dispatch( pThis->m_pEnvRemote,
                       pMemberType,
                       pThis->m_sOid.pData,
                       pThis->m_pType,
                       pReturn,
                       pArgs,
                       ppException );
}

} // end namespace bridges_remote
<commit_msg>INTEGRATION: CWS ooo19126 (1.6.86); FILE MERGED 2005/09/05 17:07:50 rt 1.6.86.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: remote.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 22:43:30 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#if OSL_DEBUG_LEVEL == 0
#  ifndef NDEBUG
#    define NDEBUG
#  endif
#endif
#include <assert.h>
#include <bridges/remote/remote.hxx>
#include <bridges/remote/counter.hxx>

#if OSL_DEBUG_LEVEL > 1
static MyCounter thisCounter( "DEBUG : Remote2RemoteStub");
#endif

namespace bridges_remote {

Remote2RemoteStub::Remote2RemoteStub( rtl_uString *pOid,
                                      typelib_InterfaceTypeDescription *pType,
                                      uno_Environment *pEnvRemote,
                                      requestClientSideDispatcher dispatch ) :
    m_sOid( pOid ),
    m_pType( (typelib_InterfaceTypeDescription * ) pType ),
    m_nRef( 1 ),
    m_pEnvRemote( pEnvRemote ),
    m_dispatch( dispatch ),
    m_nReleaseRemote( 1 )
{
    typelib_typedescription_acquire( ( typelib_TypeDescription * ) m_pType );
    m_pEnvRemote->acquire( m_pEnvRemote );

    acquire = thisAcquire;
    release = thisRelease;
    pDispatcher = thisDispatch;
#if OSL_DEBUG_LEVEL > 1
    thisCounter.acquire();
#endif
}

Remote2RemoteStub::~Remote2RemoteStub()
{

    // send a release via the connection !
    sal_Bool bNeedsRelease = sal_False;
    if( ! m_pType->aBase.bComplete )
    {
        // m_pType may be exchanged during complete, so it needs to be acquired
        // (MT : Another thread may use m_pType during e.g. dispatch ! ).
        typelib_typedescription_acquire( (typelib_TypeDescription*)m_pType );
        bNeedsRelease = sal_True;
        typelib_typedescription_complete( (typelib_TypeDescription **) &m_pType );
    }

    uno_Any any;
    uno_Any *pAny = &any;

    typelib_TypeDescription *pReleaseMethod = 0;
    typelib_typedescriptionreference_getDescription(
        &pReleaseMethod ,
        m_pType->ppAllMembers[REMOTE_RELEASE_METHOD_INDEX] );
    for( int i = 0 ; i < m_nReleaseRemote ; i ++ )
    {
        thisDispatch( this,
                      pReleaseMethod,
                      0,
                      0,
                      &pAny );
    }
    typelib_typedescription_release( pReleaseMethod );
    if( bNeedsRelease )
    {
        typelib_typedescription_release( (typelib_TypeDescription * ) m_pType );
    }

    typelib_typedescription_release( (typelib_TypeDescription * ) m_pType );
    m_pEnvRemote->release( m_pEnvRemote );
#if OSL_DEBUG_LEVEL > 1
    thisCounter.release();
#endif
}

void Remote2RemoteStub::thisFree( uno_ExtEnvironment *pEnvUno , void *pThis )
{
    delete (Remote2RemoteStub *) pThis;
}
void Remote2RemoteStub::releaseRemote()
{
    osl_incrementInterlockedCount( &m_nReleaseRemote );
}

void Remote2RemoteStub::thisAcquire( remote_Interface *pThis )
{
    Remote2RemoteStub *p = ( Remote2RemoteStub * ) pThis;
    if( 1 == osl_incrementInterlockedCount( &(p->m_nRef) ) )
    {
        p->m_pEnvRemote->pExtEnv->registerProxyInterface(
            p->m_pEnvRemote->pExtEnv,
            (void**)&pThis,
            Remote2RemoteStub::thisFree,
            p->m_sOid.pData,
            p->m_pType );
        assert( (remote_Interface *)p == pThis );
    }
}

void Remote2RemoteStub::thisRelease( remote_Interface *pThis )
{
    Remote2RemoteStub *p = ( Remote2RemoteStub * ) pThis;
     if (! osl_decrementInterlockedCount( &(p->m_nRef) ))
    {
        p->m_pEnvRemote->pExtEnv->revokeInterface( p->m_pEnvRemote->pExtEnv, pThis );

    }
}

void Remote2RemoteStub::thisDispatch(
    remote_Interface * pRemoteI,
    typelib_TypeDescription * pMemberType,
    void * pReturn,
    void * pArgs[],
    uno_Any ** ppException )
{
    Remote2RemoteStub *pThis = ( Remote2RemoteStub * ) pRemoteI;

    pThis->m_dispatch( pThis->m_pEnvRemote,
                       pMemberType,
                       pThis->m_sOid.pData,
                       pThis->m_pType,
                       pReturn,
                       pArgs,
                       ppException );
}

} // end namespace bridges_remote
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// logger_workload.cpp
//
// Identification: src/backend/benchmark/logger/logger_workload.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <thread>
#include <string>
#include <getopt.h>
#include <sys/stat.h>

#undef NDEBUG

#include "backend/bridge/ddl/ddl_database.h"
#include "backend/concurrency/transaction_manager_factory.h"
#include "backend/common/value_factory.h"

#include "backend/common/exception.h"
#include "backend/common/logger.h"
#include "backend/common/timer.h"
#include "backend/logging/log_manager.h"

#include "backend/benchmark/logger/logger_workload.h"
#include "backend/benchmark/logger/logger_loader.h"
#include "backend/benchmark/ycsb/ycsb_workload.h"
#include "backend/benchmark/ycsb/ycsb_configuration.h"
#include "backend/benchmark/ycsb/ycsb_loader.h"

#include <unistd.h>

//===--------------------------------------------------------------------===//
// GUC Variables
//===--------------------------------------------------------------------===//

namespace peloton {
namespace benchmark {
namespace logger {

//===--------------------------------------------------------------------===//
// PREPARE LOG FILE
//===--------------------------------------------------------------------===//

//===--------------------------------------------------------------------===//
// 1. Standby -- Bootstrap
// 2. Recovery -- Optional
// 3. Logging -- Collect data and flush when commit
// 4. Terminate -- Collect any remaining data and flush
// 5. Sleep -- Disconnect backend loggers and frontend logger from manager
//===--------------------------------------------------------------------===//

#define LOGGING_TESTS_DATABASE_OID 20000
#define LOGGING_TESTS_TABLE_OID 10000

std::ofstream out("outputfile.summary");

size_t GetLogFileSize();

static void WriteOutput(double value) {
  LOG_INFO("----------------------------------------------------------");
  LOG_INFO("%d %d %lf %d %d %d %d %d %d %d %d :: %lf", state.benchmark_type,
           state.logging_type, ycsb::state.update_ratio,
           ycsb::state.backend_count, ycsb::state.scale_factor,
           ycsb::state.skew_factor, ycsb::state.duration, state.nvm_latency,
           state.pcommit_latency, state.flush_mode, state.asynchronous_mode,
           value);

  out << state.benchmark_type << " ";
  out << state.logging_type << " ";
  out << ycsb::state.update_ratio << " ";
  out << ycsb::state.scale_factor << " ";
  out << ycsb::state.backend_count << " ";
  out << ycsb::state.skew_factor << " ";
  out << ycsb::state.duration << " ";
  out << state.nvm_latency << " ";
  out << state.pcommit_latency << " ";
  out << state.flush_mode << " ";
  out << state.asynchronous_mode << " ";
  out << value << "\n";
  out.flush();
}

std::string GetFilePath(std::string directory_path, std::string file_name) {
  std::string file_path = directory_path;

  // Add a trailing slash to a file path if needed
  if (!file_path.empty() && file_path.back() != '/') file_path += '/';

  file_path += file_name;

  return file_path;
}

void StartLogging(std::thread& thread) {
  auto& log_manager = logging::LogManager::GetInstance();
  if (peloton_logging_mode != LOGGING_TYPE_INVALID) {
    // Launching a thread for logging
    if (!log_manager.IsInLoggingMode()) {

      // Wait for standby mode
      auto local_thread = std::thread(
          &peloton::logging::LogManager::StartStandbyMode, &log_manager);
      thread.swap(local_thread);
      log_manager.WaitForModeTransition(peloton::LOGGING_STATUS_TYPE_STANDBY,
                                        true);

      // Clean up database tile state before recovery from checkpoint
      log_manager.PrepareRecovery();

      // Do any recovery
      log_manager.StartRecoveryMode();

      // Wait for logging mode
      log_manager.WaitForModeTransition(peloton::LOGGING_STATUS_TYPE_LOGGING,
                                        true);

      // Done recovery
      log_manager.DoneRecovery();
    }
  }
}

/**
 * @brief writing a simple log file
 */
bool PrepareLogFile() {
  if (chdir(state.log_file_dir.c_str())) {
    LOG_ERROR("change directory failed");
  }

  // start a thread for logging
  auto& log_manager = logging::LogManager::GetInstance();
  log_manager.SetLogFileName("wbl.log");

  // truncate log file if it exists
  struct stat buffer;
  if (stat(log_manager.GetLogFileName().c_str(), &buffer) == 0 &&
      remove(log_manager.GetLogFileName().c_str()) != 0) {
    LOG_ERROR("Error removing old log file");
  }

  if (log_manager.ContainsFrontendLogger() == true) {
    LOG_ERROR("another logging thread is running now");
    return false;
  }

  // Pick sync commit mode
  switch (state.asynchronous_mode) {
    case ASYNCHRONOUS_TYPE_SYNC:
      log_manager.SetSyncCommit(true);
      break;

    case ASYNCHRONOUS_TYPE_ASYNC:
    case ASYNCHRONOUS_TYPE_DISABLED:
      log_manager.SetSyncCommit(false);
      break;

    case ASYNCHRONOUS_TYPE_INVALID:
      throw Exception("Invalid asynchronous mode : " +
                      std::to_string(state.asynchronous_mode));
  }

  // Get an instance of the storage manager to force posix_fallocate
  // to be invoked before we begin benchmarking
  auto& storage_manager = storage::StorageManager::GetInstance();
  auto tmp = storage_manager.Allocate(BACKEND_TYPE_MM, 1024);
  storage_manager.Release(BACKEND_TYPE_MM, tmp);

  Timer<> timer;
  std::thread thread;

  if (peloton_logging_mode != LOGGING_TYPE_INVALID) {
    // Launching a thread for logging
    if (!log_manager.IsInLoggingMode()) {
      // Wait for standby mode
      auto local_thread = std::thread(
          &peloton::logging::LogManager::StartStandbyMode, &log_manager);
      thread.swap(local_thread);
      log_manager.WaitForModeTransition(peloton::LOGGING_STATUS_TYPE_STANDBY,
                                        true);

      // Clean up database tile state before recovery from checkpoint
      log_manager.PrepareRecovery();

      // Do any recovery
      log_manager.StartRecoveryMode();

      // Wait for logging mode
      log_manager.WaitForModeTransition(peloton::LOGGING_STATUS_TYPE_LOGGING,
                                        true);

      // Done recovery
      log_manager.DoneRecovery();
    }
  }

  timer.Start();

  // Build the log
  BuildLog();

  // Stop frontend logger if in a valid logging mode
  if (peloton_logging_mode != LOGGING_TYPE_INVALID) {
    //  Wait for the mode transition :: LOGGING -> TERMINATE -> SLEEP
    if (log_manager.EndLogging()) {
      thread.join();
    }
  }

  timer.Stop();

  // TODO: Pick YCSB or TPCC metrics based on benchmark type
  auto throughput = ycsb::state.throughput;
  auto latency = ycsb::state.latency;

  // Log the build log time
  if (state.experiment_type == EXPERIMENT_TYPE_INVALID ||
      state.experiment_type == EXPERIMENT_TYPE_THROUGHPUT) {
    WriteOutput(throughput);
  } else if (state.experiment_type == EXPERIMENT_TYPE_LATENCY) {
    WriteOutput(latency);
  } else if (state.experiment_type == EXPERIMENT_TYPE_STORAGE) {
    // TODO: Need to get more info -- in case of WAL: checkpoint size
    // in case of WBL: table size, index size ?
    auto log_file_size = GetLogFileSize();
    WriteOutput(log_file_size);
  }

  return true;
}

//===--------------------------------------------------------------------===//
// CHECK RECOVERY
//===--------------------------------------------------------------------===//

void ResetSystem() {
  // XXX Initialize oid since we assume that we restart the system

  auto& txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  txn_manager.ResetStates();
}

/**
 * @brief recover the database and check the tuples
 */
void DoRecovery(std::string file_name) {
  auto file_path = GetFilePath(state.log_file_dir, file_name);

  std::ifstream log_file(file_path);

  // Reset the log file if exists

  log_file.close();

  ycsb::CreateYCSBDatabase();

  //===--------------------------------------------------------------------===//
  // RECOVERY
  //===--------------------------------------------------------------------===//

  Timer<std::milli> timer;
  std::thread thread;

  timer.Start();

  auto& log_manager = peloton::logging::LogManager::GetInstance();
  log_manager.ResetLogStatus();
  log_manager.ResetFrontendLoggers();

  StartLogging(thread);

  if (log_manager.EndLogging()) {
    thread.join();
  } else {
    LOG_ERROR("Failed to terminate logging thread");
  }

  timer.Stop();

  // Recovery time (in ms)

  WriteOutput(timer.GetDuration());
}

//===--------------------------------------------------------------------===//
// WRITING LOG RECORD
//===--------------------------------------------------------------------===//

void BuildLog() {
  ycsb::CreateYCSBDatabase();

  ycsb::LoadYCSBDatabase();

  //===--------------------------------------------------------------------===//
  // ACTIVE PROCESSING
  //===--------------------------------------------------------------------===//
  ycsb::RunWorkload();
}

size_t GetLogFileSize() {
  struct stat log_stats;

  auto& log_manager = logging::LogManager::GetInstance();
  std::string log_file_name = log_manager.GetLogFileName();

  // open log file and file descriptor
  // we open it in append + binary mode
  auto log_file = fopen(log_file_name.c_str(), "r");
  if (log_file == NULL) {
    LOG_ERROR("LogFile is NULL");
  }

  // also, get the descriptor
  auto log_file_fd = fileno(log_file);
  if (log_file_fd == -1) {
    LOG_ERROR("log_file_fd is -1");
  }

  fstat(log_file_fd, &log_stats);
  auto log_file_size = log_stats.st_size;

  return log_file_size;
}

}  // namespace logger
}  // namespace benchmark
}  // namespace peloton
<commit_msg>clean up old logs at the beginning of each test<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// logger_workload.cpp
//
// Identification: src/backend/benchmark/logger/logger_workload.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <thread>
#include <string>
#include <getopt.h>
#include <sys/stat.h>
#include <fts.h>

#undef NDEBUG

#include "backend/bridge/ddl/ddl_database.h"
#include "backend/concurrency/transaction_manager_factory.h"
#include "backend/common/value_factory.h"

#include "backend/common/exception.h"
#include "backend/common/logger.h"
#include "backend/common/timer.h"
#include "backend/logging/log_manager.h"

#include "backend/benchmark/logger/logger_workload.h"
#include "backend/benchmark/logger/logger_loader.h"
#include "backend/benchmark/ycsb/ycsb_workload.h"
#include "backend/benchmark/ycsb/ycsb_configuration.h"
#include "backend/benchmark/ycsb/ycsb_loader.h"

#include <unistd.h>

//===--------------------------------------------------------------------===//
// GUC Variables
//===--------------------------------------------------------------------===//

namespace peloton {
namespace benchmark {
namespace logger {

//===--------------------------------------------------------------------===//
// PREPARE LOG FILE
//===--------------------------------------------------------------------===//

//===--------------------------------------------------------------------===//
// 1. Standby -- Bootstrap
// 2. Recovery -- Optional
// 3. Logging -- Collect data and flush when commit
// 4. Terminate -- Collect any remaining data and flush
// 5. Sleep -- Disconnect backend loggers and frontend logger from manager
//===--------------------------------------------------------------------===//

#define LOGGING_TESTS_DATABASE_OID 20000
#define LOGGING_TESTS_TABLE_OID 10000

std::ofstream out("outputfile.summary");

size_t GetLogFileSize();

static void WriteOutput(double value) {
  LOG_INFO("----------------------------------------------------------");
  LOG_INFO("%d %d %lf %d %d %d %d %d %d %d %d :: %lf", state.benchmark_type,
           state.logging_type, ycsb::state.update_ratio,
           ycsb::state.backend_count, ycsb::state.scale_factor,
           ycsb::state.skew_factor, ycsb::state.duration, state.nvm_latency,
           state.pcommit_latency, state.flush_mode, state.asynchronous_mode,
           value);

  out << state.benchmark_type << " ";
  out << state.logging_type << " ";
  out << ycsb::state.update_ratio << " ";
  out << ycsb::state.scale_factor << " ";
  out << ycsb::state.backend_count << " ";
  out << ycsb::state.skew_factor << " ";
  out << ycsb::state.duration << " ";
  out << state.nvm_latency << " ";
  out << state.pcommit_latency << " ";
  out << state.flush_mode << " ";
  out << state.asynchronous_mode << " ";
  out << value << "\n";
  out.flush();
}

std::string GetFilePath(std::string directory_path, std::string file_name) {
  std::string file_path = directory_path;

  // Add a trailing slash to a file path if needed
  if (!file_path.empty() && file_path.back() != '/') file_path += '/';

  file_path += file_name;

  return file_path;
}

void StartLogging(std::thread& thread) {
  auto& log_manager = logging::LogManager::GetInstance();
  if (peloton_logging_mode != LOGGING_TYPE_INVALID) {
    // Launching a thread for logging
    if (!log_manager.IsInLoggingMode()) {
      // Wait for standby mode
      auto local_thread = std::thread(
          &peloton::logging::LogManager::StartStandbyMode, &log_manager);
      thread.swap(local_thread);
      log_manager.WaitForModeTransition(peloton::LOGGING_STATUS_TYPE_STANDBY,
                                        true);

      // Clean up database tile state before recovery from checkpoint
      log_manager.PrepareRecovery();

      // Do any recovery
      log_manager.StartRecoveryMode();

      // Wait for logging mode
      log_manager.WaitForModeTransition(peloton::LOGGING_STATUS_TYPE_LOGGING,
                                        true);

      // Done recovery
      log_manager.DoneRecovery();
    }
  }
}

int recursive_delete(const char* dir) {
  int ret = 0;
  FTS* ftsp = NULL;
  FTSENT* curr;

  // Cast needed (in C) because fts_open() takes a "char * const *", instead
  // of a "const char * const *", which is only allowed in C++. fts_open()
  // does not modify the argument.
  char* files[] = {(char*)dir, NULL};

  // FTS_NOCHDIR  - Avoid changing cwd, which could cause unexpected behavior
  //                in multithreaded programs
  // FTS_PHYSICAL - Don't follow symlinks. Prevents deletion of files outside
  //                of the specified directory
  // FTS_XDEV     - Don't cross filesystem boundaries
  ftsp = fts_open(files, FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV, NULL);
  if (!ftsp) {
    fprintf(stderr, "%s: fts_open failed: %s\n", dir, strerror(errno));
    ret = -1;
    goto finish;
  }

  while ((curr = fts_read(ftsp))) {
    switch (curr->fts_info) {
      case FTS_NS:
      case FTS_DNR:
      case FTS_ERR:
        fprintf(stderr, "%s: fts_read error: %s\n", curr->fts_accpath,
                strerror(curr->fts_errno));
        break;

      case FTS_DC:
      case FTS_DOT:
      case FTS_NSOK:
        // Not reached unless FTS_LOGICAL, FTS_SEEDOT, or FTS_NOSTAT were
        // passed to fts_open()
        break;

      case FTS_D:
        // Do nothing. Need depth-first search, so directories are deleted
        // in FTS_DP
        break;

      case FTS_DP:
      case FTS_F:
      case FTS_SL:
      case FTS_SLNONE:
      case FTS_DEFAULT:
        if (remove(curr->fts_accpath) < 0) {
          fprintf(stderr, "%s: Failed to remove: %s\n", curr->fts_path,
                  strerror(errno));
          ret = -1;
        }
        break;
    }
  }

finish:
  if (ftsp) {
    fts_close(ftsp);
  }

  return ret;
}

void CleanUpOldLogs() {
  // start a thread for logging
  auto& log_manager = logging::LogManager::GetInstance();
  log_manager.SetLogFileName("wbl.log");

  // remove log file if it exists
  struct stat buffer;
  if (stat(log_manager.GetLogFileName().c_str(), &buffer) == 0 &&
      remove(log_manager.GetLogFileName().c_str()) != 0) {
    LOG_ERROR("Error removing old log file");
  }

  // remove log directory (for wal if it exists)
  // for now hardcode for 1 logger
  auto log_dir_name = "pl_log0";

  recursive_delete(log_dir_name);
}

/**
 * @brief writing a simple log file
 */
bool PrepareLogFile() {
  if (chdir(state.log_file_dir.c_str())) {
    LOG_ERROR("change directory failed");
  }

  // start a thread for logging
  auto& log_manager = logging::LogManager::GetInstance();
  log_manager.SetLogFileName("wbl.log");

  // also clean up log directory if it exists
  CleanUpOldLogs();

  if (log_manager.ContainsFrontendLogger() == true) {
    LOG_ERROR("another logging thread is running now");
    return false;
  }

  // Pick sync commit mode
  switch (state.asynchronous_mode) {
    case ASYNCHRONOUS_TYPE_SYNC:
      log_manager.SetSyncCommit(true);
      break;

    case ASYNCHRONOUS_TYPE_ASYNC:
    case ASYNCHRONOUS_TYPE_DISABLED:
      log_manager.SetSyncCommit(false);
      break;

    case ASYNCHRONOUS_TYPE_INVALID:
      throw Exception("Invalid asynchronous mode : " +
                      std::to_string(state.asynchronous_mode));
  }

  // Get an instance of the storage manager to force posix_fallocate
  // to be invoked before we begin benchmarking
  auto& storage_manager = storage::StorageManager::GetInstance();
  auto tmp = storage_manager.Allocate(BACKEND_TYPE_MM, 1024);
  storage_manager.Release(BACKEND_TYPE_MM, tmp);

  Timer<> timer;
  std::thread thread;

  StartLogging(thread);

  timer.Start();

  // Build the log
  BuildLog();

  // Stop frontend logger if in a valid logging mode
  if (peloton_logging_mode != LOGGING_TYPE_INVALID) {
    //  Wait for the mode transition :: LOGGING -> TERMINATE -> SLEEP
    if (log_manager.EndLogging()) {
      thread.join();
    }
  }

  timer.Stop();

  // TODO: Pick YCSB or TPCC metrics based on benchmark type
  auto throughput = ycsb::state.throughput;
  auto latency = ycsb::state.latency;

  // Log the build log time
  if (state.experiment_type == EXPERIMENT_TYPE_INVALID ||
      state.experiment_type == EXPERIMENT_TYPE_THROUGHPUT) {
    WriteOutput(throughput);
  } else if (state.experiment_type == EXPERIMENT_TYPE_LATENCY) {
    WriteOutput(latency);
  } else if (state.experiment_type == EXPERIMENT_TYPE_STORAGE) {
    // TODO: Need to get more info -- in case of WAL: checkpoint size
    // in case of WBL: table size, index size ?
    auto log_file_size = GetLogFileSize();
    WriteOutput(log_file_size);
  }

  return true;
}

//===--------------------------------------------------------------------===//
// CHECK RECOVERY
//===--------------------------------------------------------------------===//

void ResetSystem() {
  // XXX Initialize oid since we assume that we restart the system

  auto& txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  txn_manager.ResetStates();
}

/**
 * @brief recover the database and check the tuples
 */
void DoRecovery(std::string file_name) {
  auto file_path = GetFilePath(state.log_file_dir, file_name);

  std::ifstream log_file(file_path);

  // Reset the log file if exists

  log_file.close();

  ycsb::CreateYCSBDatabase();

  //===--------------------------------------------------------------------===//
  // RECOVERY
  //===--------------------------------------------------------------------===//

  Timer<std::milli> timer;
  std::thread thread;

  timer.Start();

  auto& log_manager = peloton::logging::LogManager::GetInstance();
  log_manager.ResetLogStatus();
  log_manager.ResetFrontendLoggers();

  StartLogging(thread);

  if (log_manager.EndLogging()) {
    thread.join();
  } else {
    LOG_ERROR("Failed to terminate logging thread");
  }

  timer.Stop();

  // Recovery time (in ms)

  WriteOutput(timer.GetDuration());
}

//===--------------------------------------------------------------------===//
// WRITING LOG RECORD
//===--------------------------------------------------------------------===//

void BuildLog() {
  ycsb::CreateYCSBDatabase();

  ycsb::LoadYCSBDatabase();

  //===--------------------------------------------------------------------===//
  // ACTIVE PROCESSING
  //===--------------------------------------------------------------------===//
  ycsb::RunWorkload();
}

size_t GetLogFileSize() {
  struct stat log_stats;

  auto& log_manager = logging::LogManager::GetInstance();
  std::string log_file_name = log_manager.GetLogFileName();

  // open log file and file descriptor
  // we open it in append + binary mode
  auto log_file = fopen(log_file_name.c_str(), "r");
  if (log_file == NULL) {
    LOG_ERROR("LogFile is NULL");
  }

  // also, get the descriptor
  auto log_file_fd = fileno(log_file);
  if (log_file_fd == -1) {
    LOG_ERROR("log_file_fd is -1");
  }

  fstat(log_file_fd, &log_stats);
  auto log_file_size = log_stats.st_size;

  return log_file_size;
}

}  // namespace logger
}  // namespace benchmark
}  // namespace peloton
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#if defined(HAVE_CAIRO)

// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/cairo/cairo_renderer.hpp>
#include <mapnik/cairo/cairo_render_vector.hpp>
#include <mapnik/renderer_common/render_pattern.hpp>
#include <mapnik/vertex_converters.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/renderer_common/clipping_extent.hpp>

namespace mapnik
{

struct cairo_renderer_process_visitor_p
{
    cairo_renderer_process_visitor_p(cairo_context & context,
                                   agg::trans_affine & image_tr,
                                   unsigned offset_x,
                                   unsigned offset_y,
                                   float opacity)
        : context_(context),
          image_tr_(image_tr),
          offset_x_(offset_x),
          offset_y_(offset_y),
          opacity_(opacity) {}

    void operator() (marker_null const&) {}

    void operator() (marker_svg const& marker)
    {
        mapnik::rasterizer ras;
        mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr_;
        mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
        render_pattern<image_rgba8>(ras, marker, image_tr_, 1.0, image);
        cairo_pattern pattern(image, opacity_);
        pattern.set_extend(CAIRO_EXTEND_REPEAT);
        pattern.set_origin(offset_x_, offset_y_);
        context_.set_pattern(pattern);
    }

    void operator() (marker_rgba8 const& marker)
    {
        cairo_pattern pattern(marker.get_data(), opacity_);
        pattern.set_extend(CAIRO_EXTEND_REPEAT);
        pattern.set_origin(offset_x_, offset_y_);
        context_.set_pattern(pattern);
    }

  private:
    cairo_context & context_;
    agg::trans_affine & image_tr_;
    unsigned offset_x_;
    unsigned offset_y_;
    float opacity_;
};

template <typename T>
void cairo_renderer<T>::process(polygon_pattern_symbolizer const& sym,
                                  mapnik::feature_impl & feature,
                                  proj_transform const& prj_trans)
{
    composite_mode_e comp_op = get<composite_mode_e, keys::comp_op>(sym, feature, common_.vars_);
    std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_);
    value_bool clip = get<value_bool, keys::clip>(sym, feature, common_.vars_);
    value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym, feature, common_.vars_);
    value_double smooth = get<value_double, keys::smooth>(sym, feature, common_.vars_);
    value_double opacity = get<value_double, keys::opacity>(sym, feature, common_.vars_);
    agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
    auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
    if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform);

    cairo_save_restore guard(context_);
    context_.set_operator(comp_op);

    mapnik::marker const& marker = mapnik::marker_cache::instance().find(filename,true);
    if (marker.is<mapnik::marker_null>()) return;

    unsigned offset_x=0;
    unsigned offset_y=0;
    box2d<double> const& clip_box = clipping_extent(common_);
    pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym, feature, common_.vars_);
    if (alignment == LOCAL_ALIGNMENT)
    {
        double x0 = 0.0;
        double y0 = 0.0;
// FIXME
#if 0
        if (feature.num_geometries() > 0)
        {
            using clipped_geometry_type = agg::conv_clip_polygon<vertex_adapter>;
            using path_type = transform_path_adapter<view_transform,clipped_geometry_type>;
            vertex_adapter va(feature.get_geometry(0));
            clipped_geometry_type clipped(va);
            clipped.clip_box(clip_box.minx(), clip_box.miny(),
                             clip_box.maxx(), clip_box.maxy());
            path_type path(common_.t_, clipped, prj_trans);
            path.vertex(&x0, &y0);
        }
        offset_x = std::abs(clip_box.width() - x0);
        offset_y = std::abs(clip_box.height() - y0);
#endif
    }

    util::apply_visitor(cairo_renderer_process_visitor_p(context_, image_tr, offset_x, offset_y, opacity), marker);

    agg::trans_affine tr;
    auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform);
    if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); }

    vertex_converter<cairo_context,clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag>
        converter(clip_box, context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);

    if (prj_trans.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true)
    converter.set<transform_tag>(); //always transform
    converter.set<affine_transform_tag>();
    if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
    if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter

// FIXME
#if 0
    for ( geometry_type const& geom : feature.paths())
    {
        if (geom.size() > 2)
        {
            vertex_adapter va(geom);
            converter.apply(va);
        }
    }
#endif
    // fill polygon
    context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD);
    context_.fill();
}

template void cairo_renderer<cairo_ptr>::process(polygon_pattern_symbolizer const&,
                                                 mapnik::feature_impl &,
                                                 proj_transform const&);

}

#endif // HAVE_CAIRO
<commit_msg>use mapnik-geometry<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2014 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#if defined(HAVE_CAIRO)

// mapnik
#include <mapnik/feature.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/cairo/cairo_renderer.hpp>
#include <mapnik/cairo/cairo_render_vector.hpp>
#include <mapnik/renderer_common/render_pattern.hpp>
#include <mapnik/vertex_converters.hpp>
#include <mapnik/vertex_processor.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/renderer_common/clipping_extent.hpp>
#include <mapnik/renderer_common/apply_vertex_converter.hpp>

namespace mapnik
{

struct cairo_renderer_process_visitor_p
{
    cairo_renderer_process_visitor_p(cairo_context & context,
                                   agg::trans_affine & image_tr,
                                   unsigned offset_x,
                                   unsigned offset_y,
                                   float opacity)
        : context_(context),
          image_tr_(image_tr),
          offset_x_(offset_x),
          offset_y_(offset_y),
          opacity_(opacity) {}

    void operator() (marker_null const&) {}

    void operator() (marker_svg const& marker)
    {
        mapnik::rasterizer ras;
        mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr_;
        mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
        render_pattern<image_rgba8>(ras, marker, image_tr_, 1.0, image);
        cairo_pattern pattern(image, opacity_);
        pattern.set_extend(CAIRO_EXTEND_REPEAT);
        pattern.set_origin(offset_x_, offset_y_);
        context_.set_pattern(pattern);
    }

    void operator() (marker_rgba8 const& marker)
    {
        cairo_pattern pattern(marker.get_data(), opacity_);
        pattern.set_extend(CAIRO_EXTEND_REPEAT);
        pattern.set_origin(offset_x_, offset_y_);
        context_.set_pattern(pattern);
    }

  private:
    cairo_context & context_;
    agg::trans_affine & image_tr_;
    unsigned offset_x_;
    unsigned offset_y_;
    float opacity_;
};

template <typename T>
void cairo_renderer<T>::process(polygon_pattern_symbolizer const& sym,
                                  mapnik::feature_impl & feature,
                                  proj_transform const& prj_trans)
{
    composite_mode_e comp_op = get<composite_mode_e, keys::comp_op>(sym, feature, common_.vars_);
    std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_);
    value_bool clip = get<value_bool, keys::clip>(sym, feature, common_.vars_);
    value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym, feature, common_.vars_);
    value_double smooth = get<value_double, keys::smooth>(sym, feature, common_.vars_);
    value_double opacity = get<value_double, keys::opacity>(sym, feature, common_.vars_);
    agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
    auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
    if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform);

    cairo_save_restore guard(context_);
    context_.set_operator(comp_op);

    mapnik::marker const& marker = mapnik::marker_cache::instance().find(filename,true);
    if (marker.is<mapnik::marker_null>()) return;

    unsigned offset_x=0;
    unsigned offset_y=0;
    box2d<double> const& clip_box = clipping_extent(common_);
    pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym, feature, common_.vars_);
    if (alignment == LOCAL_ALIGNMENT)
    {
        double x0 = 0.0;
        double y0 = 0.0;
// FIXME
#if 0
        if (feature.num_geometries() > 0)
        {
            using clipped_geometry_type = agg::conv_clip_polygon<vertex_adapter>;
            using path_type = transform_path_adapter<view_transform,clipped_geometry_type>;
            vertex_adapter va(feature.get_geometry(0));
            clipped_geometry_type clipped(va);
            clipped.clip_box(clip_box.minx(), clip_box.miny(),
                             clip_box.maxx(), clip_box.maxy());
            path_type path(common_.t_, clipped, prj_trans);
            path.vertex(&x0, &y0);
        }
        offset_x = std::abs(clip_box.width() - x0);
        offset_y = std::abs(clip_box.height() - y0);
#endif
    }

    util::apply_visitor(cairo_renderer_process_visitor_p(context_, image_tr, offset_x, offset_y, opacity), marker);

    agg::trans_affine tr;
    auto geom_transform = get_optional<transform_type>(sym, keys::geometry_transform);
    if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); }
    using vertex_converter_type = vertex_converter<cairo_context,
                                                   clip_poly_tag,
                                                   transform_tag,
                                                   affine_transform_tag,
                                                   simplify_tag,
                                                   smooth_tag>;

    vertex_converter_type converter(clip_box, context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);
    if (prj_trans.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true)
    converter.set<transform_tag>(); //always transform
    converter.set<affine_transform_tag>();
    if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
    if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter

    using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type>;
    using vertex_processor_type = new_geometry::vertex_processor<apply_vertex_converter_type>;
    apply_vertex_converter_type apply(converter);
    mapnik::util::apply_visitor(vertex_processor_type(apply),feature.get_geometry());
    // fill polygon
    context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD);
    context_.fill();
}

template void cairo_renderer<cairo_ptr>::process(polygon_pattern_symbolizer const&,
                                                 mapnik::feature_impl &,
                                                 proj_transform const&);

}

#endif // HAVE_CAIRO
<|endoftext|>