<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of meegotouch-controlpanelsoundsettingsapplet.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QDebug>
#include <QStringList>
#include <QFile>
#ifdef HAVE_LIBPROFILE
#include <profiled/libprofile.h>
#endif

#include "qprofilevalue.h"

//#define DEBUG
#define WARNING
#include "debug.h"

#define TO_STRING(string) ((string).toUtf8().constData())

int QProfileValue::nTrackedValues = 0;

QProfileValue::QProfileValue(const QString &key, bool setAllProfiles) :
	QTrackedVariant(key),
	m_setAllProfiles(setAllProfiles)
{
    SYS_DEBUG ("*** key = %s", SYS_STR(key));
	addNotify();
}

QProfileValue::~QProfileValue()
{
	delNotify();
}

void
QProfileValue::notifyValue(const char *profile, const char *key, const char *val, const char *type, QProfileValue *self)
{
	QString compareString;
	Q_UNUSED(val)
	Q_UNUSED(type)

	if (self->key().contains('@'))
		compareString = self->key();
	else {
#ifdef HAVE_LIBPROFILE
		char *currentProfile = profile_get_profile();
		compareString = self->key() + "@" + currentProfile;
		free(currentProfile);
#endif
	}

	if (compareString == (QString(key) + "@" + profile)) {
		self->m_val.clear();
		self->emit_changed();
	}
}

void
QProfileValue::addNotify()
{
#ifdef HAVE_LIBPROFILE
	if (0 == nTrackedValues)
		profile_tracker_init();
	nTrackedValues++;

	profile_track_add_active_cb((profile_track_value_fn_data)notifyValue, this, NULL);
	profile_track_add_change_cb((profile_track_value_fn_data)notifyValue, this, NULL);
#endif
}

void
QProfileValue::delNotify()
{
#ifdef HAVE_LIBPROFILE
	profile_track_remove_active_cb((profile_track_value_fn_data)notifyValue, this);
	profile_track_remove_change_cb((profile_track_value_fn_data)notifyValue, this);

	nTrackedValues--;
	if (0 == nTrackedValues)
		profile_tracker_quit();
#endif
}

void
QProfileValue::realSetValue(const QVariant &newValue)
{
#ifdef HAVE_LIBPROFILE
	m_val.clear();

	QVariant convertedValue = newValue;
	QVariant::Type neededType = QVariant::Invalid;
	QString theKey, theProfile;
	QStringList lsType = getType(theKey, theProfile);

	char *currentProfile = profile_get_profile();
	if (theProfile.isNull())
		theProfile = QString(currentProfile);
	free(currentProfile);

    /*
     *
     */
    stopWatchFiles ();

    SYS_DEBUG ("*** lsType[0] = %s", SYS_STR(lsType[0]));
	if ("SOUNDFILE" == lsType[0]) {
        QString filename;

        filename = newValue.toString();
    SYS_DEBUG ("*** filename  = %s", SYS_STR(filename));
        if (!filename.isEmpty()) {
            bool missing;
            missing = startWatchFile (newValue.toString());
	        SYS_DEBUG ("*** missing = %s", SYS_BOOL(missing));
        }

        neededType = QVariant::String;
    } else if ("STRING" == lsType[0])
		neededType = QVariant::String;
	else if ("INTEGER" == lsType[0])
		neededType = QVariant::Int;
	else if ("BOOLEAN" == lsType[0])
		neededType = QVariant::Bool;
	else if ("DOUBLE" == lsType[0])
		neededType = QVariant::Double;

	if (neededType != QVariant::Invalid && convertedValue.convert(neededType)) {
		if (QVariant::Bool == neededType)
			profile_set_value_as_bool(theProfile.toUtf8().constData(), theKey.toUtf8().constData(), (int)convertedValue.toBool());
		else
		if (QVariant::Int == neededType) {
			profile_set_value_as_int(TO_STRING(theProfile), TO_STRING(theKey), (int)convertedValue.toInt());
        } else
		if (QVariant::Double == neededType)
			profile_set_value_as_double(theProfile.toUtf8().constData(), theKey.toUtf8().constData(), (double)convertedValue.toDouble());
		else
		if (QVariant::String == neededType)
			profile_set_value(theProfile.toUtf8().constData(), theKey.toUtf8().constData(), (char *)convertedValue.toString().toUtf8().constData());
	}

	if (m_setAllProfiles) {
		char **profiles = profile_get_profiles();
		if (profiles) {
			for (int Nix = 0 ; profiles[Nix] != NULL ; Nix++)
				if (theProfile != QString(profiles[Nix]))
					QProfileValue(key() + "@" + QString(profiles[Nix]), false).set(newValue);

			profile_free_profiles(profiles);
			profiles = NULL;
		}
	}
#endif
}

void
QProfileValue::fetchFromBackend()
{
#ifdef HAVE_LIBPROFILE
	QString      theKey, theProfile;
	QStringList  lsType = getType(theKey, theProfile);
	QVariant     var;

    SYS_DEBUG ("*** lsType[0] = %s", SYS_STR(lsType[0]));
    if ("SOUNDFILE" == lsType[0]) {
        char *filename;
        bool  needReread;

        filename = profile_get_value (
                theProfile.isNull() ? NULL : TO_STRING(theProfile),
                TO_STRING(theKey));
        needReread = startWatchFile (filename);

        SYS_DEBUG ("*** needReread = %s", SYS_BOOL(needReread));
	if (needReread) {
            free (filename);
            realSetValue (QVariant (""));
            fetchFromBackend ();

            filename = profile_get_value (
                        theProfile.isNull() ? NULL : TO_STRING(theProfile),
                        TO_STRING(theKey));
            needReread = startWatchFile (filename);

            if (needReread)
            {
                SYS_WARNING ("The current profile refers to"
                             " a non-existant file (%s)!",
                             filename);
            }
        }

        var = QVariant(QString::fromUtf8(filename));
		free(filename);
    } else if ("STRING" == lsType[0]) {
		char *the_value = profile_get_value (
                theProfile.isNull() ? NULL : TO_STRING(theProfile),
                TO_STRING(theKey));

		var = QVariant(QString::fromUtf8(the_value));
		free(the_value);
	} else if ("BOOLEAN" == lsType[0]) {
		var = QVariant((bool)profile_get_value_as_bool(
                theProfile.isNull() ? NULL : TO_STRING(theProfile),
                TO_STRING(theKey)));
    } else if ("INTEGER" == lsType[0]) {
		var = QVariant((int)profile_get_value_as_int(
                theProfile.isNull() ? NULL : TO_STRING(theProfile),
                TO_STRING(theKey)));
    }

	if (!var.isNull())
		m_val = var;
#endif
}

QStringList
QProfileValue::getType(QString &theKey, QString &theProfile)
{
	QStringList    lsType;
#ifdef HAVE_LIBPROFILE
	QStringList    lsKey;
	char          *the_type;

	lsKey = key().split('@');
	theKey = lsKey[0];

	if (lsKey.size() > 1)
		theProfile = lsKey[1];

	the_type = profile_get_type(lsKey[0].toUtf8().constData());
    SYS_DEBUG ("*** %s = %s", SYS_STR(theKey), the_type);

	lsType = QString(the_type).split(' ');
	free(the_type); the_type = NULL;
#endif
	return lsType;
}

QList<QVariant>
QProfileValue::possibleValues(RangeType *p_rangeType)
{
    QList<QVariant> ret;
	QString theKey, theProfile;
	QStringList lsType = getType(theKey, theProfile);

    SYS_DEBUG ("*** p_rangeType = %p");
    SYS_DEBUG ("*** lsType[0]   = %s", SYS_STR(lsType[0]));

	if (p_rangeType)
        *p_rangeType = Invalid;

	if ("SOUNDFILE" == lsType[0] ||
	    "STRING"    == lsType[0]) {

		if (p_rangeType)
            *p_rangeType = List;

		for (int Nix = 1 ; Nix < lsType.size() ; Nix++) {
			ret.append(QVariant(lsType[Nix].remove('"')));
        }
	}
	else
	if ("BOOLEAN" == lsType[0]) {
		if (p_rangeType) (*p_rangeType) = List;
		ret.append(QVariant(false));
		ret.append(QVariant(true));
	}
	else
	if ("INTEGER" == lsType[0]) {
		QVariant lower = QVariant(INT_MIN);
		QVariant upper = QVariant(INT_MAX);

		if (p_rangeType) (*p_rangeType) = Interval;

		if (lsType.size() > 1) {
			QStringList lsInterval = lsType[1].split('-');
			if (lsInterval.size() > 0)
				if (QVariant(lsInterval[0]).canConvert(QVariant::Int))
					lower.setValue(lsInterval[0]);
			if (lsInterval.size() > 1)
				if (QVariant(lsInterval[1]).canConvert(QVariant::Int))
					upper.setValue(lsInterval[1]);
		}

		ret.append(lower);
		ret.append(upper);
	}

	return ret;
}

/*!
 * This slot will be activated when the file system watcher reports a change in
 * the file state. If the file is removed we are setting the value to the empty
 * string here and then the profile backend will report back the default value
 * for th egiven key.
 */
void
QProfileValue::fileChanged (
        const QString &filename)
{
    QFile thisFile (filename);
    bool  exists = thisFile.exists (filename);

    SYS_DEBUG ("*** path   = %s", SYS_STR(filename));
    SYS_DEBUG ("*** exists = %s", SYS_BOOL(exists));
    if (!exists) {
        realSetValue (QVariant (""));
    }
}

bool
QProfileValue::stopWatchFiles ()
{
    SYS_DEBUG ("");
    if (m_FileWatcher) {
        delete m_FileWatcher;
        return true;
    }

    return false;
}

bool
QProfileValue::startWatchFile (
        const QString &filename)
{
    QFile thisFile (filename);
    bool  exists = thisFile.exists (filename);

    SYS_DEBUG ("filename = %s", SYS_STR(filename));
    SYS_DEBUG ("exists   = %s", SYS_BOOL(exists));

    /*
     * We stop waatching if we did before.
     */
    stopWatchFiles ();

    /*
     * If the file does not exists to begin with we don't need to watch. We will
     * return true, that means the file name must be fixed.
     */
    if (!exists)
        goto finalize;

    m_FileWatcher = new QFileSystemWatcher (this);
    m_FileWatcher->addPath (filename);
    connect (m_FileWatcher, SIGNAL(fileChanged(const QString &)),
            this, SLOT(fileChanged(const QString &)));

finalize:
    SYS_DEBUG ("returning %s", SYS_BOOL(!exists));
    return !exists;
}
<commit_msg>Changes: fix<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of meegotouch-controlpanelsoundsettingsapplet.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QDebug>
#include <QStringList>
#include <QFile>
#ifdef HAVE_LIBPROFILE
#include <profiled/libprofile.h>
#endif

#include "qprofilevalue.h"

//#define DEBUG
#define WARNING
#include "debug.h"

#define TO_STRING(string) ((string).toUtf8().constData())

int QProfileValue::nTrackedValues = 0;

QProfileValue::QProfileValue(const QString &key, bool setAllProfiles) :
	QTrackedVariant(key),
	m_setAllProfiles(setAllProfiles)
{
    SYS_DEBUG ("*** key = %s", SYS_STR(key));
	addNotify();
}

QProfileValue::~QProfileValue()
{
	delNotify();
}

void
QProfileValue::notifyValue(const char *profile, const char *key, const char *val, const char *type, QProfileValue *self)
{
	QString compareString;
	Q_UNUSED(val)
	Q_UNUSED(type)

	if (self->key().contains('@'))
		compareString = self->key();
	else {
#ifdef HAVE_LIBPROFILE
		char *currentProfile = profile_get_profile();
		compareString = self->key() + "@" + currentProfile;
		free(currentProfile);
#endif
	}

	if (compareString == (QString(key) + "@" + profile)) {
		self->m_val.clear();
		self->emit_changed();
	}
}

void
QProfileValue::addNotify()
{
#ifdef HAVE_LIBPROFILE
	if (0 == nTrackedValues)
		profile_tracker_init();
	nTrackedValues++;

	profile_track_add_active_cb((profile_track_value_fn_data)notifyValue, this, NULL);
	profile_track_add_change_cb((profile_track_value_fn_data)notifyValue, this, NULL);
#endif
}

void
QProfileValue::delNotify()
{
#ifdef HAVE_LIBPROFILE
	profile_track_remove_active_cb((profile_track_value_fn_data)notifyValue, this);
	profile_track_remove_change_cb((profile_track_value_fn_data)notifyValue, this);

	nTrackedValues--;
	if (0 == nTrackedValues)
		profile_tracker_quit();
#endif
}

void
QProfileValue::realSetValue(const QVariant &newValue)
{
#ifdef HAVE_LIBPROFILE
	m_val.clear();

	QVariant convertedValue = newValue;
	QVariant::Type neededType = QVariant::Invalid;
	QString theKey, theProfile;
	QStringList lsType = getType(theKey, theProfile);

	char *currentProfile = profile_get_profile();
	if (theProfile.isNull())
		theProfile = QString(currentProfile);
	free(currentProfile);

    /*
     *
     */
    stopWatchFiles ();

    SYS_DEBUG ("*** lsType[0] = %s", SYS_STR(lsType[0]));
	if ("SOUNDFILE" == lsType[0]) {
        QString filename;

        filename = newValue.toString();
    SYS_DEBUG ("*** filename  = %s", SYS_STR(filename));
        if (!filename.isEmpty()) {
            bool missing;
            missing = startWatchFile (newValue.toString());
	        SYS_DEBUG ("*** missing = %s", SYS_BOOL(missing));
        }

        neededType = QVariant::String;
    } else if ("STRING" == lsType[0])
		neededType = QVariant::String;
	else if ("INTEGER" == lsType[0])
		neededType = QVariant::Int;
	else if ("BOOLEAN" == lsType[0])
		neededType = QVariant::Bool;
	else if ("DOUBLE" == lsType[0])
		neededType = QVariant::Double;

	if (neededType != QVariant::Invalid && convertedValue.convert(neededType)) {
		if (QVariant::Bool == neededType)
			profile_set_value_as_bool(theProfile.toUtf8().constData(), theKey.toUtf8().constData(), (int)convertedValue.toBool());
		else
		if (QVariant::Int == neededType) {
			profile_set_value_as_int(TO_STRING(theProfile), TO_STRING(theKey), (int)convertedValue.toInt());
        } else
		if (QVariant::Double == neededType)
			profile_set_value_as_double(theProfile.toUtf8().constData(), theKey.toUtf8().constData(), (double)convertedValue.toDouble());
		else
		if (QVariant::String == neededType)
			profile_set_value(theProfile.toUtf8().constData(), theKey.toUtf8().constData(), (char *)convertedValue.toString().toUtf8().constData());
	}

	if (m_setAllProfiles) {
		char **profiles = profile_get_profiles();
		if (profiles) {
			for (int Nix = 0 ; profiles[Nix] != NULL ; Nix++)
				if (theProfile != QString(profiles[Nix]))
					QProfileValue(key() + "@" + QString(profiles[Nix]), false).set(newValue);

			profile_free_profiles(profiles);
			profiles = NULL;
		}
	}
#endif
}

void
QProfileValue::fetchFromBackend()
{
#ifdef HAVE_LIBPROFILE
	QString      theKey, theProfile;
	QStringList  lsType = getType(theKey, theProfile);
	QVariant     var;

    SYS_DEBUG ("*** lsType[0] = %s", SYS_STR(lsType[0]));
    if ("SOUNDFILE" == lsType[0]) {
        char *filename;
        bool  needReread;

        filename = profile_get_value (
                theProfile.isNull() ? NULL : TO_STRING(theProfile),
                TO_STRING(theKey));
        needReread = startWatchFile (filename);

        SYS_DEBUG ("*** needReread = %s", SYS_BOOL(needReread));

        if (needReread) {
            free (filename);
            realSetValue (QVariant (""));

            filename = profile_get_value (
                        theProfile.isNull() ? NULL : TO_STRING(theProfile),
                        TO_STRING(theKey));
            needReread = startWatchFile (filename);

            if (needReread)
            {
                SYS_WARNING ("The current profile refers to"
                             " a non-existant file (%s)!",
                             filename);
            }
        }

        var = QVariant(QString::fromUtf8(filename));
		free(filename);
    } else if ("STRING" == lsType[0]) {
		char *the_value = profile_get_value (
                theProfile.isNull() ? NULL : TO_STRING(theProfile),
                TO_STRING(theKey));

		var = QVariant(QString::fromUtf8(the_value));
		free(the_value);
	} else if ("BOOLEAN" == lsType[0]) {
		var = QVariant((bool)profile_get_value_as_bool(
                theProfile.isNull() ? NULL : TO_STRING(theProfile),
                TO_STRING(theKey)));
    } else if ("INTEGER" == lsType[0]) {
		var = QVariant((int)profile_get_value_as_int(
                theProfile.isNull() ? NULL : TO_STRING(theProfile),
                TO_STRING(theKey)));
    }

	if (!var.isNull())
		m_val = var;
#endif
}

QStringList
QProfileValue::getType(QString &theKey, QString &theProfile)
{
	QStringList    lsType;
#ifdef HAVE_LIBPROFILE
	QStringList    lsKey;
	char          *the_type;

	lsKey = key().split('@');
	theKey = lsKey[0];

	if (lsKey.size() > 1)
		theProfile = lsKey[1];

	the_type = profile_get_type(lsKey[0].toUtf8().constData());
    SYS_DEBUG ("*** %s = %s", SYS_STR(theKey), the_type);

	lsType = QString(the_type).split(' ');
	free(the_type); the_type = NULL;
#endif
	return lsType;
}

QList<QVariant>
QProfileValue::possibleValues(RangeType *p_rangeType)
{
    QList<QVariant> ret;
	QString theKey, theProfile;
	QStringList lsType = getType(theKey, theProfile);

    SYS_DEBUG ("*** p_rangeType = %p");
    SYS_DEBUG ("*** lsType[0]   = %s", SYS_STR(lsType[0]));

	if (p_rangeType)
        *p_rangeType = Invalid;

	if ("SOUNDFILE" == lsType[0] ||
	    "STRING"    == lsType[0]) {

		if (p_rangeType)
            *p_rangeType = List;

		for (int Nix = 1 ; Nix < lsType.size() ; Nix++) {
			ret.append(QVariant(lsType[Nix].remove('"')));
        }
	}
	else
	if ("BOOLEAN" == lsType[0]) {
		if (p_rangeType) (*p_rangeType) = List;
		ret.append(QVariant(false));
		ret.append(QVariant(true));
	}
	else
	if ("INTEGER" == lsType[0]) {
		QVariant lower = QVariant(INT_MIN);
		QVariant upper = QVariant(INT_MAX);

		if (p_rangeType) (*p_rangeType) = Interval;

		if (lsType.size() > 1) {
			QStringList lsInterval = lsType[1].split('-');
			if (lsInterval.size() > 0)
				if (QVariant(lsInterval[0]).canConvert(QVariant::Int))
					lower.setValue(lsInterval[0]);
			if (lsInterval.size() > 1)
				if (QVariant(lsInterval[1]).canConvert(QVariant::Int))
					upper.setValue(lsInterval[1]);
		}

		ret.append(lower);
		ret.append(upper);
	}

	return ret;
}

/*!
 * This slot will be activated when the file system watcher reports a change in
 * the file state. If the file is removed we are setting the value to the empty
 * string here and then the profile backend will report back the default value
 * for th egiven key.
 */
void
QProfileValue::fileChanged (
        const QString &filename)
{
    QFile thisFile (filename);
    bool  exists = thisFile.exists (filename);

    SYS_DEBUG ("*** path   = %s", SYS_STR(filename));
    SYS_DEBUG ("*** exists = %s", SYS_BOOL(exists));
    if (!exists) {
        realSetValue (QVariant (""));
    }
}

bool
QProfileValue::stopWatchFiles ()
{
    SYS_DEBUG ("");
    if (m_FileWatcher) {
        delete m_FileWatcher;
        return true;
    }

    return false;
}

bool
QProfileValue::startWatchFile (
        const QString &filename)
{
    QFile thisFile (filename);
    bool  exists = thisFile.exists (filename);

    SYS_DEBUG ("filename = %s", SYS_STR(filename));
    SYS_DEBUG ("exists   = %s", SYS_BOOL(exists));

    /*
     * We stop waatching if we did before.
     */
    stopWatchFiles ();

    /*
     * If the file does not exists to begin with we don't need to watch. We will
     * return true, that means the file name must be fixed.
     */
    if (!exists)
        goto finalize;

    m_FileWatcher = new QFileSystemWatcher (this);
    m_FileWatcher->addPath (filename);
    connect (m_FileWatcher, SIGNAL(fileChanged(const QString &)),
            this, SLOT(fileChanged(const QString &)));

finalize:
    SYS_DEBUG ("returning %s", SYS_BOOL(!exists));
    return !exists;
}
<|endoftext|>


<commit_before>#include <isl/set.h>
#include <isl/union_map.h>
#include <isl/union_set.h>
#include <isl/ast_build.h>
#include <isl/schedule.h>
#include <isl/schedule_node.h>

#include <tiramisu/debug.h>
#include <tiramisu/core.h>

#include <string.h>
#include <Halide.h>
#include "halide_image_io.h"

using namespace tiramisu;

expr clamp(expr n, expr min, expr max) {
    return expr{o_select, n < min, min, expr{o_select, n > max, max, n}};
}

expr mixf(expr x, expr y, expr a) {
    return x * (expr{1.0f} -a) + y * a;
}

constexpr auto work_type = p_float32;
constexpr auto it_type = p_int32;
constexpr auto data_type = p_uint8;
constexpr auto block_size = 16;
#define BS "16"

int main(int argc, char **argv)
{
    // Set default tiramisu options.
    global::set_default_tiramisu_options();

    tiramisu::function affine_tiramisu("warp_affine_tiramisu");

    var i0("i0"), i1("i1"), j0("j0"), j1("j1");

    // Layer I

    // Input params.
    float a00 = 0.1;
    float a01 = 0.1;
    float a10 = 0.1;
    float a11 = 0.1;
    float b00 = 0.1;
    float b10 = 0.1;

    computation sizes{"[N, M] -> {sizes[i]}", expr{}, false, data_type, &affine_tiramisu};
    constant N{"N", sizes(0), it_type, true, nullptr, 0, &affine_tiramisu};
    constant M{"M", sizes(1), it_type, true, nullptr, 0, &affine_tiramisu};

    computation in{"[N, M] -> {in[i, j]}", expr{}, false, data_type, &affine_tiramisu};

    computation out{"[N, M] -> {out[i0, j0, i1, j1] : 0 <= i0 * " BS " + i1 < N and 0 <= i0 and 0 <= i1 < " BS " and 0 <= j0 * " BS " + j1 < M and 0 <= j0 and 0 <= j1 < " BS "}", expr(), true, data_type, &affine_tiramisu};

    auto i = i0 * expr{block_size} + i1, j = j0 * expr{block_size} + j1;

    int level = 3;
    constant o_r{"o_r", expr{a11} * cast(work_type, i) + expr{a10} * cast(work_type, j) + expr{b00}, work_type, false, &out, level, &affine_tiramisu};
    constant o_c{"o_c", expr{a01} * cast(work_type, i) + expr{a00} * cast(work_type, j) + expr{b10}, work_type, false, &out, level, &affine_tiramisu};
    constant r{"r", static_cast<expr>(o_r) - expr{o_floor, o_r}, work_type, false, &out, level, &affine_tiramisu};
    constant c{"c", static_cast<expr>(o_c) - expr{o_floor, o_c}, work_type, false, &out, level, &affine_tiramisu};
    constant coord_r{"coord_r", cast(it_type, expr{o_floor, o_r}), it_type, false, &out, level, &affine_tiramisu};
    constant coord_c{"coord_c", cast(it_type, expr{o_floor, o_r}), it_type, false, &out, level, &affine_tiramisu};
    constant coord_00r{"coord_00r", clamp(coord_r    , 0, N), it_type, false, &out, level, &affine_tiramisu};
    constant coord_00c{"coord_00c", clamp(coord_c    , 0, M), it_type, false, &out, level, &affine_tiramisu};
    constant coord_01r{"coord_01r", clamp(coord_r    , 0, N), it_type, false, &out, level, &affine_tiramisu};
    constant coord_01c{"coord_01c", clamp(coord_c + 1, 0, M), it_type, false, &out, level, &affine_tiramisu};
    constant coord_10r{"coord_10r", clamp(coord_r + 1, 0, N), it_type, false, &out, level, &affine_tiramisu};
    constant coord_10c{"coord_10c", clamp(coord_c    , 0, M), it_type, false, &out, level, &affine_tiramisu};
    constant coord_11r{"coord_11r", clamp(coord_r + 1, 0, N), it_type, false, &out, level, &affine_tiramisu};
    constant coord_11c{"coord_11c", clamp(coord_c + 1, 0, M), it_type, false, &out, level, &affine_tiramisu};

    expr A00 = cast(p_float32, in(coord_00r, coord_00c));
    expr A01 = cast(p_float32, in(coord_01r, coord_01c));
    expr A10 = cast(p_float32, in(coord_10r, coord_10c));
    expr A11 = cast(p_float32, in(coord_11r, coord_11c));

    out.set_expression(cast(data_type, mixf(mixf(A00, A01, r), mixf(A10, A11, r), c)));

    // Layer II & III

//    out.tile(i, j, block_size, block_size, i0, j0, i1, j1);
    out.tag_gpu_level(i0, j0, i1, j1);
    o_r.tag_gpu_level(i0, j0, i1, j1);

    buffer in_gpu{"in_gpu", {M, N}, data_type, a_temporary, &affine_tiramisu};
    in.set_access("{in[i, j] -> in_gpu[j, i]}");
    in_gpu.tag_gpu_global();
    buffer out_gpu{"out_gpu", {M, N}, data_type, a_temporary, &affine_tiramisu};
    out.set_access("{out[i0, j0, i1, j1] -> out_gpu[j0 * " BS " + j1, i0 * " BS " + i1]}");
    out_gpu.tag_gpu_global();

    buffer in_host{"in_host", {M, N}, data_type, a_input, &affine_tiramisu};
    buffer out_host{"out_host", {M, N}, data_type, a_output, &affine_tiramisu};
    buffer sizes_host{"sizes_host", {2}, it_type, a_input, &affine_tiramisu};
    sizes.set_access("{sizes[i] -> sizes_host[i]}");

    affine_tiramisu.dump_sched_graph();

    computation copy_to_device{"{copy_to_device[0]}", memcpy(in_host, in_gpu), true, p_none, &affine_tiramisu};
    // copy_to_device.before(*buffer_declares[0], computation::root);
    copy_to_device.before(o_r, computation::root);
    computation copy_to_host{"{copy_to_host[0]}", memcpy(out_gpu, out_host), true, p_none, &affine_tiramisu};
    copy_to_host.after(out, computation::root);

    affine_tiramisu.set_arguments({&sizes_host, &in_host, &out_host});
    affine_tiramisu.gen_time_space_domain();
    affine_tiramisu.gen_isl_ast();
    affine_tiramisu.gen_cuda_stmt();
    affine_tiramisu.gen_halide_stmt();
    affine_tiramisu.dump_halide_stmt();
    affine_tiramisu.gen_halide_obj("build/generated_fct_warp_affine.o");

    return 0;
}
<commit_msg>warp affine fix<commit_after>#include <isl/set.h>
#include <isl/union_map.h>
#include <isl/union_set.h>
#include <isl/ast_build.h>
#include <isl/schedule.h>
#include <isl/schedule_node.h>

#include <tiramisu/debug.h>
#include <tiramisu/core.h>

#include <string.h>
#include <Halide.h>
#include "halide_image_io.h"

using namespace tiramisu;

expr clamp(expr n, expr min, expr max) {
    return expr{o_select, n < min, min, expr{o_select, n > max, max, n}};
}

expr mixf(expr x, expr y, expr a) {
    return x * (expr{1.0f} -a) + y * a;
}

constexpr auto work_type = p_float32;
constexpr auto it_type = p_int32;
constexpr auto data_type = p_uint8;
constexpr auto block_size = 16;
#define BS "16"

int main(int argc, char **argv)
{
    // Set default tiramisu options.
    global::set_default_tiramisu_options();

    tiramisu::function affine_tiramisu("warp_affinegpu_tiramisu");

    var i0("i0"), i1("i1"), j0("j0"), j1("j1");

    // Layer I

    // Input params.
    float a00 = 0.1;
    float a01 = 0.1;
    float a10 = 0.1;
    float a11 = 0.1;
    float b00 = 0.1;
    float b10 = 0.1;

    computation sizes{"[N, M] -> {sizes[i]}", expr{}, false, data_type, &affine_tiramisu};
    constant N{"N", sizes(0), it_type, true, nullptr, 0, &affine_tiramisu};
    constant M{"M", sizes(1), it_type, true, nullptr, 0, &affine_tiramisu};

    computation in{"[N, M] -> {in[i, j]}", expr{}, false, data_type, &affine_tiramisu};

    computation out{"[N, M] -> {out[i0, j0, i1, j1] : 0 <= i0 * " BS " + i1 < N and 0 <= i0 and 0 <= i1 < " BS " and 0 <= j0 * " BS " + j1 < M and 0 <= j0 and 0 <= j1 < " BS "}", expr(), true, data_type, &affine_tiramisu};

    auto i = i0 * expr{block_size} + i1, j = j0 * expr{block_size} + j1;

    int level = 3;
    constant o_r{"o_r", expr{a11} * cast(work_type, i) + expr{a10} * cast(work_type, j) + expr{b00}, work_type, false, &out, level, &affine_tiramisu};
    constant o_c{"o_c", expr{a01} * cast(work_type, i) + expr{a00} * cast(work_type, j) + expr{b10}, work_type, false, &out, level, &affine_tiramisu};
    constant r{"r", static_cast<expr>(o_r) - expr{o_floor, o_r}, work_type, false, &out, level, &affine_tiramisu};
    constant c{"c", static_cast<expr>(o_c) - expr{o_floor, o_c}, work_type, false, &out, level, &affine_tiramisu};
    constant coord_r{"coord_r", cast(it_type, expr{o_floor, o_r}), it_type, false, &out, level, &affine_tiramisu};
    constant coord_c{"coord_c", cast(it_type, expr{o_floor, o_r}), it_type, false, &out, level, &affine_tiramisu};
    constant coord_00r{"coord_00r", clamp(coord_r    , 0, N), it_type, false, &out, level, &affine_tiramisu};
    constant coord_00c{"coord_00c", clamp(coord_c    , 0, M), it_type, false, &out, level, &affine_tiramisu};
    constant coord_01r{"coord_01r", clamp(coord_r    , 0, N), it_type, false, &out, level, &affine_tiramisu};
    constant coord_01c{"coord_01c", clamp(coord_c + 1, 0, M), it_type, false, &out, level, &affine_tiramisu};
    constant coord_10r{"coord_10r", clamp(coord_r + 1, 0, N), it_type, false, &out, level, &affine_tiramisu};
    constant coord_10c{"coord_10c", clamp(coord_c    , 0, M), it_type, false, &out, level, &affine_tiramisu};
    constant coord_11r{"coord_11r", clamp(coord_r + 1, 0, N), it_type, false, &out, level, &affine_tiramisu};
    constant coord_11c{"coord_11c", clamp(coord_c + 1, 0, M), it_type, false, &out, level, &affine_tiramisu};

    expr A00 = cast(p_float32, in(coord_00r, coord_00c));
    expr A01 = cast(p_float32, in(coord_01r, coord_01c));
    expr A10 = cast(p_float32, in(coord_10r, coord_10c));
    expr A11 = cast(p_float32, in(coord_11r, coord_11c));

    out.set_expression(cast(data_type, mixf(mixf(A00, A01, r), mixf(A10, A11, r), c)));

    // Layer II & III

//    out.tile(i, j, block_size, block_size, i0, j0, i1, j1);
    out.tag_gpu_level(i0, j0, i1, j1);
    o_r.tag_gpu_level(i0, j0, i1, j1);

    buffer in_gpu{"in_gpu", {M, N}, data_type, a_temporary, &affine_tiramisu};
    in.set_access("{in[i, j] -> in_gpu[j, i]}");
    in_gpu.tag_gpu_global();
    buffer out_gpu{"out_gpu", {M, N}, data_type, a_temporary, &affine_tiramisu};
    out.set_access("{out[i0, j0, i1, j1] -> out_gpu[j0 * " BS " + j1, i0 * " BS " + i1]}");
    out_gpu.tag_gpu_global();

    buffer in_host{"in_host", {M, N}, data_type, a_input, &affine_tiramisu};
    buffer out_host{"out_host", {M, N}, data_type, a_output, &affine_tiramisu};
    buffer sizes_host{"sizes_host", {2}, it_type, a_input, &affine_tiramisu};
    sizes.set_access("{sizes[i] -> sizes_host[i]}");

    affine_tiramisu.dump_sched_graph();

    computation copy_to_device{"{copy_to_device[0]}", memcpy(in_host, in_gpu), true, p_none, &affine_tiramisu};
    // copy_to_device.before(*buffer_declares[0], computation::root);
    copy_to_device.before(o_r, computation::root);
    computation copy_to_host{"{copy_to_host[0]}", memcpy(out_gpu, out_host), true, p_none, &affine_tiramisu};
    copy_to_host.after(out, computation::root);

    affine_tiramisu.set_arguments({&sizes_host, &in_host, &out_host});
    affine_tiramisu.gen_time_space_domain();
    affine_tiramisu.gen_isl_ast();
    affine_tiramisu.gen_cuda_stmt();
    affine_tiramisu.gen_halide_stmt();
    affine_tiramisu.dump_halide_stmt();
    affine_tiramisu.gen_halide_obj("build/generated_fct_warp_affinegpu.o");

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2004-2013 ZNC, see the NOTICE file for details.
 * Copyright (C) 2013 Rasmus Eskola <fruitiex@gmail.com>
 * based on sample.cpp sample module code
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <znc/FileUtils.h>
#include <znc/Client.h>
#include <znc/Chan.h>
#include <znc/User.h>
#include <znc/IRCNetwork.h>
#include <znc/Modules.h>
#include <dirent.h>
#include <vector>
#include <algorithm>

class CBacklogMod : public CModule {
public:
	MODCONSTRUCTOR(CBacklogMod) {}

	virtual bool OnLoad(const CString& sArgs, CString& sMessage);
	virtual ~CBacklogMod();
	virtual void OnModCommand(const CString& sCommand);

private:
	bool inChan(const CString& Chan);
};

bool CBacklogMod::OnLoad(const CString& sArgs, CString& sMessage) {
	CString LogPath = sArgs;

	if(LogPath.empty()) {
		LogPath = GetNV("LogPath");
		if(LogPath.empty()) {
			// TODO: guess logpath?
			PutModule("LogPath is empty, set it with the LogPath command (help for more info)");
		}
	} else {
		SetNV("LogPath", LogPath);
		PutModule("LogPath set to: " + LogPath);
	}
	return true;
}

CBacklogMod::~CBacklogMod() {
}

void CBacklogMod::OnModCommand(const CString& sCommand) {
	CString Arg = sCommand.Token(1);
	if (sCommand.Token(0).Equals("help")) {
		// TODO: proper help text, look how AddHelpCommand() does it in other ZNC code
		PutModule("Usage:");
		PutModule("<window-name> [num-lines] (e.g. #foo 42)");
		PutModule("");
		PutModule("Commands:");
		PutModule("Help (print this text)");
		PutModule("LogPath <path> (use keywords $USER, $NETWORK, $WINDOW and an asterisk * for date)");
		PutModule("PrintStatusMsgs true/false (print join/part/rename messages)");
		return;
	} else if (sCommand.Token(0).Equals("logpath")) {
		if(Arg.empty()) {
			PutModule("Usage: LogPath <path> (use keywords $USER, $NETWORK, $WINDOW and an asterisk * for date:)");
			PutModule("Current LogPath is set to: " + GetNV("LogPath"));
			return;
		}

		CString LogPath = sCommand.Token(1, true);
		SetNV("LogPath", LogPath);
		PutModule("LogPath set to: " + LogPath);
		return;
	} else if (sCommand.Token(0).Equals("PrintStatusMsgs")) {
		if(Arg.empty() || (!Arg.Equals("true", true) && !Arg.Equals("false", true))) {
			PutModule("Usage: PrintStatusMsgs true/false");
			return;
		}

		SetNV("PrintStatusMsgs", Arg);
		PutModule("PrintStatusMsgs set to: " + Arg);
		return;
	}

	// TODO: handle these differently depending on how the module was loaded
	CString User = (m_pUser ? m_pUser->GetUserName() : "UNKNOWN");
	CString Network = (m_pNetwork ? m_pNetwork->GetName() : "znc");
	CString Channel = sCommand.Token(0);

	int printedLines = 0;
	int reqLines = sCommand.Token(1).ToInt();
	if(reqLines <= 0) {
		reqLines = 150;
	}
	reqLines = std::max(std::min(reqLines, 1000), 1);

	CString Path = GetNV("LogPath").substr(); // make copy
	Path.Replace("$NETWORK", Network);
	Path.Replace("$WINDOW", Channel);
	Path.Replace("$USER", User);

	CString DirPath = Path.substr(0, Path.find_last_of("/"));
	CString FilePath;

	std::vector<CString> FileList;
	std::vector<CString> LinesToPrint;

	// gather list of all log files for requested channel/window
	DIR *dir;
	struct dirent *ent;
	if ((dir = opendir (DirPath.c_str())) != NULL) {
		while ((ent = readdir (dir)) != NULL) {
			FilePath = DirPath + "/" + ent->d_name;
			//PutModule("DEBUG: " + FilePath + " " + Path);
			if(FilePath.AsLower().StrCmp(Path.AsLower(), Path.find_last_of("*")) == 0) {
				FileList.push_back(FilePath);
			}
		}
		closedir (dir);
	} else {
		PutModule("Could not list directory " + DirPath + ": " + strerror(errno));
		return;
	}

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

	// loop through list of log files one by one starting from most recent...
	for (std::vector<CString>::reverse_iterator it = FileList.rbegin(); it != FileList.rend(); ++it) {
		CFile LogFile(*it);
		CString Line;
		std::vector<CString> Lines;

		if (LogFile.Open()) {
			while (LogFile.ReadLine(Line)) {
				try {
					// is line a part/join/rename etc message (nick ***), do we want to print it?
					// find nick by finding first whitespace, then moving one char right
					if(Line.at(Line.find_first_of(' ') + 1) == '*' && !GetNV("PrintStatusMsgs").ToBool()) {
						continue;
					}

					Lines.push_back(Line);
				} catch (int e) {
					// malformed log line, ignore
					PutModule("Malformed log line found in " + *it + ": " + Line);
				}
			}
		} else {
			PutModule("Could not open log file [" + sCommand + "]: " + strerror(errno));
			continue;
		}

		LogFile.Close();

		// loop through Lines in reverse order, push to LinesToPrint
		for (std::vector<CString>::reverse_iterator itl = Lines.rbegin(); itl != Lines.rend(); ++itl) {
			LinesToPrint.push_back(*itl);
			printedLines++;

			if(printedLines >= reqLines) {
				break;
			}
		}

		if(printedLines >= reqLines) {
			break;
		}
	}

	bool isInChan = CBacklogMod::inChan(Channel);

	if(printedLines == 0) {
		PutModule("No log files found for window " + Channel + " in " + DirPath + "/");
		return;
	} else if (isInChan) {
		m_pNetwork->PutUser(":***!znc@znc.in PRIVMSG " + Channel + " :Backlog playback...", GetClient());
	} else {
		PutModule("*** Backlog playback...");
	}

	// now actually print
	for (std::vector<CString>::reverse_iterator it = LinesToPrint.rbegin(); it != LinesToPrint.rend(); ++it) {
		if(isInChan) {
			CString Line = *it;
			size_t FirstWS = Line.find_first_of(' '); // position of first whitespace char in line
			size_t NickLen = 3;
			CString Nick = "***";

			try {
				// a log line looks like: [HH:MM:SS] <Nick> Message
				// < and > are illegal characters in nicknames, so we can
				// search for these
				if(Line.at(FirstWS + 1) == '<') { // normal message
					// nicklen includes surrounding < >
					NickLen = Line.find_first_of('>') - Line.find_first_of('<') + 1;
					// but we don't want them in Nick so subtract by two
					Nick = Line.substr(FirstWS + 2, NickLen - 2);
				}

				m_pNetwork->PutUser(":" + Nick + "!znc@znc.in PRIVMSG " + Channel + " :" + Line.substr(0, FirstWS) + Line.substr(FirstWS + NickLen + 1, Line.npos), GetClient());
			} catch (int e) {
				PutModule("Malformed log line! " + Line);
			}
		} else {
			PutModule(*it);
		}
	}

	if (isInChan) {
		m_pNetwork->PutUser(":***!znc@znc.in PRIVMSG " + Channel + " :" + "Playback complete.", GetClient());
	} else {
		PutModule("*** Playback complete.");
	}
}

bool CBacklogMod::inChan(const CString& Chan) {
	const std::vector <CChan*>& vChans (m_pNetwork->GetChans());

	for (std::vector<CChan*>::const_iterator it = vChans.begin(); it != vChans.end(); ++it) {
		CChan *curChan = *it;
		if(Chan.StrCmp(curChan->GetName()) == 0) {
			return true;
		}
	}

	return false;
}

template<> void TModInfo<CBacklogMod>(CModInfo& Info) {
	Info.AddType(CModInfo::NetworkModule);
	Info.AddType(CModInfo::GlobalModule);
	Info.SetWikiPage("backlog");
	Info.SetArgsHelpText("Takes as optional argument (and if given, sets) the log path, use keywords: $USER, $NETWORK and $WINDOW");
	Info.SetHasArgs(true);
}

NETWORKMODULEDEFS(CBacklogMod, "Module for getting the last X lines of a channels log.")
<commit_msg>tabs -> spaces<commit_after>/*
 * Copyright (C) 2004-2013 ZNC, see the NOTICE file for details.
 * Copyright (C) 2013 Rasmus Eskola <fruitiex@gmail.com>
 * based on sample.cpp sample module code
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <znc/FileUtils.h>
#include <znc/Client.h>
#include <znc/Chan.h>
#include <znc/User.h>
#include <znc/IRCNetwork.h>
#include <znc/Modules.h>
#include <dirent.h>
#include <vector>
#include <algorithm>

class CBacklogMod : public CModule {
public:
    MODCONSTRUCTOR(CBacklogMod) {}

    virtual bool OnLoad(const CString& sArgs, CString& sMessage);
    virtual ~CBacklogMod();
    virtual void OnModCommand(const CString& sCommand);

private:
    bool inChan(const CString& Chan);
};

bool CBacklogMod::OnLoad(const CString& sArgs, CString& sMessage) {
    CString LogPath = sArgs;

    if(LogPath.empty()) {
        LogPath = GetNV("LogPath");
        if(LogPath.empty()) {
            // TODO: guess logpath?
            PutModule("LogPath is empty, set it with the LogPath command (help for more info)");
        }
    } else {
        SetNV("LogPath", LogPath);
        PutModule("LogPath set to: " + LogPath);
    }
    return true;
}

CBacklogMod::~CBacklogMod() {
}

void CBacklogMod::OnModCommand(const CString& sCommand) {
    CString Arg = sCommand.Token(1);
    if (sCommand.Token(0).Equals("help")) {
        // TODO: proper help text, look how AddHelpCommand() does it in other ZNC code
        PutModule("Usage:");
        PutModule("<window-name> [num-lines] (e.g. #foo 42)");
        PutModule("");
        PutModule("Commands:");
        PutModule("Help (print this text)");
        PutModule("LogPath <path> (use keywords $USER, $NETWORK, $WINDOW and an asterisk * for date)");
        PutModule("PrintStatusMsgs true/false (print join/part/rename messages)");
        return;
    } else if (sCommand.Token(0).Equals("logpath")) {
        if(Arg.empty()) {
            PutModule("Usage: LogPath <path> (use keywords $USER, $NETWORK, $WINDOW and an asterisk * for date:)");
            PutModule("Current LogPath is set to: " + GetNV("LogPath"));
            return;
        }

        CString LogPath = sCommand.Token(1, true);
        SetNV("LogPath", LogPath);
        PutModule("LogPath set to: " + LogPath);
        return;
    } else if (sCommand.Token(0).Equals("PrintStatusMsgs")) {
        if(Arg.empty() || (!Arg.Equals("true", true) && !Arg.Equals("false", true))) {
            PutModule("Usage: PrintStatusMsgs true/false");
            return;
        }

        SetNV("PrintStatusMsgs", Arg);
        PutModule("PrintStatusMsgs set to: " + Arg);
        return;
    }

    // TODO: handle these differently depending on how the module was loaded
    CString User = (m_pUser ? m_pUser->GetUserName() : "UNKNOWN");
    CString Network = (m_pNetwork ? m_pNetwork->GetName() : "znc");
    CString Channel = sCommand.Token(0);

    int printedLines = 0;
    int reqLines = sCommand.Token(1).ToInt();
    if(reqLines <= 0) {
        reqLines = 150;
    }
    reqLines = std::max(std::min(reqLines, 1000), 1);

    CString Path = GetNV("LogPath").substr(); // make copy
    Path.Replace("$NETWORK", Network);
    Path.Replace("$WINDOW", Channel);
    Path.Replace("$USER", User);

    CString DirPath = Path.substr(0, Path.find_last_of("/"));
    CString FilePath;

    std::vector<CString> FileList;
    std::vector<CString> LinesToPrint;

    // gather list of all log files for requested channel/window
    DIR *dir;
    struct dirent *ent;
    if ((dir = opendir (DirPath.c_str())) != NULL) {
        while ((ent = readdir (dir)) != NULL) {
            FilePath = DirPath + "/" + ent->d_name;
            //PutModule("DEBUG: " + FilePath + " " + Path);
            if(FilePath.AsLower().StrCmp(Path.AsLower(), Path.find_last_of("*")) == 0) {
                FileList.push_back(FilePath);
            }
        }
        closedir (dir);
    } else {
        PutModule("Could not list directory " + DirPath + ": " + strerror(errno));
        return;
    }

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

    // loop through list of log files one by one starting from most recent...
    for (std::vector<CString>::reverse_iterator it = FileList.rbegin(); it != FileList.rend(); ++it) {
        CFile LogFile(*it);
        CString Line;
        std::vector<CString> Lines;

        if (LogFile.Open()) {
            while (LogFile.ReadLine(Line)) {
                try {
                    // is line a part/join/rename etc message (nick ***), do we want to print it?
                    // find nick by finding first whitespace, then moving one char right
                    if(Line.at(Line.find_first_of(' ') + 1) == '*' && !GetNV("PrintStatusMsgs").ToBool()) {
                        continue;
                    }

                    Lines.push_back(Line);
                } catch (int e) {
                    // malformed log line, ignore
                    PutModule("Malformed log line found in " + *it + ": " + Line);
                }
            }
        } else {
            PutModule("Could not open log file [" + sCommand + "]: " + strerror(errno));
            continue;
        }

        LogFile.Close();

        // loop through Lines in reverse order, push to LinesToPrint
        for (std::vector<CString>::reverse_iterator itl = Lines.rbegin(); itl != Lines.rend(); ++itl) {
            LinesToPrint.push_back(*itl);
            printedLines++;

            if(printedLines >= reqLines) {
                break;
            }
        }

        if(printedLines >= reqLines) {
            break;
        }
    }

    bool isInChan = CBacklogMod::inChan(Channel);

    if(printedLines == 0) {
        PutModule("No log files found for window " + Channel + " in " + DirPath + "/");
        return;
    } else if (isInChan) {
        m_pNetwork->PutUser(":***!znc@znc.in PRIVMSG " + Channel + " :Backlog playback...", GetClient());
    } else {
        PutModule("*** Backlog playback...");
    }

    // now actually print
    for (std::vector<CString>::reverse_iterator it = LinesToPrint.rbegin(); it != LinesToPrint.rend(); ++it) {
        if(isInChan) {
            CString Line = *it;
            size_t FirstWS = Line.find_first_of(' '); // position of first whitespace char in line
            size_t NickLen = 3;
            CString Nick = "***";

            try {
                // a log line looks like: [HH:MM:SS] <Nick> Message
                // < and > are illegal characters in nicknames, so we can
                // search for these
                if(Line.at(FirstWS + 1) == '<') { // normal message
                    // nicklen includes surrounding < >
                    NickLen = Line.find_first_of('>') - Line.find_first_of('<') + 1;
                    // but we don't want them in Nick so subtract by two
                    Nick = Line.substr(FirstWS + 2, NickLen - 2);
                }

                m_pNetwork->PutUser(":" + Nick + "!znc@znc.in PRIVMSG " + Channel + " :" + Line.substr(0, FirstWS) + Line.substr(FirstWS + NickLen + 1, Line.npos), GetClient());
            } catch (int e) {
                PutModule("Malformed log line! " + Line);
            }
        } else {
            PutModule(*it);
        }
    }

    if (isInChan) {
        m_pNetwork->PutUser(":***!znc@znc.in PRIVMSG " + Channel + " :" + "Playback complete.", GetClient());
    } else {
        PutModule("*** Playback complete.");
    }
}

bool CBacklogMod::inChan(const CString& Chan) {
    const std::vector <CChan*>& vChans (m_pNetwork->GetChans());

    for (std::vector<CChan*>::const_iterator it = vChans.begin(); it != vChans.end(); ++it) {
        CChan *curChan = *it;
        if(Chan.StrCmp(curChan->GetName()) == 0) {
            return true;
        }
    }

    return false;
}

template<> void TModInfo<CBacklogMod>(CModInfo& Info) {
    Info.AddType(CModInfo::NetworkModule);
    Info.AddType(CModInfo::GlobalModule);
    Info.SetWikiPage("backlog");
    Info.SetArgsHelpText("Takes as optional argument (and if given, sets) the log path, use keywords: $USER, $NETWORK and $WINDOW");
    Info.SetHasArgs(true);
}

NETWORKMODULEDEFS(CBacklogMod, "Module for getting the last X lines of a channels log.")
<|endoftext|>


<commit_before>/*
    emoticonselector.cpp

    a button that pops up a list of all emoticons and returns
    the emoticon-string if one is selected in the list

    Copyright (c) 2002      by Stefan Gehn            <metz@gehn.net>
    Copyright (c) 2003      by Martijn Klingens       <klingens@kde.org>

    Kopete    (c) 2002-2003 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * 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.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "emoticonselector.h"
#include "kopeteemoticons.h"

#include <math.h>

#include <QPixmap>
#include <QMouseEvent>
#include <QHBoxLayout>
#include <QObject>
#include <QHideEvent>
#include <QShowEvent>

#include <kdebug.h>

EmoticonItem::EmoticonItem(const QString &emoticonText, const QString &pixmapPath, QListWidget *parent)
	: QListWidgetItem(parent)
{
	m_text = emoticonText;
	m_pixmapPath = pixmapPath;
	QPixmap p(m_pixmapPath);
    //
    // Some of the custom icons are rather large
    // so lets limit them to a maximum size for this display panel
    //
    if (p.width() > 32 || p.height() > 32)
		p = p.scaled(QSize(32,32), Qt::KeepAspectRatio);

	setIcon(p);
}

QString EmoticonItem::text() const
{
	return m_text;
}

QString EmoticonItem::pixmapPath() const
{
	return m_pixmapPath;
}

EmoticonSelector::EmoticonSelector(QWidget *parent)
	: QWidget(parent)
{
	QHBoxLayout *lay = new QHBoxLayout(this);
	lay->setSpacing( 0 );
	lay->setContentsMargins( 0, 0, 0, 0 );
	m_emoticonList = new QListWidget(this);
	lay->addWidget(m_emoticonList);
	m_emoticonList->setViewMode(QListView::IconMode);
	m_emoticonList->setSelectionMode(QAbstractItemView::SingleSelection);
	m_emoticonList->setMouseTracking(true);

	QLabel *m_currentEmoticon  = new QLabel( this );
	m_currentEmoticon->setFrameShape( QFrame::Box );
	m_currentEmoticon->setMinimumSize(QSize(128,128));
	m_currentEmoticon->setAlignment( Qt::AlignCenter );
	lay->addWidget(m_currentEmoticon);

	m_currentMovie = new QMovie(this);
	m_currentEmoticon->setMovie(m_currentMovie);

	connect(m_emoticonList, SIGNAL(itemEntered(QListWidgetItem*)),
			this, SLOT(mouseOverItem(QListWidgetItem*)));
	connect(m_emoticonList, SIGNAL(itemSelectionChanged()),
			this, SLOT(currentChanged()));
	connect(m_emoticonList, SIGNAL(itemClicked(QListWidgetItem*)),
			this, SLOT(emoticonClicked(QListWidgetItem*)));

	connect(m_emoticonList, SIGNAL(itemActivated(QListWidgetItem*)),
			this, SLOT(emoticonClicked(QListWidgetItem*)));

}

void EmoticonSelector::prepareList(void)
{
//	kDebug(14000) << k_funcinfo << "called." << endl;
	QMap<QString, QStringList> list = Kopete::Emoticons::self()->emoticonAndPicList();

	for (QMap<QString, QStringList>::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
		(void) new EmoticonItem(it.value().first(), it.key(), m_emoticonList);

	m_emoticonList->setIconSize(QSize(32,32));
}

void EmoticonSelector::emoticonClicked(QListWidgetItem *i)
{
	EmoticonItem *item = dynamic_cast<EmoticonItem*>(i);
	if (!item)
		return;

	// KDE4/Qt TODO: use qobject_cast instead.
	emit itemSelected ( item->text() );
	if ( isVisible() && parentWidget() &&
		parentWidget()->inherits("QMenu") )
	{
		parentWidget()->close();
	}
}

void EmoticonSelector::mouseOverItem(QListWidgetItem *item)
{
	item->setSelected(true);
	if (!m_emoticonList->hasFocus())
		m_emoticonList->setFocus();
}

void EmoticonSelector::currentChanged()
{
	EmoticonItem *item = dynamic_cast<EmoticonItem*>(m_emoticonList->selectedItems().first());
	if (!item)
		return;

	// FIXME: the label is not correctly cleared when changing from a bigger movie to a smaller one
	m_currentMovie->stop();
	m_currentMovie->setFileName(item->pixmapPath());
	m_currentMovie->start();
}

void EmoticonSelector::hideEvent( QHideEvent* )
{
	m_currentMovie->stop();
}

void EmoticonSelector::showEvent( QShowEvent* )
{
	m_currentMovie->start();
}

#include "emoticonselector.moc"

// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>Disable dragging of emoticons<commit_after>/*
    emoticonselector.cpp

    a button that pops up a list of all emoticons and returns
    the emoticon-string if one is selected in the list

    Copyright (c) 2002      by Stefan Gehn            <metz@gehn.net>
    Copyright (c) 2003      by Martijn Klingens       <klingens@kde.org>

    Kopete    (c) 2002-2003 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * 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.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "emoticonselector.h"
#include "kopeteemoticons.h"

#include <math.h>

#include <QPixmap>
#include <QMouseEvent>
#include <QHBoxLayout>
#include <QObject>
#include <QHideEvent>
#include <QShowEvent>

#include <kdebug.h>

EmoticonItem::EmoticonItem(const QString &emoticonText, const QString &pixmapPath, QListWidget *parent)
	: QListWidgetItem(parent)
{
	m_text = emoticonText;
	m_pixmapPath = pixmapPath;
	QPixmap p(m_pixmapPath);
    //
    // Some of the custom icons are rather large
    // so lets limit them to a maximum size for this display panel
    //
    if (p.width() > 32 || p.height() > 32)
		p = p.scaled(QSize(32,32), Qt::KeepAspectRatio);

	setIcon(p);
}

QString EmoticonItem::text() const
{
	return m_text;
}

QString EmoticonItem::pixmapPath() const
{
	return m_pixmapPath;
}

EmoticonSelector::EmoticonSelector(QWidget *parent)
	: QWidget(parent)
{
	QHBoxLayout *lay = new QHBoxLayout(this);
	lay->setSpacing( 0 );
	lay->setContentsMargins( 0, 0, 0, 0 );
	m_emoticonList = new QListWidget(this);
	lay->addWidget(m_emoticonList);
	m_emoticonList->setViewMode(QListView::IconMode);
	m_emoticonList->setSelectionMode(QAbstractItemView::SingleSelection);
	m_emoticonList->setMouseTracking(true);
	m_emoticonList->setDragEnabled(false);

	QLabel *m_currentEmoticon  = new QLabel( this );
	m_currentEmoticon->setFrameShape( QFrame::Box );
	m_currentEmoticon->setMinimumSize(QSize(128,128));
	m_currentEmoticon->setAlignment( Qt::AlignCenter );
	lay->addWidget(m_currentEmoticon);

	m_currentMovie = new QMovie(this);
	m_currentEmoticon->setMovie(m_currentMovie);

	connect(m_emoticonList, SIGNAL(itemEntered(QListWidgetItem*)),
			this, SLOT(mouseOverItem(QListWidgetItem*)));
	connect(m_emoticonList, SIGNAL(itemSelectionChanged()),
			this, SLOT(currentChanged()));
	connect(m_emoticonList, SIGNAL(itemClicked(QListWidgetItem*)),
			this, SLOT(emoticonClicked(QListWidgetItem*)));

	connect(m_emoticonList, SIGNAL(itemActivated(QListWidgetItem*)),
			this, SLOT(emoticonClicked(QListWidgetItem*)));

}

void EmoticonSelector::prepareList(void)
{
//	kDebug(14000) << k_funcinfo << "called." << endl;
	QMap<QString, QStringList> list = Kopete::Emoticons::self()->emoticonAndPicList();

	for (QMap<QString, QStringList>::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
		(void) new EmoticonItem(it.value().first(), it.key(), m_emoticonList);

	m_emoticonList->setIconSize(QSize(32,32));
}

void EmoticonSelector::emoticonClicked(QListWidgetItem *i)
{
	EmoticonItem *item = dynamic_cast<EmoticonItem*>(i);
	if (!item)
		return;

	// KDE4/Qt TODO: use qobject_cast instead.
	emit itemSelected ( item->text() );
	if ( isVisible() && parentWidget() &&
		parentWidget()->inherits("QMenu") )
	{
		parentWidget()->close();
	}
}

void EmoticonSelector::mouseOverItem(QListWidgetItem *item)
{
	item->setSelected(true);
	if (!m_emoticonList->hasFocus())
		m_emoticonList->setFocus();
}

void EmoticonSelector::currentChanged()
{

	if (!m_emoticonList->selectedItems().count())
		return;

	EmoticonItem *item = dynamic_cast<EmoticonItem*>(m_emoticonList->selectedItems().first());
	if (!item)
		return;

	// FIXME: the label is not correctly cleared when changing from a bigger movie to a smaller one
	m_currentMovie->stop();
	m_currentMovie->setFileName(item->pixmapPath());
	m_currentMovie->start();
}

void EmoticonSelector::hideEvent( QHideEvent* )
{
	m_currentMovie->stop();
}

void EmoticonSelector::showEvent( QShowEvent* )
{
	m_currentMovie->start();
}

#include "emoticonselector.moc"

// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before>#include <iostream>
#include <vw/Plate/RpcServices.h>
#include <vw/Plate/Amqp.h>
#include <vw/Core/ProgressCallback.h>
#include <cerrno>

using namespace vw;
using namespace vw::platefile;

#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>

namespace fs = boost::filesystem;
namespace po = boost::program_options;

struct Options {
  std::string filename;
  uint32 clients;
  uint32 id;
  uint32 timeout;
  uint32 block_size;
  uint32 block_count;
  std::string server;
  bool verify;
};

VW_DEFINE_EXCEPTION(Usage, Exception);

void handle_arguments(int argc, char *argv[], Options& opt)
{
  bool help = false;

  po::options_description options("Options");
  options.add_options()
    ("rabbitmq,r",    po::value(&opt.server),   "rabbitmq server (host:port)")
    ("file,f",        po::value(&opt.filename), "File to append to")
    ("num-clients,n", po::value(&opt.clients),  "Number of clients.")
    ("id,i",          po::value(&opt.id),       "This client's id.")
    ("timeout,t",     po::value(&opt.timeout)->default_value(5000), "timeout in ms.")
    ("verify,v",      "Check the file instead of writing it")
    ("block-size,b",  po::value(&opt.block_size)->default_value(4),  "How much should each client write?")
    ("block-count,c", po::value(&opt.block_count)->default_value(std::numeric_limits<uint32>().max()), "How many times should each client write?")
    ("help,h",        "Display this help message.");

  po::variables_map vm;
  po::store( po::command_line_parser( argc, argv ).options(options).run(), vm );
  po::notify( vm );

  std::ostringstream out;

#define REQUIRE(name) do {\
  if (!vm.count(#name)) {\
    out << "Error: missing required parameter \"" #name "\"" << std::endl;\
    help = true;\
  }\
} while (0)

  opt.verify = vm.count("verify");
  help = vm.count("help");

  if (!opt.verify)
    REQUIRE(id);

  REQUIRE(num-clients);
  REQUIRE(file);

#undef REQUIRE

  if( help )
    vw_throw(Usage() << out.str() << "Usage: " << argv[0] << "\n" << options << "\n");

  VW_ASSERT( opt.clients > 0,      Usage() << "Error: # of clients must be > 0."     );
  VW_ASSERT( opt.id < opt.clients, Usage() << "Error: # of clients must be > id."    );
  VW_ASSERT( opt.clients < 10000,  Usage() << "Error: # of clients must be < 10000." );
}

std::string queue_name(const Options& opt) {
  return std::string("client_") + vw::stringify(opt.id);
}
std::string next_queue_name(const Options& opt) {
  return std::string("client_") + vw::stringify((opt.id+1) % opt.clients );
}

void run(const Options& opt) {
  // On first pass with client id 0, there's no message to read.
  bool first_node = (opt.id == 0);

  std::string host = "localhost",
              port = "5672";

  if (!opt.server.empty()) {
      size_t ret = opt.server.find_last_of(":");
      if (ret == std::string::npos)
          host = opt.server;
      else {
          host = opt.server.substr(0,ret);
          port = opt.server.substr(ret+1);
      }
  }

  boost::shared_ptr<AmqpConnection> conn(new AmqpConnection(host, boost::lexical_cast<int>(port)));
  AmqpRpcDumbClient node(conn, "lustre_torture", queue_name(opt));
  node.bind_service(queue_name(opt));

  std::string next = next_queue_name(opt);
  ByteArray send_msg(next.size() + 2);
  send_msg[0] = 'G';
  send_msg[1] = 'O';
  std::copy(next.begin(), next.end(), send_msg.begin()+2);

  TerminalProgressCallback pc;

  vw_out(InfoMessage) << "Ready to create "
                      << opt.clients * opt.block_size * opt.block_count / 1024. / 1024.
                      << "MB file! Waiting 5 seconds for everyone to start." << std::endl;
  sleep(5);

  uint32 blocks_written = 0;
  uint32 tick = opt.block_count / 100;
  while (blocks_written++ < opt.block_count) {
    if (blocks_written % tick == 1) {
      pc.report_incremental_progress(.01);
      pc.print_progress();
    }
    if (first_node) {
      first_node = false;
      // truncate file (and close it implicitly)
      std::ofstream file(opt.filename.c_str(), std::ios::binary|std::ios::trunc);
      VW_ASSERT(file.is_open(), LogicErr() << "Could not truncate file: " << opt.filename);
    } else {
      SharedByteArray msg;
      node.get_bytes(msg, opt.timeout);
      VW_ASSERT(msg->begin()[0] == 'G' && msg->begin()[1] == 'O', LogicErr() << "Buh?");
    }

    std::ofstream file(opt.filename.c_str(), std::ios::binary|std::ios::app);
    VW_ASSERT(file.is_open(), LogicErr() << "Could not open file: " << opt.filename << " (" << strerror(errno) << ")");

    std::string s_id = boost::lexical_cast<std::string>(opt.id);
    s_id.insert(0, opt.block_size-s_id.size(), '0');
    VW_ASSERT(s_id.size() == opt.block_size, LogicErr() << "Must pad s_id to block size");

    file.write(s_id.c_str(), s_id.size());
    file.close();
    // to exacerbate the problem, don't put anything, put the close and the
    // unlock-next-client as close as possible
    node.send_bytes(send_msg, next);
  }
  pc.report_finished();
}

void verify(const Options& opt) {
    std::ifstream file(opt.filename.c_str(), std::ios::binary);
    VW_ASSERT(file.is_open(), LogicErr() << "Could not open file: " << opt.filename << " (" << strerror(errno) << ")");

    uint32 id = 0, next;
    std::vector<char> bytes(opt.block_size+1, 0);
    uint32 failed = 0;
    int32 first_failure = -1;

    TerminalProgressCallback pc;
    uint32 tick = (opt.clients * opt.block_count) / 100;

    uint32 blocks_read = 0;
    while (file.read(&bytes[0], opt.block_size)) {
      if (blocks_read++ % tick == 0) {
        pc.report_incremental_progress(.01);
        pc.print_progress();
      }
      try {
        next = boost::lexical_cast<uint32>(&bytes[0]);
      } catch (const boost::bad_lexical_cast&) {
        next = -1;
      }
      if (next != id) {
        failed++;
        if (first_failure == -1)
            first_failure = blocks_read-1;
      }
      id = (id + 1) % opt.clients;
    }
    pc.report_finished();

    VW_ASSERT(failed == 0, LogicErr() << "Verification failed on " << failed << " blocks (first failure at block " << first_failure << ")");
}

int main(int argc, char *argv[]) {
  Options opt;
  try {
    handle_arguments(argc, argv, opt);
    if (opt.verify)
      verify(opt);
    else
      run(opt);
  } catch (const Usage& e) {
    std::cout << e.what() << std::endl;
    return 1;
  } catch (const AMQPTimeout&) {
    std::cout << "Timeout!" << std::endl;
    return 0;
  } catch (const Exception& e) {
    std::cerr << "Error: " << e.what() << std::endl;
    return 1;
  }
  return 0;
}
<commit_msg>this should hopefully fix the blob corruption<commit_after>#include <iostream>
#include <vw/Plate/RpcServices.h>
#include <vw/Plate/Amqp.h>
#include <vw/Core/ProgressCallback.h>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <cerrno>

using namespace vw;
using namespace vw::platefile;

#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>

namespace fs = boost::filesystem;
namespace po = boost::program_options;
namespace io = boost::iostreams;

struct Options {
  std::string filename;
  uint32 clients;
  uint32 id;
  uint32 timeout;
  uint32 block_size;
  uint32 block_count;
  std::string server;
  bool verify;
};

VW_DEFINE_EXCEPTION(Usage, Exception);

void handle_arguments(int argc, char *argv[], Options& opt)
{
  bool help = false;

  po::options_description options("Options");
  options.add_options()
    ("rabbitmq,r",    po::value(&opt.server),   "rabbitmq server (host:port)")
    ("file,f",        po::value(&opt.filename), "File to append to")
    ("num-clients,n", po::value(&opt.clients),  "Number of clients.")
    ("id,i",          po::value(&opt.id),       "This client's id.")
    ("timeout,t",     po::value(&opt.timeout)->default_value(5000), "timeout in ms.")
    ("verify,v",      "Check the file instead of writing it")
    ("block-size,b",  po::value(&opt.block_size)->default_value(4),  "How much should each client write?")
    ("block-count,c", po::value(&opt.block_count)->default_value(std::numeric_limits<uint32>().max()), "How many times should each client write?")
    ("help,h",        "Display this help message.");

  po::variables_map vm;
  po::store( po::command_line_parser( argc, argv ).options(options).run(), vm );
  po::notify( vm );

  std::ostringstream out;

#define REQUIRE(name) do {\
  if (!vm.count(#name)) {\
    out << "Error: missing required parameter \"" #name "\"" << std::endl;\
    help = true;\
  }\
} while (0)

  opt.verify = vm.count("verify");
  help = vm.count("help");

  if (!opt.verify)
    REQUIRE(id);

  REQUIRE(num-clients);
  REQUIRE(file);

#undef REQUIRE

  if( help )
    vw_throw(Usage() << out.str() << "Usage: " << argv[0] << "\n" << options << "\n");

  VW_ASSERT( opt.clients > 0,      Usage() << "Error: # of clients must be > 0."     );
  VW_ASSERT( opt.id < opt.clients, Usage() << "Error: # of clients must be > id."    );
  VW_ASSERT( opt.clients < 10000,  Usage() << "Error: # of clients must be < 10000." );
}

std::string queue_name(const Options& opt) {
  return std::string("client_") + vw::stringify(opt.id);
}
std::string next_queue_name(const Options& opt) {
  return std::string("client_") + vw::stringify((opt.id+1) % opt.clients );
}

void run(const Options& opt) {
  // On first pass with client id 0, there's no message to read.
  bool first_node = (opt.id == 0);

  std::string host = "localhost",
              port = "5672";

  if (!opt.server.empty()) {
      size_t ret = opt.server.find_last_of(":");
      if (ret == std::string::npos)
          host = opt.server;
      else {
          host = opt.server.substr(0,ret);
          port = opt.server.substr(ret+1);
      }
  }

  boost::shared_ptr<AmqpConnection> conn(new AmqpConnection(host, boost::lexical_cast<int>(port)));
  AmqpRpcDumbClient node(conn, "lustre_torture", queue_name(opt));
  node.bind_service(queue_name(opt));

  std::string next = next_queue_name(opt);
  ByteArray send_msg(next.size() + 2);
  send_msg[0] = 'G';
  send_msg[1] = 'O';
  std::copy(next.begin(), next.end(), send_msg.begin()+2);

  TerminalProgressCallback pc;

  vw_out(InfoMessage) << "Ready to create "
                      << opt.clients * opt.block_size * opt.block_count / 1024. / 1024.
                      << "MB file! Waiting 5 seconds for everyone to start." << std::endl;
  sleep(5);

  uint32 blocks_written = 0;
  uint32 tick = opt.block_count / 100;
  while (blocks_written++ < opt.block_count) {
    if (blocks_written % tick == 1) {
      pc.report_incremental_progress(.01);
      pc.print_progress();
    }
    if (first_node) {
      first_node = false;
      // truncate file (and close it implicitly)
      io::file_descriptor file(opt.filename.c_str(), std::ios::binary|std::ios::trunc);
      VW_ASSERT(file.is_open(), LogicErr() << "Could not truncate file: " << opt.filename);
    } else {
      SharedByteArray msg;
      node.get_bytes(msg, opt.timeout);
      VW_ASSERT(msg->begin()[0] == 'G' && msg->begin()[1] == 'O', LogicErr() << "Buh?");
    }

    io::file_descriptor file(opt.filename.c_str(), std::ios::binary|std::ios::app);
    VW_ASSERT(file.is_open(), LogicErr() << "Could not open file: " << opt.filename << " (" << strerror(errno) << ")");

    std::string s_id = boost::lexical_cast<std::string>(opt.id);
    s_id.insert(0, opt.block_size-s_id.size(), '0');
    VW_ASSERT(s_id.size() == opt.block_size, LogicErr() << "Must pad s_id to block size");

    file.write(s_id.c_str(), s_id.size());
    // this should actually be fdatasync, but OSX and freebsd are too good to
    // support posix.
    VW_ASSERT(fsync(file.handle()) == 0, IOErr() << "Could not fsync: " << strerror(errno));
    file.close();
    // to exacerbate the problem, don't put anything, put the close and the
    // unlock-next-client as close as possible
    node.send_bytes(send_msg, next);
  }
  pc.report_finished();
}

void verify(const Options& opt) {
    std::ifstream file(opt.filename.c_str(), std::ios::binary);
    VW_ASSERT(file.is_open(), LogicErr() << "Could not open file: " << opt.filename << " (" << strerror(errno) << ")");

    uint32 id = 0, next;
    std::vector<char> bytes(opt.block_size+1, 0);
    uint32 failed = 0;
    int32 first_failure = -1;

    TerminalProgressCallback pc;
    uint32 tick = (opt.clients * opt.block_count) / 100;

    uint32 blocks_read = 0;
    while (file.read(&bytes[0], opt.block_size)) {
      if (blocks_read++ % tick == 0) {
        pc.report_incremental_progress(.01);
        pc.print_progress();
      }
      try {
        next = boost::lexical_cast<uint32>(&bytes[0]);
      } catch (const boost::bad_lexical_cast&) {
        next = -1;
      }
      if (next != id) {
        failed++;
        if (first_failure == -1)
            first_failure = blocks_read-1;
      }
      id = (id + 1) % opt.clients;
    }
    pc.report_finished();

    VW_ASSERT(failed == 0, LogicErr() << "Verification failed on " << failed << " blocks (first failure at block " << first_failure << ")");
}

int main(int argc, char *argv[]) {
  Options opt;
  try {
    handle_arguments(argc, argv, opt);
    if (opt.verify)
      verify(opt);
    else
      run(opt);
  } catch (const Usage& e) {
    std::cout << e.what() << std::endl;
    return 1;
  } catch (const AMQPTimeout&) {
    std::cout << "Timeout!" << std::endl;
    return 0;
  } catch (const Exception& e) {
    std::cerr << "Error: " << e.what() << std::endl;
    return 1;
  }
  return 0;
}
<|endoftext|>


<commit_before>/**
 * @file
 *
 * @brief implementation of the config service class
 *
 * @copyright BSD License (see doc/LICENSE.md or http://www.libelektra.org)
 */

#include <algorithm>
#include <regex>

#include <boost/algorithm/string/predicate.hpp>

#include <service.hpp>

namespace kdbrest
{

namespace service
{

const std::string REGEX_CONF_KEY = "((?:[a-zA-Z_]+(?:\\.?[a-zA-Z_])+)?)\\.?#_?([0-9]+)\\.?((?:[a-zA-Z0-9_#]+(?:\\.?[a-zA-Z0-9_#])+)?)";

/**
 * @brief can be used to load the configuration of the whole application
 *
 * the configuration is loaded from the key database provided by elektra.
 * the result can be used to bootstrap the application (cppcms service).
 */
cppcms::json::value ConfigEngine::loadApplicationConfiguration () const
{
	cppcms::json::value result;
	kdb::KDB kdb;
	kdb::KeySet ks;

	kdb.get (ks, ELEKTRA_REST_CONFIG_ROOT);
	ks = ks.cut (kdb::Key (ELEKTRA_REST_CONFIG_ROOT, KEY_END));

	for (auto elem : ks)
	{
		std::string key =
			elem.getName ().substr (elem.getName ().find (ELEKTRA_REST_CONFIG_ROOT) + strlen (ELEKTRA_REST_CONFIG_ROOT) + 1);
		std::replace (key.begin (), key.end (), '/', '.');

		this->setValue (result, key, elem);
	}

	return result;
}

/**
 * @brief can be used to set a key value to a cppcms::json::value
 *
 * checks the path for an array and recursively sets the value then.
 * for objects the path is simply set.
 *
 * @param config the current configuration value
 * @param path remaining path to set
 * @param key the elektra key containing the value to set
 */
void ConfigEngine::setValue (cppcms::json::value & config, const std::string path, const kdb::Key & key) const
{
	// check if the key contains an array
	std::regex array_regex (REGEX_CONF_KEY);
	std::smatch matches;

	// there is an array in the path
	if (std::regex_match (path, matches, array_regex) && !matches.empty ())
	{
		// here we have a structure like: some.path.before.#_14.array
		// so we delegate call!
		if (!matches.str (1).empty ())
		{
			// next element will be an array, so make one
			try
			{
				config.at (matches.str (1));
			}
			catch (cppcms::json::bad_value_cast & e)
			{
				config.set (matches.str (1), cppcms::json::array ());
			}
			this->setValue (config.at (matches.str (1)), matches.str (0).erase (0, matches.str (1).length () + 1), key);
			return;
		}

		// here we have a structure like: #_14.var
		// while it is not yet sure if ".var" is really there
		int array_index = std::stoi (matches.str (2));
		if (config.type () != cppcms::json::is_array)
		{
			config.set_value (cppcms::json::array ());
		}

		// with remaining part like ".var" we need to call recursively
		if (!matches.str (3).empty ())
		{
			try
			{
				config[array_index];
			}
			catch (cppcms::json::bad_value_cast & e)
			{
				config[array_index] = cppcms::json::object ();
			}
			this->setValue (config[array_index], matches.str (3), key);
			return;
		}

		// otherwise we can set directly
		try
		{
			if (std::to_string (key.get<int> ()).length () == key.get<std::string> ().length ())
			{
				config[array_index] = key.get<int> ();
				return;
			}
		}
		catch (kdb::KeyTypeConversion & e)
		{
			// do nothing, it's fine
		}
		try
		{
			std::string val = key.getString ();
			if (val == "true")
			{
				config[array_index] = true;
			}
			else if (val == "false")
			{
				config[array_index] = false;
			}
			else
			{
				config[array_index] = val;
			}
			return;
		}
		catch (kdb::KeyTypeConversion & e)
		{
			// do nothing, it's fine
		}
	}
	// there is no array in the path, set as object(s)
	else
	{
		try
		{
			if (std::to_string (key.get<int> ()).length () == key.get<std::string> ().length ())
			{
				config.set (path, key.get<int> ());
				return;
			}
		}
		catch (kdb::KeyTypeConversion & e)
		{
			// do nothing, it's fine
		}
		try
		{
			std::string val = key.getString ();
			if (val == "true")
			{
				config.set (path, true);
			}
			else if (val == "false")
			{
				config.set (path, false);
			}
			else
			{
				config.set (path, val);
			}
			return;
		}
		catch (kdb::KeyTypeConversion & e)
		{
			// do nothing, it's fine
		}
	}
}

} // namespace service

} // namespace kdbrest
<commit_msg>rest-backend: fix keyset to cppcms::json::value transformation<commit_after>/**
 * @file
 *
 * @brief implementation of the config service class
 *
 * @copyright BSD License (see doc/LICENSE.md or http://www.libelektra.org)
 */

#include <algorithm>
#include <regex>

#include <boost/algorithm/string/predicate.hpp>

#include <service.hpp>

namespace kdbrest
{

namespace service
{

const std::string REGEX_CONF_KEY = "((?:[a-zA-Z_]+(?:\\.?[a-zA-Z_])+)?)\\.?#_?([0-9]+)\\.?((?:[a-zA-Z0-9_#]+(?:\\.?[a-zA-Z0-9_#])+)?)";

/**
 * @brief can be used to load the configuration of the whole application
 *
 * the configuration is loaded from the key database provided by elektra.
 * the result can be used to bootstrap the application (cppcms service).
 */
cppcms::json::value ConfigEngine::loadApplicationConfiguration () const
{
	cppcms::json::value result;
	kdb::KDB kdb;
	kdb::KeySet ks;

	kdb.get (ks, ELEKTRA_REST_CONFIG_ROOT);
	ks = ks.cut (kdb::Key (ELEKTRA_REST_CONFIG_ROOT, KEY_END));

	for (auto elem : ks)
	{
		std::string key =
			elem.getName ().substr (elem.getName ().find (ELEKTRA_REST_CONFIG_ROOT) + strlen (ELEKTRA_REST_CONFIG_ROOT) + 1);
		std::replace (key.begin (), key.end (), '/', '.');

		this->setValue (result, key, elem);
	}

	return result;
}

/**
 * @brief can be used to set a key value to a cppcms::json::value
 *
 * checks the path for an array and recursively sets the value then.
 * for objects the path is simply set.
 *
 * @param config the current configuration value
 * @param path remaining path to set
 * @param key the elektra key containing the value to set
 */
void ConfigEngine::setValue (cppcms::json::value & config, const std::string path, const kdb::Key & key) const
{
	// check if the key contains an array
	std::regex array_regex (REGEX_CONF_KEY);
	std::smatch matches;

	// there is an array in the path
	if (std::regex_match (path, matches, array_regex) && !matches.empty ())
	{
		// here we have a structure like: some.path.before.#_14.array
		// so we delegate call!
		if (!matches.str (1).empty ())
		{
			// next element will be an array, so make one
			try
			{
				config.at (matches.str (1));
			}
			catch (cppcms::json::bad_value_cast & e)
			{
				config.set (matches.str (1), cppcms::json::array ());
			}
			this->setValue (config.at (matches.str (1)), matches.str (0).erase (0, matches.str (1).length () + 1), key);
			return;
		}

		// here we have a structure like: #_14.var
		// while it is not yet sure if ".var" is really there
		int array_index = std::stoi (matches.str (2));
		if (config.type () != cppcms::json::is_array)
		{
			config.set_value (cppcms::json::array ());
		}

		// with remaining part like ".var" we need to call recursively
		if (!matches.str (3).empty ())
		{
			if (static_cast<int> (config.array ().size ()) <= array_index)
			{
				config[array_index] = cppcms::json::object ();
			}
			this->setValue (config[array_index], matches.str (3), key);
			return;
		}

		// otherwise we can set directly
		try
		{
			config[array_index] = key.get<bool> ();
			return;
		}
		catch (kdb::KeyTypeConversion & e)
		{
			// do nothing, it's fine
		}
		try
		{
			config[array_index] = key.get<int> ();
			return;
		}
		catch (kdb::KeyTypeConversion & e)
		{
			// do nothing, it's fine
		}

		config[array_index] = key.getString ();
		return;
	}
	// there is no array in the path, set as object(s)
	else
	{
		try
		{
			config.set (path, key.get<bool> ());
			return;
		}
		catch (kdb::KeyTypeConversion & e)
		{
			// do nothing, it's fine
		}
		try
		{
			config.set (path, key.get<int> ());
			return;
		}
		catch (kdb::KeyTypeConversion & e)
		{
			// do nothing, it's fine
		}

		config.set (path, key.getString ());
		return;
	}
}

} // namespace service

} // namespace kdbrest
<|endoftext|>


<commit_before>#include <boost/pointer_cast.hpp>
#include "messageStream.h"

using namespace watcher;
using namespace watcher::event;
using namespace std;

INIT_LOGGER(MessageStream, "MessageStream");

MessageStream::MessageStream(const string &serverName_, const Timestamp &startTime_, const float streamRate_) :
    messageStreamFilters(),
    streamRate(streamRate_),
    streamStartTime(startTime_),
    connection(new Client(serverName_))
{
    TRACE_ENTER();
    TRACE_EXIT();
}

bool MessageStream::init()
{
    TRACE_ENTER();
    ClientMessageHandlerPtr tmp(shared_from_this());
    LOG_DEBUG("Setting message handler to this class. this pointer: " << tmp);
    connection->setMessageHandler(tmp);
    TRACE_EXIT();
}

// virtual
MessageStream::~MessageStream()
{
    TRACE_ENTER();
    TRACE_EXIT();
}

bool MessageStream::setStreamTimeStart(const Timestamp &startTime)
{
    TRACE_ENTER()
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::setStreamRate(const float &messageStreamRate)
{
    TRACE_ENTER();
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::getNextMessage(MessagePtr newMessage)
{
    TRACE_ENTER();
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::isStreamReadable() const
{
    TRACE_ENTER();
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::addMessageFilter(const MessageStreamFilter &filter)
{
    TRACE_ENTER();

    assert(0);  // filters are not supported yet.

    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::getMessageTimeRange(Timestamp &startTime, Timestamp endTime)
{
    TRACE_ENTER();
    TRACE_EXIT_RET("true");
    return true;
}

//virtual
std::ostream &MessageStream::toStream(std::ostream &out) const
{
    TRACE_ENTER();
    out << "MessageStream output operator not yet implemented - this space intensionally left blank";
    TRACE_EXIT();
    return out;
}
bool MessageStream::startStream()
{
    TRACE_ENTER();
    // startWatcherMessagePtr mess(new startWatcherMessage);
    // bool retVal=connection.sendMessage(mess);
    // TRACE_EXIT_RET((retVal==true?"true":"false"));
    // return retVal;
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::stopStream()
{
    TRACE_ENTER();
    // stopWatcherMessagePtr mess(new stopWatcherMessage);
    // bool retVal=connection.sendMessage(mess);
    // TRACE_EXIT_RET((retVal==true?"true":"false"));
    // return retVal;
    TRACE_EXIT_RET("true");
    return true;
}

//virtual
bool MessageStream::handleMessageArrive(const MessagePtr message, MessagePtr &response)
{
    TRACE_ENTER();

    bool retVal=ClientMessageHandler::handleMessageArrive(message, response);

    TRACE_EXIT_RET((retVal==true?"true":"false"));
    return retVal;
}

std::ostream &operator<<(std::ostream &out, const MessageStream &messStream)
{
    TRACE_ENTER();
    TRACE_EXIT();
    return out;
}
<commit_msg>messageStream actaully sends start/stop messages now. messageStream "correctly" initializes itself as a shared_ptr to pass into Client data member. THis forces use of "createMessageStream" static function (ctor is now private).<commit_after>#include "messageStream.h"
#include "libwatcher/startWatcherMessage.h"
#include "libwatcher/stopWatcherMessage.h"

using namespace watcher;
using namespace watcher::event;
using namespace std;

INIT_LOGGER(MessageStream, "MessageStream");

MessageStream::MessageStream(const string &serverName_, const Timestamp &startTime_, const float streamRate_) :
    messageStreamFilters(),
    streamRate(streamRate_),
    streamStartTime(startTime_),
    connection(new Client(serverName_))
{
    TRACE_ENTER();
    TRACE_EXIT();
}

// static
MessageStreamPtr MessageStream::createNewMessageStream(const string &serverName_, const Timestamp &startTime_, const float streamRate_)
{
    TRACE_ENTER();
    MessageStreamPtr retVal(new MessageStream(serverName_,startTime_,streamRate_));
    retVal->initConnection();
    TRACE_EXIT();
    return retVal;
}

void MessageStream::initConnection()
{
    TRACE_ENTER();
    connection->setMessageHandler(shared_from_this());
    TRACE_EXIT();
}

// virtual
MessageStream::~MessageStream()
{
    TRACE_ENTER();
    TRACE_EXIT();
}

bool MessageStream::setStreamTimeStart(const Timestamp &startTime)
{
    TRACE_ENTER()
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::setStreamRate(const float &messageStreamRate)
{
    TRACE_ENTER();
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::getNextMessage(MessagePtr newMessage)
{
    TRACE_ENTER();
    sleep(1000000);
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::isStreamReadable() const
{
    TRACE_ENTER();
    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::addMessageFilter(const MessageStreamFilter &filter)
{
    TRACE_ENTER();

    assert(0);  // filters are not supported yet.

    TRACE_EXIT_RET("true");
    return true;
}
bool MessageStream::getMessageTimeRange(Timestamp &startTime, Timestamp endTime)
{
    TRACE_ENTER();
    TRACE_EXIT_RET("true");
    return true;
}

//virtual
std::ostream &MessageStream::toStream(std::ostream &out) const
{
    TRACE_ENTER();
    out << "MessageStream output operator not yet implemented - this space intensionally left blank";
    TRACE_EXIT();
    return out;
}
bool MessageStream::startStream()
{
    TRACE_ENTER();
    StartMessagePtr mess(new StartMessage);
    bool retVal=connection->sendMessage(mess);
    TRACE_EXIT_RET((retVal==true?"true":"false"));
    return retVal;
}
bool MessageStream::stopStream()
{
    TRACE_ENTER();
    StopMessagePtr mess(new StopMessage);
    bool retVal=connection->sendMessage(mess);
    TRACE_EXIT_RET((retVal==true?"true":"false"));
    return retVal;
}

//virtual
bool MessageStream::handleMessageArrive(const MessagePtr message, MessagePtr &response)
{
    TRACE_ENTER();
    bool retVal=ClientMessageHandler::handleMessageArrive(message, response);
    TRACE_EXIT_RET((retVal==true?"true":"false"));
    return retVal;
}

std::ostream &operator<<(std::ostream &out, const MessageStream &messStream)
{
    TRACE_ENTER();
    TRACE_EXIT();
    return out;
}
<|endoftext|>