<commit_before>#include <QSettings>
#include <QDebug>
#include <QJsonObject>
#include <QJsonArray>
#include <QDir>
#include <QFont>
#include <QFontMetrics>
#include <QStringList>
#include <QFontDatabase>
#include "vnote.h"
#include "utils/vutils.h"
#include "vconfigmanager.h"
#include "vmainwindow.h"
#include "vorphanfile.h"

extern VConfigManager vconfig;

QString VNote::s_markdownTemplate;
QString VNote::s_markdownTemplatePDF;

const QString VNote::c_hoedownJsFile = ":/resources/hoedown.js";

const QString VNote::c_markedJsFile = ":/resources/marked.js";
const QString VNote::c_markedExtraFile = ":/utils/marked/marked.min.js";

const QString VNote::c_markdownitJsFile = ":/resources/markdown-it.js";
const QString VNote::c_markdownitExtraFile = ":/utils/markdown-it/markdown-it.min.js";
const QString VNote::c_markdownitAnchorExtraFile = ":/utils/markdown-it/markdown-it-headinganchor.js";
const QString VNote::c_markdownitTaskListExtraFile = ":/utils/markdown-it/markdown-it-task-lists.min.js";
const QString VNote::c_markdownitSubExtraFile = ":/utils/markdown-it/markdown-it-sub.min.js";
const QString VNote::c_markdownitSupExtraFile = ":/utils/markdown-it/markdown-it-sup.min.js";
const QString VNote::c_markdownitFootnoteExtraFile = ":/utils/markdown-it/markdown-it-footnote.min.js";

const QString VNote::c_showdownJsFile = ":/resources/showdown.js";
const QString VNote::c_showdownExtraFile = ":/utils/showdown/showdown.min.js";
const QString VNote::c_showdownAnchorExtraFile = ":/utils/showdown/showdown-headinganchor.js";

const QString VNote::c_mermaidApiJsFile = ":/utils/mermaid/mermaidAPI.min.js";
const QString VNote::c_mermaidCssFile = ":/utils/mermaid/mermaid.css";
const QString VNote::c_mermaidDarkCssFile = ":/utils/mermaid/mermaid.dark.css";
const QString VNote::c_mermaidForestCssFile = ":/utils/mermaid/mermaid.forest.css";

const QString VNote::c_mathjaxJsFile = "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML";

const QString VNote::c_shortcutsDocFile_en = ":/resources/docs/shortcuts_en.md";
const QString VNote::c_shortcutsDocFile_zh = ":/resources/docs/shortcuts_zh.md";

VNote::VNote(QObject *parent)
    : QObject(parent), m_mainWindow(dynamic_cast<VMainWindow *>(parent))
{
    initTemplate();
    vconfig.getNotebooks(m_notebooks, this);
}

void VNote::initPalette(QPalette palette)
{
    m_palette.clear();

    m_palette.append(QPair<QString, QString>("base-background",
                                             palette.background().color().name()));
    m_palette.append(QPair<QString, QString>("base-foreground",
                                             palette.background().color().name()));
    m_palette.append(QPair<QString, QString>("hover-color", "#42A5F5"));
    m_palette.append(QPair<QString, QString>("base-color", "#BDBDBD"));
    m_palette.append(QPair<QString, QString>("focus-color", "#75C5B5"));
    m_palette.append(QPair<QString, QString>("logo-base", "#D6EACE"));
    m_palette.append(QPair<QString, QString>("logo-max", "#15AE67"));
    m_palette.append(QPair<QString, QString>("logo-min", "#75C5B5"));

    // Material Design Colors
    m_palette.append(QPair<QString, QString>("Teal0", "#E0F2F1"));
    m_palette.append(QPair<QString, QString>("Teal1", "#B2DFDB"));
    m_palette.append(QPair<QString, QString>("Teal2", "#80CBC4"));
    m_palette.append(QPair<QString, QString>("Teal3", "#4DB6AC"));
    m_palette.append(QPair<QString, QString>("Teal4", "#26A69A"));
    m_palette.append(QPair<QString, QString>("Teal5", "#009688"));

    m_palette.append(QPair<QString, QString>("Indigo0", "#E8EAF6"));
    m_palette.append(QPair<QString, QString>("Indigo1", "#C5CAE9"));
    m_palette.append(QPair<QString, QString>("Indigo2", "#9FA8DA"));
    m_palette.append(QPair<QString, QString>("Indigo3", "#7986CB"));
    m_palette.append(QPair<QString, QString>("Indigo4", "#5C6BC0"));

    m_palette.append(QPair<QString, QString>("Grey0", "#FAFAFA"));
    m_palette.append(QPair<QString, QString>("Grey1", "#F5F5F5"));
    m_palette.append(QPair<QString, QString>("Grey2", "#EEEEEE"));
    m_palette.append(QPair<QString, QString>("Grey3", "#E0E0E0"));
    m_palette.append(QPair<QString, QString>("Grey4", "#BDBDBD"));
    m_palette.append(QPair<QString, QString>("Grey5", "#9E9E9E"));
    m_palette.append(QPair<QString, QString>("Grey6", "#757575"));
    m_palette.append(QPair<QString, QString>("Grey7", "#616161"));
    m_palette.append(QPair<QString, QString>("Grey8", "#424242"));

    m_palette.append(QPair<QString, QString>("Green0", "#E8F5E9"));
    m_palette.append(QPair<QString, QString>("Green1", "#C8E6C9"));
    m_palette.append(QPair<QString, QString>("Green2", "#A5D6A7"));
    m_palette.append(QPair<QString, QString>("Green3", "#81C784"));
    m_palette.append(QPair<QString, QString>("Green4", "#66BB6A"));
    m_palette.append(QPair<QString, QString>("Green5", "#4CAF50"));
    m_palette.append(QPair<QString, QString>("Green6", "#43A047"));
    m_palette.append(QPair<QString, QString>("Green7", "#388E3C"));
    m_palette.append(QPair<QString, QString>("Green8", "#2E7D32"));
    m_palette.append(QPair<QString, QString>("Green9", "#1B5E20"));

    m_palette.append(QPair<QString, QString>("DeepPurple0", "#EDE7F6"));
    m_palette.append(QPair<QString, QString>("DeepPurple1", "#D1C4E9"));
    m_palette.append(QPair<QString, QString>("DeepPurple2", "#B39DDB"));
    m_palette.append(QPair<QString, QString>("DeepPurple3", "#9575CD"));
    m_palette.append(QPair<QString, QString>("DeepPurple4", "#7E57C2"));
    m_palette.append(QPair<QString, QString>("DeepPurple5", "#673AB7"));
    m_palette.append(QPair<QString, QString>("DeepPurple6", "#5E35B1"));
    m_palette.append(QPair<QString, QString>("DeepPurple7", "#512DA8"));
    m_palette.append(QPair<QString, QString>("DeepPurple8", "#4527A0"));
    m_palette.append(QPair<QString, QString>("DeepPurple9", "#311B92"));

    m_palette.append(QPair<QString, QString>("Purple0", "#F3E5F5"));
    m_palette.append(QPair<QString, QString>("Purple1", "#E1BEE7"));
    m_palette.append(QPair<QString, QString>("Purple2", "#CE93D8"));
    m_palette.append(QPair<QString, QString>("Purple3", "#BA68C8"));
    m_palette.append(QPair<QString, QString>("Purple4", "#AB47BC"));
    m_palette.append(QPair<QString, QString>("Purple5", "#9C27B0"));
    m_palette.append(QPair<QString, QString>("Purple6", "#8E24AA"));
    m_palette.append(QPair<QString, QString>("Purple7", "#7B1FA2"));
    m_palette.append(QPair<QString, QString>("Purple8", "#6A1B9A"));
    m_palette.append(QPair<QString, QString>("Purple9", "#4A148C"));

    m_palette.append(QPair<QString, QString>("Red0", "#FFEBEE"));
    m_palette.append(QPair<QString, QString>("Red1", "#FFCDD2"));
    m_palette.append(QPair<QString, QString>("Red2", "#EF9A9A"));
    m_palette.append(QPair<QString, QString>("Red3", "#E57373"));
    m_palette.append(QPair<QString, QString>("Red4", "#EF5350"));
    m_palette.append(QPair<QString, QString>("Red5", "#F44336"));
    m_palette.append(QPair<QString, QString>("Red6", "#E53935"));
    m_palette.append(QPair<QString, QString>("Red7", "#D32F2F"));
    m_palette.append(QPair<QString, QString>("Red8", "#C62828"));
    m_palette.append(QPair<QString, QString>("Red9", "#B71C1C"));
}

QString VNote::getColorFromPalette(const QString &p_name) const
{
    for (int i = 0; i < m_palette.size(); ++i) {
        if (m_palette[i].first == p_name) {
            return m_palette[i].second;
        }
    }
    return "White";
}

void VNote::initTemplate()
{
    if (s_markdownTemplate.isEmpty()) {
        updateTemplate();
    }
}

void VNote::updateTemplate()
{
    const QString c_markdownTemplatePath(":/resources/markdown_template.html");

    // Get background color
    QString rgb;
    const QString &curRenderBg = vconfig.getCurRenderBackgroundColor();
    const QVector<VColor> &predefinedColors = vconfig.getPredefinedColors();
    if (curRenderBg != "System") {
        for (int i = 0; i < predefinedColors.size(); ++i) {
            if (predefinedColors[i].name == curRenderBg) {
                rgb = predefinedColors[i].rgb;
                break;
            }
        }
    }
    QString cssStyle;
    if (!rgb.isEmpty()) {
        cssStyle += "body { background-color: #" + rgb + " !important; }\n";
    }

    if (vconfig.getEnableImageConstraint()) {
        // Constain the image width.
        cssStyle += "img { max-width: 100% !important; height: auto !important; }\n";
    }

    const QString styleHolder("<!-- BACKGROUND_PLACE_HOLDER -->");
    const QString cssHolder("CSS_PLACE_HOLDER");

    s_markdownTemplate = VUtils::readFileFromDisk(c_markdownTemplatePath);
    s_markdownTemplate.replace(cssHolder, vconfig.getTemplateCssUrl());

    s_markdownTemplatePDF = s_markdownTemplate;

    if (!cssStyle.isEmpty()) {
        s_markdownTemplate.replace(styleHolder, cssStyle);
    }

    // Shoudl not display scrollbar in PDF.
    cssStyle += "pre code { white-space: pre-wrap !important; "
                           "word-break: break-all !important; }\n";
    s_markdownTemplatePDF.replace(styleHolder, cssStyle);
}

const QVector<VNotebook *> &VNote::getNotebooks() const
{
    return m_notebooks;
}

QVector<VNotebook *> &VNote::getNotebooks()
{
    return m_notebooks;
}

QString VNote::getNavigationLabelStyle(const QString &p_str) const
{
    static int lastLen = -1;
    static int pxWidth = 24;
    int fontPt = 15;
    QString fontFamily = getMonospacedFont();

    if (p_str.size() != lastLen) {
        QFont font(fontFamily, fontPt);
        font.setBold(true);
        QFontMetrics fm(font);
        pxWidth = fm.width(p_str);
        lastLen = p_str.size();
    }

    return QString("background-color: %1;"
                   "color: %2;"
                   "font-size: %3pt;"
                   "font: bold;"
                   "font-family: %4;"
                   "border-radius: 3px;"
                   "min-width: %5px;"
                   "max-width: %5px;")
                   .arg(getColorFromPalette("logo-base"))
                   .arg(getColorFromPalette("logo-max"))
                   .arg(fontPt)
                   .arg(fontFamily)
                   .arg(pxWidth);
}

const QString &VNote::getMonospacedFont() const
{
    static QString font;
    if (font.isNull()) {
        QStringList candidates;
        candidates << "Consolas" << "Monaco" << "Andale Mono" << "Monospace" << "Courier New";
        QStringList availFamilies = QFontDatabase().families();

        for (int i = 0; i < candidates.size(); ++i) {
            QString family = candidates[i].trimmed().toLower();
            for (int j = 0; j < availFamilies.size(); ++j) {
                QString availFamily = availFamilies[j];
                availFamily.remove(QRegExp("\\[.*\\]"));
                if (family == availFamily.trimmed().toLower()) {
                    font = availFamily;
                    return font;
                }
            }
        }

        // Fallback to current font.
        font = QFont().family();
    }
    return font;
}

VFile *VNote::getOrphanFile(const QString &p_path)
{
    if (p_path.isEmpty()) {
        return NULL;
    }

    // See if the file has already been opened before.
    for (auto const &file : m_externalFiles) {
        if (file->getType() == FileType::Orphan && file->retrivePath() == p_path) {
            qDebug() << "find a VFile for path" << p_path;
            return file;
        }
    }

    // TODO: Clean up unopened file here.

    // Create a VOrphanFile for p_path.
    VOrphanFile *file = new VOrphanFile(p_path, this);
    m_externalFiles.append(file);
    return file;
}
<commit_msg>bug-fix: always constrain the image width when exporting PDF<commit_after>#include <QSettings>
#include <QDebug>
#include <QJsonObject>
#include <QJsonArray>
#include <QDir>
#include <QFont>
#include <QFontMetrics>
#include <QStringList>
#include <QFontDatabase>
#include "vnote.h"
#include "utils/vutils.h"
#include "vconfigmanager.h"
#include "vmainwindow.h"
#include "vorphanfile.h"

extern VConfigManager vconfig;

QString VNote::s_markdownTemplate;
QString VNote::s_markdownTemplatePDF;

const QString VNote::c_hoedownJsFile = ":/resources/hoedown.js";

const QString VNote::c_markedJsFile = ":/resources/marked.js";
const QString VNote::c_markedExtraFile = ":/utils/marked/marked.min.js";

const QString VNote::c_markdownitJsFile = ":/resources/markdown-it.js";
const QString VNote::c_markdownitExtraFile = ":/utils/markdown-it/markdown-it.min.js";
const QString VNote::c_markdownitAnchorExtraFile = ":/utils/markdown-it/markdown-it-headinganchor.js";
const QString VNote::c_markdownitTaskListExtraFile = ":/utils/markdown-it/markdown-it-task-lists.min.js";
const QString VNote::c_markdownitSubExtraFile = ":/utils/markdown-it/markdown-it-sub.min.js";
const QString VNote::c_markdownitSupExtraFile = ":/utils/markdown-it/markdown-it-sup.min.js";
const QString VNote::c_markdownitFootnoteExtraFile = ":/utils/markdown-it/markdown-it-footnote.min.js";

const QString VNote::c_showdownJsFile = ":/resources/showdown.js";
const QString VNote::c_showdownExtraFile = ":/utils/showdown/showdown.min.js";
const QString VNote::c_showdownAnchorExtraFile = ":/utils/showdown/showdown-headinganchor.js";

const QString VNote::c_mermaidApiJsFile = ":/utils/mermaid/mermaidAPI.min.js";
const QString VNote::c_mermaidCssFile = ":/utils/mermaid/mermaid.css";
const QString VNote::c_mermaidDarkCssFile = ":/utils/mermaid/mermaid.dark.css";
const QString VNote::c_mermaidForestCssFile = ":/utils/mermaid/mermaid.forest.css";

const QString VNote::c_mathjaxJsFile = "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML";

const QString VNote::c_shortcutsDocFile_en = ":/resources/docs/shortcuts_en.md";
const QString VNote::c_shortcutsDocFile_zh = ":/resources/docs/shortcuts_zh.md";

VNote::VNote(QObject *parent)
    : QObject(parent), m_mainWindow(dynamic_cast<VMainWindow *>(parent))
{
    initTemplate();
    vconfig.getNotebooks(m_notebooks, this);
}

void VNote::initPalette(QPalette palette)
{
    m_palette.clear();

    m_palette.append(QPair<QString, QString>("base-background",
                                             palette.background().color().name()));
    m_palette.append(QPair<QString, QString>("base-foreground",
                                             palette.background().color().name()));
    m_palette.append(QPair<QString, QString>("hover-color", "#42A5F5"));
    m_palette.append(QPair<QString, QString>("base-color", "#BDBDBD"));
    m_palette.append(QPair<QString, QString>("focus-color", "#75C5B5"));
    m_palette.append(QPair<QString, QString>("logo-base", "#D6EACE"));
    m_palette.append(QPair<QString, QString>("logo-max", "#15AE67"));
    m_palette.append(QPair<QString, QString>("logo-min", "#75C5B5"));

    // Material Design Colors
    m_palette.append(QPair<QString, QString>("Teal0", "#E0F2F1"));
    m_palette.append(QPair<QString, QString>("Teal1", "#B2DFDB"));
    m_palette.append(QPair<QString, QString>("Teal2", "#80CBC4"));
    m_palette.append(QPair<QString, QString>("Teal3", "#4DB6AC"));
    m_palette.append(QPair<QString, QString>("Teal4", "#26A69A"));
    m_palette.append(QPair<QString, QString>("Teal5", "#009688"));

    m_palette.append(QPair<QString, QString>("Indigo0", "#E8EAF6"));
    m_palette.append(QPair<QString, QString>("Indigo1", "#C5CAE9"));
    m_palette.append(QPair<QString, QString>("Indigo2", "#9FA8DA"));
    m_palette.append(QPair<QString, QString>("Indigo3", "#7986CB"));
    m_palette.append(QPair<QString, QString>("Indigo4", "#5C6BC0"));

    m_palette.append(QPair<QString, QString>("Grey0", "#FAFAFA"));
    m_palette.append(QPair<QString, QString>("Grey1", "#F5F5F5"));
    m_palette.append(QPair<QString, QString>("Grey2", "#EEEEEE"));
    m_palette.append(QPair<QString, QString>("Grey3", "#E0E0E0"));
    m_palette.append(QPair<QString, QString>("Grey4", "#BDBDBD"));
    m_palette.append(QPair<QString, QString>("Grey5", "#9E9E9E"));
    m_palette.append(QPair<QString, QString>("Grey6", "#757575"));
    m_palette.append(QPair<QString, QString>("Grey7", "#616161"));
    m_palette.append(QPair<QString, QString>("Grey8", "#424242"));

    m_palette.append(QPair<QString, QString>("Green0", "#E8F5E9"));
    m_palette.append(QPair<QString, QString>("Green1", "#C8E6C9"));
    m_palette.append(QPair<QString, QString>("Green2", "#A5D6A7"));
    m_palette.append(QPair<QString, QString>("Green3", "#81C784"));
    m_palette.append(QPair<QString, QString>("Green4", "#66BB6A"));
    m_palette.append(QPair<QString, QString>("Green5", "#4CAF50"));
    m_palette.append(QPair<QString, QString>("Green6", "#43A047"));
    m_palette.append(QPair<QString, QString>("Green7", "#388E3C"));
    m_palette.append(QPair<QString, QString>("Green8", "#2E7D32"));
    m_palette.append(QPair<QString, QString>("Green9", "#1B5E20"));

    m_palette.append(QPair<QString, QString>("DeepPurple0", "#EDE7F6"));
    m_palette.append(QPair<QString, QString>("DeepPurple1", "#D1C4E9"));
    m_palette.append(QPair<QString, QString>("DeepPurple2", "#B39DDB"));
    m_palette.append(QPair<QString, QString>("DeepPurple3", "#9575CD"));
    m_palette.append(QPair<QString, QString>("DeepPurple4", "#7E57C2"));
    m_palette.append(QPair<QString, QString>("DeepPurple5", "#673AB7"));
    m_palette.append(QPair<QString, QString>("DeepPurple6", "#5E35B1"));
    m_palette.append(QPair<QString, QString>("DeepPurple7", "#512DA8"));
    m_palette.append(QPair<QString, QString>("DeepPurple8", "#4527A0"));
    m_palette.append(QPair<QString, QString>("DeepPurple9", "#311B92"));

    m_palette.append(QPair<QString, QString>("Purple0", "#F3E5F5"));
    m_palette.append(QPair<QString, QString>("Purple1", "#E1BEE7"));
    m_palette.append(QPair<QString, QString>("Purple2", "#CE93D8"));
    m_palette.append(QPair<QString, QString>("Purple3", "#BA68C8"));
    m_palette.append(QPair<QString, QString>("Purple4", "#AB47BC"));
    m_palette.append(QPair<QString, QString>("Purple5", "#9C27B0"));
    m_palette.append(QPair<QString, QString>("Purple6", "#8E24AA"));
    m_palette.append(QPair<QString, QString>("Purple7", "#7B1FA2"));
    m_palette.append(QPair<QString, QString>("Purple8", "#6A1B9A"));
    m_palette.append(QPair<QString, QString>("Purple9", "#4A148C"));

    m_palette.append(QPair<QString, QString>("Red0", "#FFEBEE"));
    m_palette.append(QPair<QString, QString>("Red1", "#FFCDD2"));
    m_palette.append(QPair<QString, QString>("Red2", "#EF9A9A"));
    m_palette.append(QPair<QString, QString>("Red3", "#E57373"));
    m_palette.append(QPair<QString, QString>("Red4", "#EF5350"));
    m_palette.append(QPair<QString, QString>("Red5", "#F44336"));
    m_palette.append(QPair<QString, QString>("Red6", "#E53935"));
    m_palette.append(QPair<QString, QString>("Red7", "#D32F2F"));
    m_palette.append(QPair<QString, QString>("Red8", "#C62828"));
    m_palette.append(QPair<QString, QString>("Red9", "#B71C1C"));
}

QString VNote::getColorFromPalette(const QString &p_name) const
{
    for (int i = 0; i < m_palette.size(); ++i) {
        if (m_palette[i].first == p_name) {
            return m_palette[i].second;
        }
    }
    return "White";
}

void VNote::initTemplate()
{
    if (s_markdownTemplate.isEmpty()) {
        updateTemplate();
    }
}

void VNote::updateTemplate()
{
    const QString c_markdownTemplatePath(":/resources/markdown_template.html");

    // Get background color
    QString rgb;
    const QString &curRenderBg = vconfig.getCurRenderBackgroundColor();
    const QVector<VColor> &predefinedColors = vconfig.getPredefinedColors();
    if (curRenderBg != "System") {
        for (int i = 0; i < predefinedColors.size(); ++i) {
            if (predefinedColors[i].name == curRenderBg) {
                rgb = predefinedColors[i].rgb;
                break;
            }
        }
    }
    QString cssStyle;
    if (!rgb.isEmpty()) {
        cssStyle += "body { background-color: #" + rgb + " !important; }\n";
    }

    if (vconfig.getEnableImageConstraint()) {
        // Constain the image width.
        cssStyle += "img { max-width: 100% !important; height: auto !important; }\n";
    }

    const QString styleHolder("<!-- BACKGROUND_PLACE_HOLDER -->");
    const QString cssHolder("CSS_PLACE_HOLDER");

    s_markdownTemplate = VUtils::readFileFromDisk(c_markdownTemplatePath);
    s_markdownTemplate.replace(cssHolder, vconfig.getTemplateCssUrl());

    s_markdownTemplatePDF = s_markdownTemplate;

    if (!cssStyle.isEmpty()) {
        s_markdownTemplate.replace(styleHolder, cssStyle);
    }

    // Shoudl not display scrollbar in PDF.
    cssStyle += "pre code { white-space: pre-wrap !important; "
                           "word-break: break-all !important; }\n";
    if (!vconfig.getEnableImageConstraint()) {
        // Constain the image width by force in PDF, otherwise, the PDF will
        // be cut off.
        cssStyle += "img { max-width: 100% !important; height: auto !important; }\n";
    }

    s_markdownTemplatePDF.replace(styleHolder, cssStyle);
}

const QVector<VNotebook *> &VNote::getNotebooks() const
{
    return m_notebooks;
}

QVector<VNotebook *> &VNote::getNotebooks()
{
    return m_notebooks;
}

QString VNote::getNavigationLabelStyle(const QString &p_str) const
{
    static int lastLen = -1;
    static int pxWidth = 24;
    int fontPt = 15;
    QString fontFamily = getMonospacedFont();

    if (p_str.size() != lastLen) {
        QFont font(fontFamily, fontPt);
        font.setBold(true);
        QFontMetrics fm(font);
        pxWidth = fm.width(p_str);
        lastLen = p_str.size();
    }

    return QString("background-color: %1;"
                   "color: %2;"
                   "font-size: %3pt;"
                   "font: bold;"
                   "font-family: %4;"
                   "border-radius: 3px;"
                   "min-width: %5px;"
                   "max-width: %5px;")
                   .arg(getColorFromPalette("logo-base"))
                   .arg(getColorFromPalette("logo-max"))
                   .arg(fontPt)
                   .arg(fontFamily)
                   .arg(pxWidth);
}

const QString &VNote::getMonospacedFont() const
{
    static QString font;
    if (font.isNull()) {
        QStringList candidates;
        candidates << "Consolas" << "Monaco" << "Andale Mono" << "Monospace" << "Courier New";
        QStringList availFamilies = QFontDatabase().families();

        for (int i = 0; i < candidates.size(); ++i) {
            QString family = candidates[i].trimmed().toLower();
            for (int j = 0; j < availFamilies.size(); ++j) {
                QString availFamily = availFamilies[j];
                availFamily.remove(QRegExp("\\[.*\\]"));
                if (family == availFamily.trimmed().toLower()) {
                    font = availFamily;
                    return font;
                }
            }
        }

        // Fallback to current font.
        font = QFont().family();
    }
    return font;
}

VFile *VNote::getOrphanFile(const QString &p_path)
{
    if (p_path.isEmpty()) {
        return NULL;
    }

    // See if the file has already been opened before.
    for (auto const &file : m_externalFiles) {
        if (file->getType() == FileType::Orphan && file->retrivePath() == p_path) {
            qDebug() << "find a VFile for path" << p_path;
            return file;
        }
    }

    // TODO: Clean up unopened file here.

    // Create a VOrphanFile for p_path.
    VOrphanFile *file = new VOrphanFile(p_path, this);
    m_externalFiles.append(file);
    return file;
}
<|endoftext|>


<commit_before>/*	____________________________________________________________________________

	                 Scanner Component for the Micro A Compiler

	                                mscan.h

	                              Version 2007 - 2016

	                           James L. Richards
	                     Last Update: August 28, 2007
	                      	   Nelson A Castillo
	                     Last Update: January 31, 2016

	The routines in this unit are based on those provided in the book
	"Crafting A Compiler" by Charles N. Fischer and Richard J. LeBlanc, Jr.,
	Benjamin Cummings Publishing Co. (1991).

	See Section 2.2, pp. 25-29.
	____________________________________________________________________________
*/

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

extern ifstream sourceFile;
extern ofstream outFile, listFile;

#include "mscan.h"

// *******************
// **  Constructor  **
// *******************

Scanner::Scanner()
{
	tokenBuffer = "";
	lineBuffer = "";
	lineNumber = 0;
}

// ********************************
// **  Private Member Functions  **
// ********************************

void Scanner::BufferChar(char c)
{
	if (tokenBuffer.length() < ID_STRING_LEN){
		tokenBuffer += c;
	}
	//cerr << tokenBuffer << endl;
}
void Scanner::BufferString(char c)
{
		stringBuffer += c;
	//cerr << tokenBuffer << endl;
}

Token Scanner::CheckReserved()
{
	if (tolower(tokenBuffer) == "bool") return BOOL_SYM;
	if (tolower(tokenBuffer) == "break") return BREAK_SYM;
	if (tolower(tokenBuffer) == "case") return CASE_SYM;
	if (tolower(tokenBuffer) == "cheese") return CHEESE_SYM;
	if (tolower(tokenBuffer) == "decs") return DECS_SYM;
	if (tolower(tokenBuffer) == "do") return DO_SYM;
	if (tolower(tokenBuffer) == "else") return ELSE_SYM;
	if (tolower(tokenBuffer) == "end") return END_SYM;
	if (tolower(tokenBuffer) == "false") return FALSE_SYM;
	if (tolower(tokenBuffer) == "float") return FLOAT_SYM;
	if (tolower(tokenBuffer) == "for") return FOR_SYM;
	if (tolower(tokenBuffer) == "hiphip") return HIPHIP_SYM;
	if (tolower(tokenBuffer) == "if") return IF_SYM;
	if (tolower(tokenBuffer) == "int") return INT_SYM;
	if (tolower(tokenBuffer) == "listen") return LISTEN_SYM;
	if (tolower(tokenBuffer) == "otherwise") return OTHERWISE_SYM;
	if (tolower(tokenBuffer) == "select") return SELECT_SYM;
	if (tolower(tokenBuffer) == "shout") return SHOUT_SYM;
	if (tolower(tokenBuffer) == "then") return THEN_SYM;
	if (tolower(tokenBuffer) == "true") return TRUE_SYM;
	if (tolower(tokenBuffer) == "while") return WHILE_SYM;

	return ID;
}

void Scanner::ClearBuffer()
{
	tokenBuffer = "";
	stringBuffer = "";
}

void Scanner::LexicalError(char& c, string& errorExp="")
{
	cout << " *** Lexical Error: '" << c
		<< "' ignored at position " << int(lineBuffer.size())
		<< " on line #" << lineNumber+1 << '.' << endl;
	listFile << " *** Lexical Error: '" << c
		<< "' ignored at position " << int(lineBuffer.size())
		<< " on line #" << lineNumber+1 << '.' << endl;
	if(errorExp!=""){
		//TODO :: I was starting with the comment but
		//I need to ampliate the code
	}
	c = NextChar();
}

char Scanner::NextChar()
{
	char c;

	sourceFile.get(c);
	if (c == '\n')
	{
		listFile.width(6);
		listFile << ++lineNumber << "  " << lineBuffer << endl;
		lineBuffer = "";
	} else{
		lineBuffer += c;
	}
	return c;
}

// *******************************
// **  Public Member Functions  **
// *******************************

Token Scanner::GetNextToken()
{
	char currentChar, c;

	ClearBuffer();
	currentChar = NextChar();
	while (!sourceFile.eof())
	{
		if (isspace(currentChar)){
			currentChar = NextChar();     // do nothing
		} else if (isalpha(currentChar))
		{                                // identifier
			BufferChar(currentChar);
			c = sourceFile.peek();
			while (isalnum(c) || c == '_')
			{
				currentChar = NextChar();
				BufferChar(currentChar);
				c = sourceFile.peek();
			}
			return CheckReserved();
		} else if (isdigit(currentChar)){                                // integer or float literals
			BufferChar(currentChar);
			c = sourceFile.peek();
			while (isdigit(c))
			{
				currentChar = NextChar();
				BufferChar(currentChar);
				c = sourceFile.peek();
			}
			/* Check if it is a float */
			if (c == '.')
			{
				currentChar = NextChar();
				c = sourceFile.peek();
				if (!isdigit(c))
					LexicalError(currentChar);
				BufferChar(currentChar);
				while (isdigit(c))
				{
					currentChar = NextChar();
					BufferChar(currentChar);
					c = sourceFile.peek();
				}
				 if (c == 'e' || c == 'E')
				{
					currentChar = NextChar();
					c = sourceFile.peek();
					if(c != '+' && c!= '-'){
						LexicalError(currentChar);
					}
					BufferChar(currentChar);
					currentChar = NextChar();
					c = sourceFile.peek();
					if (!isdigit(c))
						LexicalError(currentChar);
					BufferChar(currentChar);
					while (isdigit(c))
					{
						currentChar = NextChar();
						BufferChar(currentChar);
						c = sourceFile.peek();
					}
				}
				return FLOAT_LIT;
			}
			return INT_LIT;
		} else if (currentChar == '"'){
			// string literal
//			BufferString(currentChar);
			do
			{
				currentChar = NextChar();
//				cout << currentChar <<endl;
				if(currentChar == '"' & sourceFile.peek()!='"'){
//					BufferString(currentChar);
//					cout << "________________________" <<endl;
//					cout << stringBuffer <<endl;
//					cout << "________________________" <<endl;
					return CHEESE_LIT;
				}else if(currentChar == '"' & sourceFile.peek()=='"'){
					currentChar = NextChar();
				}
				BufferString(currentChar);
			} while (sourceFile.peek()!='\n');
			return CHEESE_LIT;
		} else if (currentChar == '('){
			return LBANANA;
		} else if (currentChar == ')'){
			return RBANANA;
		} else if (currentChar == '['){
			return LSTAPLE;
		} else if (currentChar == ']'){
			return RSTAPLE;
		} else if (currentChar == '{'){
			return LMUSTACHE;
		} else if (currentChar == '}'){
			return RMUSTACHE;
		} else if (currentChar == ';'){
			return SEMICOLON;
		} else if (currentChar == ':'){
			return COLON;
		} else if (currentChar == ','){
			return COMMA;
		} else if (currentChar == '+'){
			BufferChar(currentChar);
			return PLUS_OP;
		} else if (currentChar == '*'){
			BufferChar(currentChar);
			return MULT_OP;
		} else if (currentChar == '/'){
			if (sourceFile.peek() == ':') {// comment
				do{  // skip comment
					currentChar = NextChar();
					if(currentChar == ':'){
						currentChar = NextChar();
						if(currentChar == '/'){
							break;
						}
					}
				} while (!sourceFile.eof());
			}
			BufferChar(currentChar);
			return DIV_OP;
		} else if (currentChar == '=') {
			if (sourceFile.peek() == '=')
			{
				currentChar = NextChar();
				return EQ_OP1;
			}
			currentChar = NextChar();
			return ASSIGN_OP;
		} else if (currentChar == '!') {
			if (sourceFile.peek() == '!')
			{
				currentChar = NextChar();
				return EQ_OP2;
			}
			else if(sourceFile.peek() == '='){
			currentChar = NextChar();
			return NE_OP;
			}
		} else if (currentChar == '<') {
			if (sourceFile.peek() == '=')
			{
				currentChar = NextChar();
				return LE_OP;
			}
			currentChar = NextChar();
			return LT_OP;
		} else if (currentChar == '>') {
			if (sourceFile.peek() == '=')
			{
				currentChar = NextChar();
				return GE_OP;
			}
			currentChar = NextChar();
			return GT_OP;
		} else if (currentChar == '-'){
			if (sourceFile.peek() == '-') {// comment
				do{  // skip comment
					currentChar = NextChar();
				} while (currentChar != '\n');
			} else{
				BufferChar(currentChar);      // minus operator
				return MINUS_OP;
			}
		} else{
			LexicalError(currentChar);
		}
	} // end while

	return EOF_SYM;
}
<commit_msg>Fix some indentation.<commit_after>/*	____________________________________________________________________________

	                 Scanner Component for the Micro A Compiler

	                                mscan.h

	                              Version 2007 - 2016

	                           James L. Richards
	                     Last Update: August 28, 2007
	                      	   Nelson A Castillo
	                     Last Update: January 31, 2016

	The routines in this unit are based on those provided in the book
	"Crafting A Compiler" by Charles N. Fischer and Richard J. LeBlanc, Jr.,
	Benjamin Cummings Publishing Co. (1991).

	See Section 2.2, pp. 25-29.
	____________________________________________________________________________
*/

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

extern ifstream sourceFile;
extern ofstream outFile, listFile;

#include "mscan.h"

// *******************
// **  Constructor  **
// *******************

Scanner::Scanner()
{
	tokenBuffer = "";
	lineBuffer = "";
	lineNumber = 0;
}

// ********************************
// **  Private Member Functions  **
// ********************************

void Scanner::BufferChar(char c)
{
	if (tokenBuffer.length() < ID_STRING_LEN){
		tokenBuffer += c;
	}
	//cerr << tokenBuffer << endl;
}
void Scanner::BufferString(char c)
{
	stringBuffer += c;
	//cerr << tokenBuffer << endl;
}

Token Scanner::CheckReserved()
{
	if (tolower(tokenBuffer) == "bool") return BOOL_SYM;
	if (tolower(tokenBuffer) == "break") return BREAK_SYM;
	if (tolower(tokenBuffer) == "case") return CASE_SYM;
	if (tolower(tokenBuffer) == "cheese") return CHEESE_SYM;
	if (tolower(tokenBuffer) == "decs") return DECS_SYM;
	if (tolower(tokenBuffer) == "do") return DO_SYM;
	if (tolower(tokenBuffer) == "else") return ELSE_SYM;
	if (tolower(tokenBuffer) == "end") return END_SYM;
	if (tolower(tokenBuffer) == "false") return FALSE_SYM;
	if (tolower(tokenBuffer) == "float") return FLOAT_SYM;
	if (tolower(tokenBuffer) == "for") return FOR_SYM;
	if (tolower(tokenBuffer) == "hiphip") return HIPHIP_SYM;
	if (tolower(tokenBuffer) == "if") return IF_SYM;
	if (tolower(tokenBuffer) == "int") return INT_SYM;
	if (tolower(tokenBuffer) == "listen") return LISTEN_SYM;
	if (tolower(tokenBuffer) == "otherwise") return OTHERWISE_SYM;
	if (tolower(tokenBuffer) == "select") return SELECT_SYM;
	if (tolower(tokenBuffer) == "shout") return SHOUT_SYM;
	if (tolower(tokenBuffer) == "then") return THEN_SYM;
	if (tolower(tokenBuffer) == "true") return TRUE_SYM;
	if (tolower(tokenBuffer) == "while") return WHILE_SYM;

	return ID;
}

void Scanner::ClearBuffer()
{
	tokenBuffer = "";
	stringBuffer = "";
}

void Scanner::LexicalError(char& c, string& errorExp="")
{
	cout << " *** Lexical Error: '" << c
		<< "' ignored at position " << int(lineBuffer.size())
		<< " on line #" << lineNumber+1 << '.' << endl;
	listFile << " *** Lexical Error: '" << c
		<< "' ignored at position " << int(lineBuffer.size())
		<< " on line #" << lineNumber+1 << '.' << endl;
	if(errorExp!=""){
		//TODO :: I was starting with the comment but
		//I need to ampliate the code
	}
	c = NextChar();
}

char Scanner::NextChar()
{
	char c;

	sourceFile.get(c);
	if (c == '\n')
	{
		listFile.width(6);
		listFile << ++lineNumber << "  " << lineBuffer << endl;
		lineBuffer = "";
	} else{
		lineBuffer += c;
	}
	return c;
}

// *******************************
// **  Public Member Functions  **
// *******************************

Token Scanner::GetNextToken()
{
	char currentChar, c;

	ClearBuffer();
	currentChar = NextChar();
	while (!sourceFile.eof())
	{
		if (isspace(currentChar)){
			currentChar = NextChar(); // do nothing
		} else if (isalpha(currentChar))
		{ // identifier
			BufferChar(currentChar);
			c = sourceFile.peek();
			while (isalnum(c) || c == '_')
			{
				currentChar = NextChar();
				BufferChar(currentChar);
				c = sourceFile.peek();
			}
			return CheckReserved();
		} else if (isdigit(currentChar)){ // integer or float literals
			BufferChar(currentChar);
			c = sourceFile.peek();
			while (isdigit(c))
			{
				currentChar = NextChar();
				BufferChar(currentChar);
				c = sourceFile.peek();
			}
			/* Check if it is a float */
			if (c == '.')
			{
				currentChar = NextChar();
				c = sourceFile.peek();
				if (!isdigit(c))
					LexicalError(currentChar);
				BufferChar(currentChar);
				while (isdigit(c))
				{
					currentChar = NextChar();
					BufferChar(currentChar);
					c = sourceFile.peek();
				}
				if (c == 'e' || c == 'E')
				{
					currentChar = NextChar();
					c = sourceFile.peek();
					if(c != '+' && c!= '-'){
						LexicalError(currentChar);
					}
					BufferChar(currentChar);
					currentChar = NextChar();
					c = sourceFile.peek();
					if (!isdigit(c))
						LexicalError(currentChar);
					BufferChar(currentChar);
					while (isdigit(c))
					{
						currentChar = NextChar();
						BufferChar(currentChar);
						c = sourceFile.peek();
					}
				}
				return FLOAT_LIT;
			}
			return INT_LIT;
		} else if (currentChar == '"'){
			// string literal
			// BufferString(currentChar);
			do
			{
				currentChar = NextChar();
				// cout << currentChar <<endl;
				if(currentChar == '"' & sourceFile.peek()!='"'){
					// BufferString(currentChar);
					// cout << "________________________" <<endl;
					// cout << stringBuffer <<endl;
					// cout << "________________________" <<endl;
					return CHEESE_LIT;
				}else if(currentChar == '"' & sourceFile.peek()=='"'){
					currentChar = NextChar();
				}
				BufferString(currentChar);
			} while (sourceFile.peek()!='\n');
			return CHEESE_LIT;
		} else if (currentChar == '('){
			return LBANANA;
		} else if (currentChar == ')'){
			return RBANANA;
		} else if (currentChar == '['){
			return LSTAPLE;
		} else if (currentChar == ']'){
			return RSTAPLE;
		} else if (currentChar == '{'){
			return LMUSTACHE;
		} else if (currentChar == '}'){
			return RMUSTACHE;
		} else if (currentChar == ';'){
			return SEMICOLON;
		} else if (currentChar == ':'){
			return COLON;
		} else if (currentChar == ','){
			return COMMA;
		} else if (currentChar == '+'){
			BufferChar(currentChar);
			return PLUS_OP;
		} else if (currentChar == '*'){
			BufferChar(currentChar);
			return MULT_OP;
		} else if (currentChar == '/'){
			if (sourceFile.peek() == ':') {// comment
				do{  // skip comment
					currentChar = NextChar();
					if(currentChar == ':'){
						currentChar = NextChar();
						if(currentChar == '/'){
							break;
						}
					}
				} while (!sourceFile.eof());
			}
			BufferChar(currentChar);
			return DIV_OP;
		} else if (currentChar == '=') {
			if (sourceFile.peek() == '=')
			{
				currentChar = NextChar();
				return EQ_OP1;
			}
			currentChar = NextChar();
			return ASSIGN_OP;
		} else if (currentChar == '!') {
			if (sourceFile.peek() == '!')
			{
				currentChar = NextChar();
				return EQ_OP2;
			}
			else if(sourceFile.peek() == '='){
				currentChar = NextChar();
				return NE_OP;
			}
		} else if (currentChar == '<') {
			if (sourceFile.peek() == '=')
			{
				currentChar = NextChar();
				return LE_OP;
			}
			currentChar = NextChar();
			return LT_OP;
		} else if (currentChar == '>') {
			if (sourceFile.peek() == '=')
			{
				currentChar = NextChar();
				return GE_OP;
			}
			currentChar = NextChar();
			return GT_OP;
		} else if (currentChar == '-'){
			if (sourceFile.peek() == '-') {// comment
				do{ // skip comment
					currentChar = NextChar();
				} while (currentChar != '\n');
			} else{
				BufferChar(currentChar); // minus operator
				return MINUS_OP;
			}
		} else{
			LexicalError(currentChar);
		}
	} // end while

	return EOF_SYM;
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * seekpoints.cpp : Chapters & Bookmarks (menu)
 *****************************************************************************
 * Copyright © 2011 the VideoLAN team
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * ( at your option ) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "recents.hpp"
#include "dialogs_provider.hpp"
#include "menus.hpp"

#include "seekpoints.hpp"

#include "qt4.hpp"
#include "input_manager.hpp"

SeekPoints::SeekPoints( QObject *parent, intf_thread_t *p_intf_ ) :
    QObject( parent ), p_intf( p_intf_ )
{}

void SeekPoints::update()
{
    input_title_t *p_title = NULL;
    input_thread_t *p_input_thread = playlist_CurrentInput( THEPL );
    int i_title_id = -1;
    if( !p_input_thread ) { pointsList.clear(); return; }

    if ( input_Control( p_input_thread, INPUT_GET_TITLE_INFO, &p_title, &i_title_id )
        != VLC_SUCCESS )
    {
        vlc_object_release( p_input_thread );
        pointsList.clear();
        return;
    }

    vlc_object_release( p_input_thread );

    /* lock here too, as update event is triggered by an external thread */
    if ( !access() ) return;
    pointsList.clear();
    if ( p_title->i_seekpoint > 0 )
    {
        /* first check the last point to see if we have filled time offsets (> 0) */
        if ( p_title->seekpoint[p_title->i_seekpoint - 1]->i_time_offset > 0 )
        {
            for ( int i=0; i<p_title->i_seekpoint ; i++ )
                pointsList << SeekPoint( p_title->seekpoint[i] );
        }
    }
    vlc_input_title_Delete( p_title );
    release();
}

QList<SeekPoint> const SeekPoints::getPoints()
{
    QList<SeekPoint> copy;
    if ( access() )
    {
        copy = pointsList;
        release();
    }
    return copy;
}

bool SeekPoints::jumpTo( int i_chapterindex )
{
    vlc_value_t val;
    val.i_int = i_chapterindex;
    input_thread_t *p_input_thread = playlist_CurrentInput( THEPL );
    if( !p_input_thread ) return false;
    bool b_succ = var_Set( p_input_thread, "chapter", val );
    vlc_object_release( p_input_thread );
    return ( b_succ == VLC_SUCCESS );
}
<commit_msg>Qt: fix segfault in seekpoints updater<commit_after>/*****************************************************************************
 * seekpoints.cpp : Chapters & Bookmarks (menu)
 *****************************************************************************
 * Copyright © 2011 the VideoLAN team
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * ( at your option ) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "recents.hpp"
#include "dialogs_provider.hpp"
#include "menus.hpp"

#include "seekpoints.hpp"

#include "qt4.hpp"
#include "input_manager.hpp"

SeekPoints::SeekPoints( QObject *parent, intf_thread_t *p_intf_ ) :
    QObject( parent ), p_intf( p_intf_ )
{}

void SeekPoints::update()
{
    input_title_t *p_title = NULL;
    input_thread_t *p_input_thread = playlist_CurrentInput( THEPL );
    int i_title_id = -1;
    if( !p_input_thread ) { pointsList.clear(); return; }

    if ( input_Control( p_input_thread, INPUT_GET_TITLE_INFO, &p_title, &i_title_id )
        != VLC_SUCCESS )
    {
        vlc_object_release( p_input_thread );
        pointsList.clear();
        return;
    }

    vlc_object_release( p_input_thread );

    if( !p_title )
        return;

    /* lock here too, as update event is triggered by an external thread */
    if ( !access() ) return;
    pointsList.clear();
    if ( p_title->i_seekpoint > 0 )
    {
        /* first check the last point to see if we have filled time offsets (> 0) */
        if ( p_title->seekpoint[p_title->i_seekpoint - 1]->i_time_offset > 0 )
        {
            for ( int i=0; i<p_title->i_seekpoint ; i++ )
                pointsList << SeekPoint( p_title->seekpoint[i] );
        }
    }
    vlc_input_title_Delete( p_title );
    release();
}

QList<SeekPoint> const SeekPoints::getPoints()
{
    QList<SeekPoint> copy;
    if ( access() )
    {
        copy = pointsList;
        release();
    }
    return copy;
}

bool SeekPoints::jumpTo( int i_chapterindex )
{
    vlc_value_t val;
    val.i_int = i_chapterindex;
    input_thread_t *p_input_thread = playlist_CurrentInput( THEPL );
    if( !p_input_thread ) return false;
    bool b_succ = var_Set( p_input_thread, "chapter", val );
    vlc_object_release( p_input_thread );
    return ( b_succ == VLC_SUCCESS );
}
<|endoftext|>


<commit_before>
#include "DataFile.hh"
#include "Specific.hh"
#include "avrocpp/api/DataFile.hh"
#include "avrocpp/api/Specific.hh"
#include "types_encode_decode.h"  // IWYU pragma: keep
#include "data_file.h"

namespace RMF {
namespace avro2 {
struct FileDataChanges;
struct Frame;
}  // namespace avro2
}  // namespace RMF

RMF_ENABLE_WARNINGS

namespace RMF {
namespace avro2 {
void write(internal_avro::DataFileWriterBase *writer, const Frame &fr) {
  writer->syncIfNeeded();
  internal_avro::encode(writer->encoder(), fr);
  writer->incr();
}
void write(internal_avro::DataFileWriterBase *writer,
           const FileDataChanges &fr) {
  writer->syncIfNeeded();
  internal_avro::encode(writer->encoder(), fr);
  writer->incr();
}

void load_frame(FrameID id, internal_avro::DataFileReader<Frame>& reader,
                Frame& frame) {
  RMF_TRACE("Looking for frame " << id);

  do {
    frame = Frame();
    reader.read(frame);
    if (frame.id == id) {
      RMF_INFO("Loaded frame " << frame.id << " " << id << std::endl);
      return;
    } else {
      RMF_INFO("Found frame for frame " << frame.id);
    }
  } while (true);
}

void load_file_data(internal_avro::DataFileReader<FileData> &reader,
                    FileData &fd) {
  // clear it
  clear(fd);
  try {
    while (reader.read(fd)) {
      if (fd.cur_id != FrameID()) {
        fd.frame_block_offsets[fd.cur_id] = reader.blockOffsetBytes();
      }
    }
  }
  catch (const std::exception &e) {
  }
}

}
}
RMF_DISABLE_WARNINGS
<commit_msg>improve error messages on failure to load<commit_after>
#include "DataFile.hh"
#include "Specific.hh"
#include "avrocpp/api/DataFile.hh"
#include "avrocpp/api/Specific.hh"
#include "types_encode_decode.h"  // IWYU pragma: keep
#include "data_file.h"

namespace RMF {
namespace avro2 {
struct FileDataChanges;
struct Frame;
}  // namespace avro2
}  // namespace RMF

RMF_ENABLE_WARNINGS

namespace RMF {
namespace avro2 {
void write(internal_avro::DataFileWriterBase *writer, const Frame &fr) {
  writer->syncIfNeeded();
  internal_avro::encode(writer->encoder(), fr);
  writer->incr();
}
void write(internal_avro::DataFileWriterBase *writer,
           const FileDataChanges &fr) {
  writer->syncIfNeeded();
  internal_avro::encode(writer->encoder(), fr);
  writer->incr();
}

void load_frame(FrameID id, internal_avro::DataFileReader<Frame>& reader,
                Frame& frame) {
  RMF_TRACE("Looking for frame " << id);

  do {
    frame = Frame();
    reader.read(frame);
    if (frame.id == id) {
      RMF_INFO("Loaded frame " << frame.id << " " << id << std::endl);
      return;
    } else {
      RMF_INFO("Found frame for frame " << frame.id);
    }
  } while (true);
}

void load_file_data(internal_avro::DataFileReader<FileData> &reader,
                    FileData &fd) {
  // clear it
  clear(fd);
  try {
    while (reader.read(fd)) {
      if (fd.cur_id != FrameID()) {
        fd.frame_block_offsets[fd.cur_id] = reader.blockOffsetBytes();
      }
    }
  }
  catch (const std::exception &e) {
    // ick, ick, ewe
    if (std::string(e.what()) != "EOF reached") {
      RMF_THROW(Message(e.what()) << Operation("loading file data"),
                IOException);
    }
  }
}

}
}
RMF_DISABLE_WARNINGS
<|endoftext|>


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

#include "chrome/test/ui/ui_test.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "net/base/net_util.h"

typedef UITest ChromeMainTest;

// Launch the app, then close the app.
TEST_F(ChromeMainTest, AppLaunch) {
  // If we make it here at all, we've succeeded in retrieving the app window
  // in UITest::SetUp()--otherwise we'd fail with an exception in SetUp().

  if (UITest::in_process_renderer()) {
    EXPECT_EQ(1, UITest::GetBrowserProcessCount());
  } else {
#if defined(OS_LINUX)
    // On Linux we'll have four processes: browser, renderer, zygote and
    // sandbox helper.
    EXPECT_EQ(4, UITest::GetBrowserProcessCount());
#else
    // We should have two instances of the browser process alive -
    // one is the Browser and the other is the Renderer.
    EXPECT_EQ(2, UITest::GetBrowserProcessCount());
#endif
  }
}

// Make sure that the testing interface is there and giving reasonable answers.
TEST_F(ChromeMainTest, AppTestingInterface) {
  int window_count = 0;
  EXPECT_TRUE(automation()->GetBrowserWindowCount(&window_count));
  EXPECT_EQ(1, window_count);

  EXPECT_EQ(1, GetTabCount());
}

#if !defined(OS_MACOSX)
// These tests don't apply to the Mac version; see
// LaunchAnotherBrowserBlockUntilClosed for details.

// Make sure that the second invocation creates a new window.
TEST_F(ChromeMainTest, SecondLaunch) {
  include_testing_id_ = false;

  ASSERT_TRUE(LaunchAnotherBrowserBlockUntilClosed(
                  CommandLine(CommandLine::ARGUMENTS_ONLY)));

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2));
}

TEST_F(ChromeMainTest, ReuseBrowserInstanceWhenOpeningFile) {
  include_testing_id_ = false;

  FilePath test_file = test_data_directory_.AppendASCII("empty.html");

  CommandLine command_line(CommandLine::ARGUMENTS_ONLY);
  command_line.AppendArgPath(test_file);
  ASSERT_TRUE(LaunchAnotherBrowserBlockUntilClosed(command_line));

  ASSERT_TRUE(automation()->IsURLDisplayed(net::FilePathToFileURL(test_file)));
}

#endif  // !OS_MACOSX
<commit_msg>GTTF: Remove flaky and/or useless UI tests.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/ui/ui_test.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "net/base/net_util.h"

typedef UITest ChromeMainTest;

#if !defined(OS_MACOSX)
// These tests don't apply to the Mac version; see
// LaunchAnotherBrowserBlockUntilClosed for details.

// Make sure that the second invocation creates a new window.
TEST_F(ChromeMainTest, SecondLaunch) {
  include_testing_id_ = false;

  ASSERT_TRUE(LaunchAnotherBrowserBlockUntilClosed(
                  CommandLine(CommandLine::ARGUMENTS_ONLY)));

  ASSERT_TRUE(automation()->WaitForWindowCountToBecome(2));
}

TEST_F(ChromeMainTest, ReuseBrowserInstanceWhenOpeningFile) {
  include_testing_id_ = false;

  FilePath test_file = test_data_directory_.AppendASCII("empty.html");

  CommandLine command_line(CommandLine::ARGUMENTS_ONLY);
  command_line.AppendArgPath(test_file);
  ASSERT_TRUE(LaunchAnotherBrowserBlockUntilClosed(command_line));

  ASSERT_TRUE(automation()->IsURLDisplayed(net::FilePathToFileURL(test_file)));
}
#endif  // !OS_MACOSX
<|endoftext|>


<commit_before>#include "flat_control.h"
//#include "traj_control.h"
#include "gamma.h"
#include "saturate.h"
#include <time.h>

#define DEGREE 5

//Controller proportions
#define KPX 1
#define KDX 2
#define KPY 1
#define KDY 2

#define CMD_RATE .3

using namespace alglib;
using namespace PlayerCc;

flat_control::flat_control(PlayerClient * sourceClient,
			   Position2dProxy * sourcePos,
			   double * endGoal,double tol,
			   PlayerClient * sinkClient,
			   Position2dProxy * sinkPos,
			   double vmax,double omegamax,double vmin,
			   double omegamin){

  this->sourceClient = sourceClient;
  this->sourcePos = sourcePos;

  if(sinkClient == NULL)
    this->sinkClient = this->sourceClient;
  else
    this->sinkClient = sinkClient;
  if(sinkPos == NULL)
    this->sinkPos = this->sourcePos;
  else
    this->sinkPos = sinkPos;

  this->endGoal[0] = endGoal[0];
  this->endGoal[1] = endGoal[1];

  this->tol = tol;
  this->vmax = vmax;
  this->wmax = omegamax;
  this->vmin = vmin;
  this->wmin = omegamin;

  /*
  this->xCurrent = new barycentricinterpolant();
  this->yCurrent = new barycentricinterpolant();
  this->xNext = new barycentricinterpolant();
  this->yNext = new barycentricinterpolant();
  */

  this->xCurrent = new spline1dinterpolant();
  this->yCurrent = new spline1dinterpolant();
  this->xNext = new spline1dinterpolant();
  this->yNext = new spline1dinterpolant();

  this->sourceClient->Read();
  this->pose[0] = this->sourcePos->GetXPos();
  this->pose[1] = this->sourcePos->GetYPos();
  this->pose[2] = this->sourcePos->GetYaw();

  this->first = true;
}

void flat_control::preProcess(double time,double ** path, double ** pathDeriv,
			      int steps){
  this->nextDuration = time;
  //Copy the path into arrays
  real_1d_array x,y,t,weights,tc,xc,yc,dx,dy;
  x.setlength(steps+1);
  y.setlength(steps+1);
  dx.setlength(steps+1);
  dy.setlength(steps+1);
  t.setlength(steps+1);
  weights.setlength(steps+1);

  double dt = time/static_cast<double>(steps);
  for(int i(0); i<steps+1; i++){
    t[i] = (i)*dt;
    x[i] = path[i][0];
    y[i] = path[i][1];
    dx[i] = pathDeriv[i][0];
    dy[i] = pathDeriv[i][1];
    weights[i] = 1;
  }

  /*
  //put constraints on the endpoint
  tc.setlength(2);
  xc.setlength(2);
  yc.setlength(2);

  tc[0] = time;
  tc[1] = 0;

  xc[0] = path[steps][0];
  xc[1] = path[0][0];

  yc[0] = path[steps][1];
  yc[1] = path[0][1];

  integer_1d_array type("[0,0]");
  int info;
  barycentricfitreport rep;

  barycentricfitfloaterhormannwc(t,x,weights,t.length(),tc,xc,type,tc.length(),DEGREE,info,*this->xNext,rep);
  barycentricfitfloaterhormannwc(t,y,weights,t.length(),tc,yc,type,tc.length(),DEGREE,info,*this->yNext,rep);
  */

  spline1dbuildhermite(t,x,dx,*this->xNext);
  spline1dbuildhermite(t,y,dy,*this->yNext);

}

void flat_control::operator()(){

  *this->xCurrent = *this->xNext;
  *this->yCurrent = *this->yNext;
  this->currDuration = this->nextDuration;

  //std::cout << "path = [";
  //this->goal[0] = barycentriccalc(*this->xCurrent,this->currDuration);
  //this->goal[1] = barycentriccalc(*this->yCurrent,this->currDuration);
  this->goal[0] = spline1dcalc(*this->xCurrent,this->currDuration);
  this->goal[1] = spline1dcalc(*this->yCurrent,this->currDuration);

  gettimeofday(&this->start,NULL);
  this->startTime = start.tv_sec + start.tv_usec/1000000.;
  this->currTime = this->startTime;
  this->prevTime = this->startTime;

  while(this->currTime - this->startTime < this->currDuration
	&& gamma(this->pose,this->goal,2) > this->tol*this->tol){
    this->dt = this->currTime - this->prevTime;

    /*
    barycentricdiff2(*this->xCurrent,this->currTime-this->startTime,
		     this->desiredX[0],this->desiredV[0],this->desiredA[0]);
    barycentricdiff2(*this->yCurrent,this->currTime-this->startTime,
		     this->desiredX[1],this->desiredV[1],this->desiredA[1]);
    */
    spline1ddiff(*this->xCurrent,this->currTime-this->startTime,
		     this->desiredX[0],this->desiredV[0],this->desiredA[0]);
    spline1ddiff(*this->yCurrent,this->currTime-this->startTime,
		     this->desiredX[1],this->desiredV[1],this->desiredA[1]);

    std::cout << desiredX[0] << "," << desiredX[1];
    std::cout << "," << desiredV[0] << "," << desiredV[1];
    std::cout << "," << desiredA[0] << "," << desiredA[1];
    std::cout << "," << this->currTime-this->startTime << std::endl;
    //std::cout << "desired x: " << desiredX[0] << " desired y: " << desiredX[1] << std::endl;

    this->sourceClient->Read();
    this->pose[0] = this->sourcePos->GetXPos();
    this->pose[1] = this->sourcePos->GetYPos();
    this->pose[2] = this->sourcePos->GetYaw();
    //std::cout << pose[0] << "," << pose[1] << ";";
    //if(pose[2] <= 0)
    //pose[2] += 2*M_PI;
    //std::cout << pose[2] << std::endl;

    if(gamma(this->pose,this->endGoal,2) < this->tol*this->tol){
      this->sinkPos->SetSpeed(0,0);
      break;
    }

    if(this->first){
      //std::cout << "HEREHEREHEREHERE\n";
      this->first = false;
      this->currVel[0] = this->desiredV[0];
      this->currVel[1] = this->desiredV[1];
    }
    else{
      this->currVel[0] = this->sourcePos->GetXSpeed()*cos(this->pose[2]);
      this->currVel[1] = this->sourcePos->GetXSpeed()*sin(this->pose[2]);
      //currVel[0] = prevVel*cos(pose[2])*((rand()-rand())
      //				   /static_cast<double>(RAND_MAX));
      //currVel[1] = prevVel*sin(pose[2])*((rand()-rand())
      //				   /static_cast<double>(RAND_MAX));

    }

    //std::cout << "currvel: " <<currVel[0] << "," << currVel[1] << std::endl;

    this->u[0] = this->desiredA[0] + KPX*(this->desiredX[0] - this->pose[0] ) +
      KDX*(this->desiredV[0] - this->currVel[0]);
    this->u[1] = this->desiredA[1] + KPX*(this->desiredX[1] - this->pose[1] ) +
      KDX*(this->desiredV[1] - this->currVel[1]);

    //std::cout << "u: " <<u[0] << "," << u[1] << std::endl;

    this->acc = this->u[0]*cos(this->pose[2]) + this->u[1]*sin(this->pose[2]);
    v = sqrt(gamma(this->currVel,2)) + this->acc*this->dt;
    omega = (this->u[1]*cos(this->pose[2])-this->u[0]*sin(this->pose[2]))/
      (this->v);

    //std::cout << currVel[0] << "," << currVel[1] << std::endl;
    //std::cout << sin(pose[2]) << std::endl;

    saturate(&this->v,this->vmax,this->vmin);
    //Positive velocities only, thank you very much.
    this->v = this->v > 0 ? this->v : 0;
    saturate(&this->omega,this->wmax,this->wmin);

    this->sinkPos->SetSpeed(this->v,this->omega);

    //std::cout << "vel: " << v << " omega: " << omega << std::endl;

    this->prevTime = this->currTime;
    do{
      usleep(200);
      gettimeofday(&this->now,NULL);
      this->currTime = this->now.tv_sec + this->now.tv_usec/1000000.;
    }while(this->currTime-this->prevTime < CMD_RATE);

  }
  //std::cout << "DONE!\n";
  //std::cout << "Time used: " << currTime - startTime << std::endl;
  //std::cout << "];\n";
}

<commit_msg>Updated timing<commit_after>#include "flat_control.h"
//#include "traj_control.h"
#include "gamma.h"
#include "saturate.h"
#include <time.h>

#define DEGREE 5

//Controller proportions
#define KPX 1
#define KDX 2
#define KPY 1
#define KDY 2

#define CMD_RATE .3

using namespace alglib;
using namespace PlayerCc;

flat_control::flat_control(PlayerClient * sourceClient,
			   Position2dProxy * sourcePos,
			   double * endGoal,double tol,
			   PlayerClient * sinkClient,
			   Position2dProxy * sinkPos,
			   double vmax,double omegamax,double vmin,
			   double omegamin){

  this->sourceClient = sourceClient;
  this->sourcePos = sourcePos;

  if(sinkClient == NULL)
    this->sinkClient = this->sourceClient;
  else
    this->sinkClient = sinkClient;
  if(sinkPos == NULL)
    this->sinkPos = this->sourcePos;
  else
    this->sinkPos = sinkPos;

  this->endGoal[0] = endGoal[0];
  this->endGoal[1] = endGoal[1];

  this->tol = tol;
  this->vmax = vmax;
  this->wmax = omegamax;
  this->vmin = vmin;
  this->wmin = omegamin;

  /*
  this->xCurrent = new barycentricinterpolant();
  this->yCurrent = new barycentricinterpolant();
  this->xNext = new barycentricinterpolant();
  this->yNext = new barycentricinterpolant();
  */

  this->xCurrent = new spline1dinterpolant();
  this->yCurrent = new spline1dinterpolant();
  this->xNext = new spline1dinterpolant();
  this->yNext = new spline1dinterpolant();

  this->sourceClient->Read();
  this->pose[0] = this->sourcePos->GetXPos();
  this->pose[1] = this->sourcePos->GetYPos();
  this->pose[2] = this->sourcePos->GetYaw();

  this->first = true;
}

void flat_control::preProcess(double time,double ** path, double ** pathDeriv,
			      int steps){
  this->nextDuration = time;
  //Copy the path into arrays
  real_1d_array x,y,t,weights,tc,xc,yc,dx,dy;
  x.setlength(steps+1);
  y.setlength(steps+1);
  dx.setlength(steps+1);
  dy.setlength(steps+1);
  t.setlength(steps+1);
  weights.setlength(steps+1);

  double dt = time/static_cast<double>(steps);
  for(int i(0); i<steps+1; i++){
    t[i] = (i)*dt;
    x[i] = path[i][0];
    y[i] = path[i][1];
    dx[i] = pathDeriv[i][0];
    dy[i] = pathDeriv[i][1];
    weights[i] = 1;
  }

  /*
  //put constraints on the endpoint
  tc.setlength(2);
  xc.setlength(2);
  yc.setlength(2);

  tc[0] = time;
  tc[1] = 0;

  xc[0] = path[steps][0];
  xc[1] = path[0][0];

  yc[0] = path[steps][1];
  yc[1] = path[0][1];

  integer_1d_array type("[0,0]");
  int info;
  barycentricfitreport rep;

  barycentricfitfloaterhormannwc(t,x,weights,t.length(),tc,xc,type,tc.length(),DEGREE,info,*this->xNext,rep);
  barycentricfitfloaterhormannwc(t,y,weights,t.length(),tc,yc,type,tc.length(),DEGREE,info,*this->yNext,rep);
  */

  spline1dbuildhermite(t,x,dx,*this->xNext);
  spline1dbuildhermite(t,y,dy,*this->yNext);

}

void flat_control::operator()(){

  *this->xCurrent = *this->xNext;
  *this->yCurrent = *this->yNext;
  this->currDuration = this->nextDuration;

  //std::cout << "path = [";
  //this->goal[0] = barycentriccalc(*this->xCurrent,this->currDuration);
  //this->goal[1] = barycentriccalc(*this->yCurrent,this->currDuration);
  this->goal[0] = spline1dcalc(*this->xCurrent,this->currDuration);
  this->goal[1] = spline1dcalc(*this->yCurrent,this->currDuration);

  gettimeofday(&this->start,NULL);
  this->startTime = start.tv_sec + start.tv_usec/1000000.;
  this->currTime = this->startTime;
  this->prevTime = this->startTime;

  while(this->currTime - this->startTime < this->currDuration
	&& gamma(this->pose,this->goal,2) > this->tol*this->tol){

    gettimeofday(&this->now,NULL);
    this->currTime = this->now.tv_sec + this->now.tv_usec/1000000.;

    this->dt = this->currTime - this->prevTime;

    /*
    barycentricdiff2(*this->xCurrent,this->currTime-this->startTime,
		     this->desiredX[0],this->desiredV[0],this->desiredA[0]);
    barycentricdiff2(*this->yCurrent,this->currTime-this->startTime,
		     this->desiredX[1],this->desiredV[1],this->desiredA[1]);
    */
    spline1ddiff(*this->xCurrent,this->currTime-this->startTime,
		     this->desiredX[0],this->desiredV[0],this->desiredA[0]);
    spline1ddiff(*this->yCurrent,this->currTime-this->startTime,
		     this->desiredX[1],this->desiredV[1],this->desiredA[1]);

    std::cout << desiredX[0] << "," << desiredX[1];
    std::cout << "," << desiredV[0] << "," << desiredV[1];
    std::cout << "," << desiredA[0] << "," << desiredA[1];
    std::cout << "," << this->currTime-this->startTime << std::endl;
    //std::cout << "desired x: " << desiredX[0] << " desired y: " << desiredX[1] << std::endl;

    this->sourceClient->Read();
    this->pose[0] = this->sourcePos->GetXPos();
    this->pose[1] = this->sourcePos->GetYPos();
    this->pose[2] = this->sourcePos->GetYaw();
    //std::cout << pose[0] << "," << pose[1] << ";";
    //if(pose[2] <= 0)
    //pose[2] += 2*M_PI;
    //std::cout << pose[2] << std::endl;

    if(gamma(this->pose,this->endGoal,2) < this->tol*this->tol){
      this->sinkPos->SetSpeed(0,0);
      break;
    }

    if(this->first){
      //std::cout << "HEREHEREHEREHERE\n";
      this->first = false;
      this->currVel[0] = this->desiredV[0];
      this->currVel[1] = this->desiredV[1];
    }
    else{
      this->currVel[0] = this->sourcePos->GetXSpeed()*cos(this->pose[2]);
      this->currVel[1] = this->sourcePos->GetXSpeed()*sin(this->pose[2]);
      //currVel[0] = prevVel*cos(pose[2])*((rand()-rand())
      //				   /static_cast<double>(RAND_MAX));
      //currVel[1] = prevVel*sin(pose[2])*((rand()-rand())
      //				   /static_cast<double>(RAND_MAX));

    }

    //std::cout << "currvel: " <<currVel[0] << "," << currVel[1] << std::endl;

    this->u[0] = this->desiredA[0] + KPX*(this->desiredX[0] - this->pose[0] ) +
      KDX*(this->desiredV[0] - this->currVel[0]);
    this->u[1] = this->desiredA[1] + KPX*(this->desiredX[1] - this->pose[1] ) +
      KDX*(this->desiredV[1] - this->currVel[1]);

    //std::cout << "u: " <<u[0] << "," << u[1] << std::endl;

    this->acc = this->u[0]*cos(this->pose[2]) + this->u[1]*sin(this->pose[2]);
    v = sqrt(gamma(this->currVel,2)) + this->acc*this->dt;
    omega = (this->u[1]*cos(this->pose[2])-this->u[0]*sin(this->pose[2]))/
      (this->v);

    //std::cout << currVel[0] << "," << currVel[1] << std::endl;
    //std::cout << sin(pose[2]) << std::endl;

    saturate(&this->v,this->vmax,this->vmin);
    //Positive velocities only, thank you very much.
    this->v = this->v > 0 ? this->v : 0;
    saturate(&this->omega,this->wmax,this->wmin);

    this->sinkPos->SetSpeed(this->v,this->omega);

    //std::cout << "vel: " << v << " omega: " << omega << std::endl;

    this->prevTime = this->currTime;
    do{
      usleep(200);
      gettimeofday(&this->now,NULL);
      this->currTime = this->now.tv_sec + this->now.tv_usec/1000000.;
    }while(this->currTime-this->prevTime < CMD_RATE);

  }
  //std::cout << "DONE!\n";
  //std::cout << "Time used: " << currTime - startTime << std::endl;
  //std::cout << "];\n";
}

<|endoftext|>


<commit_before>#include "replication/protocol.hpp"

#include "concurrency/coro_fifo.hpp"

namespace replication {

// The 16 bytes conveniently include a \0 at the end.
// 13 is the length of the text.
const char STANDARD_HELLO_MAGIC[16] = "13rethinkdbrepl";

template <class T> struct stream_type { typedef scoped_malloc<T> type; };
template <> struct stream_type<net_sarc_t> { typedef stream_pair<net_sarc_t> type; };
template <> struct stream_type<net_append_t> { typedef stream_pair<net_append_t> type; };
template <> struct stream_type<net_prepend_t> { typedef stream_pair<net_prepend_t> type; };
template <> struct stream_type<net_backfill_set_t> { typedef stream_pair<net_backfill_set_t> type; };

size_t objsize(UNUSED const net_introduce_t *buf) { return sizeof(net_introduce_t); }
size_t objsize(UNUSED const net_backfill_t *buf) { return sizeof(net_backfill_t); }
size_t objsize(UNUSED const net_backfill_complete_t *buf) { return sizeof(net_backfill_complete_t); }
size_t objsize(UNUSED const net_backfill_delete_everything_t *buf) { return sizeof(net_backfill_delete_everything_t); }
size_t objsize(UNUSED const net_nop_t *buf) { return sizeof(net_nop_t); }
size_t objsize(const net_get_cas_t *buf) { return sizeof(net_get_cas_t) + buf->key_size; }
size_t objsize(const net_incr_t *buf) { return sizeof(net_incr_t) + buf->key_size; }
size_t objsize(const net_decr_t *buf) { return sizeof(net_decr_t) + buf->key_size; }
size_t objsize(const net_delete_t *buf) { return sizeof(net_delete_t) + buf->key_size; }
size_t objsize(const net_sarc_t *buf) { return sizeof(net_sarc_t) + buf->key_size + buf->value_size; }
size_t objsize(const net_append_t *buf) { return sizeof(net_append_t) + buf->key_size + buf->value_size; }
size_t objsize(const net_prepend_t *buf) { return sizeof(net_prepend_t) + buf->key_size + buf->value_size; }
size_t objsize(const net_backfill_set_t *buf) { return sizeof(net_backfill_set_t) + buf->key_size + buf->value_size; }
size_t objsize(const net_backfill_delete_t *buf) { return sizeof(net_backfill_delete_t) + buf->key_size; }

namespace internal {

template <class T>
void check_pass(message_callback_t *receiver, const char *buf, size_t realsize) {
    if (sizeof(T) <= realsize && objsize(reinterpret_cast<const T *>(buf)) == realsize) {
        typename stream_type<T>::type b(buf, buf + realsize);
        receiver->send(b);
    } else {
        debugf("realsize: %zu sizeof(T): %zu objsize: %zu\n", realsize, sizeof(T), objsize(reinterpret_cast<const T *>(buf)));
        throw protocol_exc_t("message wrong length for message code");
    }
}

template <class T>
tracker_obj_t *check_value_streamer(message_callback_t *receiver, const char *buf, size_t size) {
    if (sizeof(T) <= size
        && sizeof(T) + reinterpret_cast<const T *>(buf)->key_size <= size) {

        stream_pair<T> spair(buf, buf + size, reinterpret_cast<const T *>(buf)->value_size);
        size_t m = size - sizeof(T) - reinterpret_cast<const T *>(buf)->key_size;

        void (message_callback_t::*fn)(typename stream_type<T>::type&) = &message_callback_t::send;

        char *p = spair.stream->peek() + m;

        return new tracker_obj_t(boost::bind(fn, receiver, spair), p, reinterpret_cast<const T *>(buf)->value_size - m);

    } else {
        throw protocol_exc_t("message too short for message code and key size");
    }
}

void replication_stream_handler_t::stream_part(const char *buf, size_t size) {
    if (!saw_first_part_) {
        uint8_t msgcode = *reinterpret_cast<const uint8_t *>(buf);
        ++buf;
        --size;

        switch (msgcode) {
        case INTRODUCE: check_pass<net_introduce_t>(receiver_, buf, size); break;
        case BACKFILL: check_pass<net_backfill_t>(receiver_, buf, size); break;
        case BACKFILL_COMPLETE: check_pass<net_backfill_complete_t>(receiver_, buf, size); break;
        case BACKFILL_DELETE_EVERYTHING: check_pass<net_backfill_delete_everything_t>(receiver_, buf, size); break;
        case NOP: check_pass<net_nop_t>(receiver_, buf, size); break;
        case GET_CAS: check_pass<net_get_cas_t>(receiver_, buf, size); break;
        case SARC: tracker_obj_ = check_value_streamer<net_sarc_t>(receiver_, buf, size); break;
        case INCR: check_pass<net_incr_t>(receiver_, buf, size); break;
        case DECR: check_pass<net_decr_t>(receiver_, buf, size); break;
        case APPEND: tracker_obj_ = check_value_streamer<net_append_t>(receiver_, buf, size); break;
        case PREPEND: tracker_obj_ = check_value_streamer<net_prepend_t>(receiver_, buf, size); break;
        case DELETE: check_pass<net_delete_t>(receiver_, buf, size); break;
        case BACKFILL_SET: tracker_obj_ = check_value_streamer<net_backfill_set_t>(receiver_, buf, size); break;
        case BACKFILL_DELETE: check_pass<net_backfill_delete_t>(receiver_, buf, size); break;
        default: throw protocol_exc_t("invalid message code");
        }

        saw_first_part_ = true;
    } else {
        if (tracker_obj_ == NULL) {
            throw protocol_exc_t("multipart message received for an inappropriate message type");
        }
        if (size > tracker_obj_->bufsize) {
            throw protocol_exc_t("buffer overflows value size");
        }
        memcpy(tracker_obj_->buf, buf, size);
        tracker_obj_->buf += size;
        tracker_obj_->bufsize -= size;
    }
}

void replication_stream_handler_t::end_of_stream() {
    rassert(saw_first_part_);
    if (tracker_obj_) {
        tracker_obj_->function();
        delete tracker_obj_;
        tracker_obj_ = NULL;
    }
}

void replication_connection_handler_t::process_hello_message(net_hello_t buf) {
    rassert(16 == sizeof(STANDARD_HELLO_MAGIC));
    if (0 != memcmp(buf.hello_magic, STANDARD_HELLO_MAGIC, sizeof(STANDARD_HELLO_MAGIC))) {
        throw protocol_exc_t("bad hello magic");  // TODO details
    }

    if (buf.replication_protocol_version != 1) {
        throw protocol_exc_t("bad protocol version");  // TODO details
    }

    receiver_->hello(buf);
}

}  // namespace internal

template <class net_struct_type>
void repli_stream_t::sendobj(uint8_t msgcode, net_struct_type *msg) {

    size_t obsize = objsize(msg);

    if (obsize + sizeof(net_header_t) + 1 <= MAX_MESSAGE_SIZE) {
        net_header_t hdr;
        hdr.msgsize = sizeof(net_header_t) + 1 + obsize;
        hdr.message_multipart_aspect = SMALL;

        mutex_acquisition_t ak(&outgoing_mutex_);

        try_write(&hdr, sizeof(net_header_t));
        rassert(1 == sizeof(msgcode));
        try_write(&msgcode, sizeof(msgcode));
        try_write(msg, obsize);
    } else {
        net_multipart_header_t hdr;
        hdr.msgsize = MAX_MESSAGE_SIZE;
        hdr.message_multipart_aspect = FIRST;
        hdr.ident = 1;        // TODO: This is an obvious bug.

        size_t offset = MAX_MESSAGE_SIZE - (sizeof(net_multipart_header_t) + 1);

        {
            mutex_acquisition_t ak(&outgoing_mutex_);
            try_write(&hdr, sizeof(net_multipart_header_t));
            rassert(sizeof(msgcode) == 1);
            try_write(&msgcode, sizeof(msgcode));
            try_write(msg, offset);
        }

        char *buf = reinterpret_cast<char *>(msg);

        while (offset + MAX_MESSAGE_SIZE < obsize) {
            mutex_acquisition_t ak(&outgoing_mutex_);
            hdr.message_multipart_aspect = MIDDLE;
            try_write(&hdr, sizeof(net_multipart_header_t));
            try_write(buf + offset, MAX_MESSAGE_SIZE);
            offset += MAX_MESSAGE_SIZE;
        }

        {
            rassert(obsize - offset <= MAX_MESSAGE_SIZE);
            mutex_acquisition_t ak(&outgoing_mutex_);
            hdr.message_multipart_aspect = LAST;
            try_write(&hdr, sizeof(net_multipart_header_t));
            try_write(buf + offset, obsize - offset);
        }
    }
}

template <class net_struct_type>
void repli_stream_t::sendobj(uint8_t msgcode, net_struct_type *msg, const char *key, unique_ptr_t<data_provider_t> data) {
    rassert(msg->value_size == data->get_size());

    size_t bufsize = objsize(msg);
    scoped_malloc<char> buf(bufsize);
    memcpy(buf.get(), msg, sizeof(net_struct_type));
    memcpy(buf.get() + sizeof(net_struct_type), key, msg->key_size);

    /* We guarantee that if data->get_data_into_buffers() fails, we rethrow the exception without
    sending anything over the wire. */
    buffer_group_t group;
    group.add_buffer(data->get_size(), buf.get() + sizeof(net_struct_type) + msg->key_size);

    // TODO: This could theoretically block and that could cause
    // reordering of sets.  The fact that it doesn't block is just a
    // function of whatever data provider which we happen to use.
    data->get_data_into_buffers(&group);

    sendobj(msgcode, reinterpret_cast<net_struct_type *>(buf.get()));
}

void repli_stream_t::send(net_introduce_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(INTRODUCE, msg);
}

void repli_stream_t::send(net_backfill_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(BACKFILL, msg);
}

void repli_stream_t::send(net_backfill_complete_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(BACKFILL_COMPLETE, msg);
}

void repli_stream_t::send(net_backfill_delete_everything_t msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(BACKFILL_DELETE_EVERYTHING, &msg);
}

void repli_stream_t::send(net_get_cas_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(GET_CAS, msg);
}

void repli_stream_t::send(net_sarc_t *msg, const char *key, unique_ptr_t<data_provider_t> value) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(SARC, msg, key, value);
}

void repli_stream_t::send(net_backfill_set_t *msg, const char *key, unique_ptr_t<data_provider_t> value) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(BACKFILL_SET, msg, key, value);
}

void repli_stream_t::send(net_incr_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(INCR, msg);
}

void repli_stream_t::send(net_decr_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(DECR, msg);
}

void repli_stream_t::send(net_append_t *msg, const char *key, unique_ptr_t<data_provider_t> value) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(APPEND, msg, key, value);
}

void repli_stream_t::send(net_prepend_t *msg, const char *key, unique_ptr_t<data_provider_t> value) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(PREPEND, msg, key, value);
}

void repli_stream_t::send(net_delete_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(DELETE, msg);
}

void repli_stream_t::send(net_backfill_delete_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(BACKFILL_DELETE, msg);
}

void repli_stream_t::send(net_nop_t msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(NOP, &msg);
}

void repli_stream_t::send_hello(UNUSED const mutex_acquisition_t& evidence_of_acquisition) {

    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);

    net_hello_t msg;
    rassert(sizeof(msg.hello_magic) == 16);
    rassert(sizeof(STANDARD_HELLO_MAGIC) == 16);
    memcpy(msg.hello_magic, STANDARD_HELLO_MAGIC, 16);
    msg.replication_protocol_version = 1;

    try_write(&msg, sizeof(msg));
}

perfmon_duration_sampler_t master_write("master_write", secs_to_ticks(1.0));

void repli_stream_t::try_write(const void *data, size_t size) {
    try {
        block_pm_duration set_timer(&master_write);
        conn_->write(data, size);
    } catch (tcp_conn_t::write_closed_exc_t &e) {
        /* Master died; we happened to be mid-write at the time. A tcp_conn_t::read_closed_exc_t
        will be thrown somewhere and that will cause us to shut down. So we can ignore this
        exception. */
    }
}

}  // namespace replication
<commit_msg>Put in a hack where we acquire the mutex_acquisition_t for the whole message.<commit_after>#include "replication/protocol.hpp"

#include "concurrency/coro_fifo.hpp"

namespace replication {

// The 16 bytes conveniently include a \0 at the end.
// 13 is the length of the text.
const char STANDARD_HELLO_MAGIC[16] = "13rethinkdbrepl";

template <class T> struct stream_type { typedef scoped_malloc<T> type; };
template <> struct stream_type<net_sarc_t> { typedef stream_pair<net_sarc_t> type; };
template <> struct stream_type<net_append_t> { typedef stream_pair<net_append_t> type; };
template <> struct stream_type<net_prepend_t> { typedef stream_pair<net_prepend_t> type; };
template <> struct stream_type<net_backfill_set_t> { typedef stream_pair<net_backfill_set_t> type; };

size_t objsize(UNUSED const net_introduce_t *buf) { return sizeof(net_introduce_t); }
size_t objsize(UNUSED const net_backfill_t *buf) { return sizeof(net_backfill_t); }
size_t objsize(UNUSED const net_backfill_complete_t *buf) { return sizeof(net_backfill_complete_t); }
size_t objsize(UNUSED const net_backfill_delete_everything_t *buf) { return sizeof(net_backfill_delete_everything_t); }
size_t objsize(UNUSED const net_nop_t *buf) { return sizeof(net_nop_t); }
size_t objsize(const net_get_cas_t *buf) { return sizeof(net_get_cas_t) + buf->key_size; }
size_t objsize(const net_incr_t *buf) { return sizeof(net_incr_t) + buf->key_size; }
size_t objsize(const net_decr_t *buf) { return sizeof(net_decr_t) + buf->key_size; }
size_t objsize(const net_delete_t *buf) { return sizeof(net_delete_t) + buf->key_size; }
size_t objsize(const net_sarc_t *buf) { return sizeof(net_sarc_t) + buf->key_size + buf->value_size; }
size_t objsize(const net_append_t *buf) { return sizeof(net_append_t) + buf->key_size + buf->value_size; }
size_t objsize(const net_prepend_t *buf) { return sizeof(net_prepend_t) + buf->key_size + buf->value_size; }
size_t objsize(const net_backfill_set_t *buf) { return sizeof(net_backfill_set_t) + buf->key_size + buf->value_size; }
size_t objsize(const net_backfill_delete_t *buf) { return sizeof(net_backfill_delete_t) + buf->key_size; }

namespace internal {

template <class T>
void check_pass(message_callback_t *receiver, const char *buf, size_t realsize) {
    if (sizeof(T) <= realsize && objsize(reinterpret_cast<const T *>(buf)) == realsize) {
        typename stream_type<T>::type b(buf, buf + realsize);
        receiver->send(b);
    } else {
        debugf("realsize: %zu sizeof(T): %zu objsize: %zu\n", realsize, sizeof(T), objsize(reinterpret_cast<const T *>(buf)));
        throw protocol_exc_t("message wrong length for message code");
    }
}

template <class T>
tracker_obj_t *check_value_streamer(message_callback_t *receiver, const char *buf, size_t size) {
    if (sizeof(T) <= size
        && sizeof(T) + reinterpret_cast<const T *>(buf)->key_size <= size) {

        stream_pair<T> spair(buf, buf + size, reinterpret_cast<const T *>(buf)->value_size);
        size_t m = size - sizeof(T) - reinterpret_cast<const T *>(buf)->key_size;

        void (message_callback_t::*fn)(typename stream_type<T>::type&) = &message_callback_t::send;

        char *p = spair.stream->peek() + m;

        return new tracker_obj_t(boost::bind(fn, receiver, spair), p, reinterpret_cast<const T *>(buf)->value_size - m);

    } else {
        throw protocol_exc_t("message too short for message code and key size");
    }
}

void replication_stream_handler_t::stream_part(const char *buf, size_t size) {
    if (!saw_first_part_) {
        uint8_t msgcode = *reinterpret_cast<const uint8_t *>(buf);
        ++buf;
        --size;

        switch (msgcode) {
        case INTRODUCE: check_pass<net_introduce_t>(receiver_, buf, size); break;
        case BACKFILL: check_pass<net_backfill_t>(receiver_, buf, size); break;
        case BACKFILL_COMPLETE: check_pass<net_backfill_complete_t>(receiver_, buf, size); break;
        case BACKFILL_DELETE_EVERYTHING: check_pass<net_backfill_delete_everything_t>(receiver_, buf, size); break;
        case NOP: check_pass<net_nop_t>(receiver_, buf, size); break;
        case GET_CAS: check_pass<net_get_cas_t>(receiver_, buf, size); break;
        case SARC: tracker_obj_ = check_value_streamer<net_sarc_t>(receiver_, buf, size); break;
        case INCR: check_pass<net_incr_t>(receiver_, buf, size); break;
        case DECR: check_pass<net_decr_t>(receiver_, buf, size); break;
        case APPEND: tracker_obj_ = check_value_streamer<net_append_t>(receiver_, buf, size); break;
        case PREPEND: tracker_obj_ = check_value_streamer<net_prepend_t>(receiver_, buf, size); break;
        case DELETE: check_pass<net_delete_t>(receiver_, buf, size); break;
        case BACKFILL_SET: tracker_obj_ = check_value_streamer<net_backfill_set_t>(receiver_, buf, size); break;
        case BACKFILL_DELETE: check_pass<net_backfill_delete_t>(receiver_, buf, size); break;
        default: throw protocol_exc_t("invalid message code");
        }

        saw_first_part_ = true;
    } else {
        if (tracker_obj_ == NULL) {
            throw protocol_exc_t("multipart message received for an inappropriate message type");
        }
        if (size > tracker_obj_->bufsize) {
            throw protocol_exc_t("buffer overflows value size");
        }
        memcpy(tracker_obj_->buf, buf, size);
        tracker_obj_->buf += size;
        tracker_obj_->bufsize -= size;
    }
}

void replication_stream_handler_t::end_of_stream() {
    rassert(saw_first_part_);
    if (tracker_obj_) {
        tracker_obj_->function();
        delete tracker_obj_;
        tracker_obj_ = NULL;
    }
}

void replication_connection_handler_t::process_hello_message(net_hello_t buf) {
    rassert(16 == sizeof(STANDARD_HELLO_MAGIC));
    if (0 != memcmp(buf.hello_magic, STANDARD_HELLO_MAGIC, sizeof(STANDARD_HELLO_MAGIC))) {
        throw protocol_exc_t("bad hello magic");  // TODO details
    }

    if (buf.replication_protocol_version != 1) {
        throw protocol_exc_t("bad protocol version");  // TODO details
    }

    receiver_->hello(buf);
}

}  // namespace internal

template <class net_struct_type>
void repli_stream_t::sendobj(uint8_t msgcode, net_struct_type *msg) {

    size_t obsize = objsize(msg);

    if (obsize + sizeof(net_header_t) + 1 <= MAX_MESSAGE_SIZE) {
        net_header_t hdr;
        hdr.msgsize = sizeof(net_header_t) + 1 + obsize;
        hdr.message_multipart_aspect = SMALL;

        mutex_acquisition_t ak(&outgoing_mutex_);

        try_write(&hdr, sizeof(net_header_t));
        rassert(1 == sizeof(msgcode));
        try_write(&msgcode, sizeof(msgcode));
        try_write(msg, obsize);
    } else {
        // Right now we don't really split up messages into
        // submessages.
        mutex_acquisition_t ak(&outgoing_mutex_);

        net_multipart_header_t hdr;
        hdr.msgsize = MAX_MESSAGE_SIZE;
        hdr.message_multipart_aspect = FIRST;
        hdr.ident = 1;        // TODO: This is an obvious bug, when we can split up our messages (but right now it is fine because we hold the mutex_acquisition_t the whole time).

        size_t offset = MAX_MESSAGE_SIZE - (sizeof(net_multipart_header_t) + 1);

        {
            //            mutex_acquisition_t ak(&outgoing_mutex_);
            try_write(&hdr, sizeof(net_multipart_header_t));
            rassert(sizeof(msgcode) == 1);
            try_write(&msgcode, sizeof(msgcode));
            try_write(msg, offset);
        }

        char *buf = reinterpret_cast<char *>(msg);

        while (offset + MAX_MESSAGE_SIZE < obsize) {
            //            mutex_acquisition_t ak(&outgoing_mutex_);
            hdr.message_multipart_aspect = MIDDLE;
            try_write(&hdr, sizeof(net_multipart_header_t));
            try_write(buf + offset, MAX_MESSAGE_SIZE);
            offset += MAX_MESSAGE_SIZE;
        }

        {
            rassert(obsize - offset <= MAX_MESSAGE_SIZE);
            //            mutex_acquisition_t ak(&outgoing_mutex_);
            hdr.message_multipart_aspect = LAST;
            try_write(&hdr, sizeof(net_multipart_header_t));
            try_write(buf + offset, obsize - offset);
        }
    }
}

template <class net_struct_type>
void repli_stream_t::sendobj(uint8_t msgcode, net_struct_type *msg, const char *key, unique_ptr_t<data_provider_t> data) {
    rassert(msg->value_size == data->get_size());

    size_t bufsize = objsize(msg);
    scoped_malloc<char> buf(bufsize);
    memcpy(buf.get(), msg, sizeof(net_struct_type));
    memcpy(buf.get() + sizeof(net_struct_type), key, msg->key_size);

    /* We guarantee that if data->get_data_into_buffers() fails, we rethrow the exception without
    sending anything over the wire. */
    buffer_group_t group;
    group.add_buffer(data->get_size(), buf.get() + sizeof(net_struct_type) + msg->key_size);

    // TODO: This could theoretically block and that could cause
    // reordering of sets.  The fact that it doesn't block is just a
    // function of whatever data provider which we happen to use.
    data->get_data_into_buffers(&group);

    sendobj(msgcode, reinterpret_cast<net_struct_type *>(buf.get()));
}

void repli_stream_t::send(net_introduce_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(INTRODUCE, msg);
}

void repli_stream_t::send(net_backfill_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(BACKFILL, msg);
}

void repli_stream_t::send(net_backfill_complete_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(BACKFILL_COMPLETE, msg);
}

void repli_stream_t::send(net_backfill_delete_everything_t msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(BACKFILL_DELETE_EVERYTHING, &msg);
}

void repli_stream_t::send(net_get_cas_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(GET_CAS, msg);
}

void repli_stream_t::send(net_sarc_t *msg, const char *key, unique_ptr_t<data_provider_t> value) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(SARC, msg, key, value);
}

void repli_stream_t::send(net_backfill_set_t *msg, const char *key, unique_ptr_t<data_provider_t> value) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(BACKFILL_SET, msg, key, value);
}

void repli_stream_t::send(net_incr_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(INCR, msg);
}

void repli_stream_t::send(net_decr_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(DECR, msg);
}

void repli_stream_t::send(net_append_t *msg, const char *key, unique_ptr_t<data_provider_t> value) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(APPEND, msg, key, value);
}

void repli_stream_t::send(net_prepend_t *msg, const char *key, unique_ptr_t<data_provider_t> value) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(PREPEND, msg, key, value);
}

void repli_stream_t::send(net_delete_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(DELETE, msg);
}

void repli_stream_t::send(net_backfill_delete_t *msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(BACKFILL_DELETE, msg);
}

void repli_stream_t::send(net_nop_t msg) {
    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);
    sendobj(NOP, &msg);
}

void repli_stream_t::send_hello(UNUSED const mutex_acquisition_t& evidence_of_acquisition) {

    drain_semaphore_t::lock_t keep_us_alive(&drain_semaphore_);

    net_hello_t msg;
    rassert(sizeof(msg.hello_magic) == 16);
    rassert(sizeof(STANDARD_HELLO_MAGIC) == 16);
    memcpy(msg.hello_magic, STANDARD_HELLO_MAGIC, 16);
    msg.replication_protocol_version = 1;

    try_write(&msg, sizeof(msg));
}

perfmon_duration_sampler_t master_write("master_write", secs_to_ticks(1.0));

void repli_stream_t::try_write(const void *data, size_t size) {
    try {
        block_pm_duration set_timer(&master_write);
        conn_->write(data, size);
    } catch (tcp_conn_t::write_closed_exc_t &e) {
        /* Master died; we happened to be mid-write at the time. A tcp_conn_t::read_closed_exc_t
        will be thrown somewhere and that will cause us to shut down. So we can ignore this
        exception. */
    }
}

}  // namespace replication
<|endoftext|>


<commit_before>/*
 * =====================================================================================
 *
 *       Filename:  third.cpp
 *
 *    Description:  Third glfw application
 *
 *        Version:  1.0
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Sean Jones (SJ), NeuralSandwich@gmail.com
 *        Company:  NeuralSandwich
 *
 * =====================================================================================
 */

#define GLFW_INCLUDE_GLU
#include <GLFW/glfw3.h>
#include <chrono>

using namespace std::chrono;

GLFWwindow* window;

bool running = true;

bool initialise()
{
  // Set Color to cyan
  glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
  //Enable face culling
  glEnable(GL_CULL_FACE);
  return true;
}

//updates the application
void update(double deltaTime)
{
  // Check if escape pressed or window is closed
  running = !glfwGetKey(window, GLFW_KEY_ESCAPE) &&
    !glfwWindowShouldClose(window);
}

//renders the application
void render()
{
  // Clear the screen
  glClear(GL_COLOR_BUFFER_BIT);

  //Set the colour
  glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

  //Render a Quad
  glBegin(GL_TRIANGLE_STRIP);
    // Quad has four vertexes (corners)
    glVertex3f(0.5f, 0.5f, 0.0f);
    glVertex3f(-0.5f, 0.5f, 0.0f);
    glVertex3f(-0.5f, -0.5f, 0.0f);
    glVertex3f(0.5f, -0.5f, 0.0f);
  glEnd();

  // Swap front and back buffers
  glfwSwapBuffers(window);
}

int main(void)
{
    /* Initialize the library */
    if (!glfwInit())
    {
        return -1;
    }

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    //initialise the window
    if (!initialise())
    {
      glfwTerminate();
      return -1;
    }

    // Monitor the elapsed time per frame
    auto currentTimeStamp = system_clock::now();
    auto prevTimeStamp = system_clock::now();

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        // Get current time
        currentTimeStamp = system_clock::now();
        // Calculate elapsed time
        auto elapsed = duration_cast<milliseconds>(currentTimeStamp
            - prevTimeStamp);
        //Convert to fractions of a second
        auto seconds = double(elapsed.count()) / 1000.0;

        // Update Application
        update(seconds);
        //Render scene
        render();

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();

        // set the previous time stamp to current time stamp
        prevTimeStamp = currentTimeStamp;
    } // Main Loop

    glfwTerminate();
    return 0;
}
<commit_msg>Fixed the Triangle strip<commit_after>/*
 * =====================================================================================
 *
 *       Filename:  third.cpp
 *
 *    Description:  Third glfw application
 *
 *        Version:  1.0
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Sean Jones (SJ), NeuralSandwich@gmail.com
 *        Company:  NeuralSandwich
 *
 * =====================================================================================
 */

#define GLFW_INCLUDE_GLU
#include <GLFW/glfw3.h>
#include <chrono>

using namespace std::chrono;

GLFWwindow* window;

bool running = true;

bool initialise()
{
  // Set Color to cyan
  glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
  //Enable face culling
  glEnable(GL_CULL_FACE);
  return true;
}

//updates the application
void update(double deltaTime)
{
  // Check if escape pressed or window is closed
  running = !glfwGetKey(window, GLFW_KEY_ESCAPE) &&
    !glfwWindowShouldClose(window);
}

//renders the application
void render()
{
  // Clear the screen
  glClear(GL_COLOR_BUFFER_BIT);

  //Set the colour
  glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

  //Render a Quad
  glBegin(GL_TRIANGLE_STRIP);
    // Quad has four vertexes (corners)
    // Bottom Right
    glVertex3f(0.5f, -0.5f, 0.0f);
    // Top Right
    glVertex3f(0.5f, 0.5f, 0.0f);
    // Bottom Left
    glVertex3f(-0.5f, -0.5f, 0.0f);
    // Top Left
    glVertex3f(-0.5f, 0.5f, 0.0f);
  glEnd();

  // Swap front and back buffers
  glfwSwapBuffers(window);
}

int main(void)
{
    /* Initialize the library */
    if (!glfwInit())
    {
        return -1;
    }

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    //initialise the window
    if (!initialise())
    {
      glfwTerminate();
      return -1;
    }

    // Monitor the elapsed time per frame
    auto currentTimeStamp = system_clock::now();
    auto prevTimeStamp = system_clock::now();

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        // Get current time
        currentTimeStamp = system_clock::now();
        // Calculate elapsed time
        auto elapsed = duration_cast<milliseconds>(currentTimeStamp
            - prevTimeStamp);
        //Convert to fractions of a second
        auto seconds = double(elapsed.count()) / 1000.0;

        // Update Application
        update(seconds);
        //Render scene
        render();

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();

        // set the previous time stamp to current time stamp
        prevTimeStamp = currentTimeStamp;
    } // Main Loop

    glfwTerminate();
    return 0;
}
<|endoftext|>