<commit_before>#define CATCH_CONFIG_MAIN
#include "catch/catch.hpp"

#include <iostream>
#include <vector>
#include "tangram.h"
#define GLFONTSTASH_IMPLEMENTATION
#include "glfontstash.h"

#define ATLAS_WIDTH         512
#define ATLAS_HEIGHT        512
#define TEXT_BUFFER_SIZE    32
#define ID_OVERFLOW_SIZE    TEXT_BUFFER_SIZE * TEXT_BUFFER_SIZE

struct Text {
    fsuint textId;
    float x;
    float y;
    float rotation;
    float alpha;
};

struct UserPtr {
    int screenRes;
    fsuint bufferId;
    std::vector<Text> texts;
};

void createTexTransforms(void* _userPtr, unsigned int _width, unsigned int _height) {
    REQUIRE(_width == TEXT_BUFFER_SIZE);
    REQUIRE(_height == TEXT_BUFFER_SIZE * 2);
}

void updateTransforms(void* _userPtr, unsigned int _xoff, unsigned int _yoff, unsigned int _width,
                              unsigned int _height, const unsigned int* _pixels, void* _ownerPtr) {
    UserPtr* ptr = static_cast<UserPtr*>(_userPtr);

    float screenRes = (float) ptr->screenRes;

    for(auto text : ptr->texts) {
        float i = fmod(text.textId * 2, TEXT_BUFFER_SIZE);
        float j = (text.textId * 2) / TEXT_BUFFER_SIZE;

        REQUIRE(i < TEXT_BUFFER_SIZE);
        REQUIRE(j < TEXT_BUFFER_SIZE * 2);

        unsigned int p = (unsigned int) (j * TEXT_BUFFER_SIZE + i);

        unsigned int packByte1 = _pixels[p];
        unsigned int packByte2 = _pixels[p + 1];

        int x = ((packByte1 & 0x000000ff) >>  0);
        int y = ((packByte1 & 0x0000ff00) >>  8);
        int r = ((packByte1 & 0x00ff0000) >> 16);
        int a = ((packByte1 & 0xff000000) >> 24);

        REQUIRE(a < 256); REQUIRE(a >= 0);
        REQUIRE(r < 256); REQUIRE(r >= 0);
        REQUIRE(x < 256); REQUIRE(x >= 0);
        REQUIRE(y < 256); REQUIRE(y >= 0);

        int px = (packByte2 & 0x000000ff) >> 0;
        int py = (packByte2 & 0x0000ff00) >> 8;

        REQUIRE(px < 256); REQUIRE(px >= 0);
        REQUIRE(py < 256); REQUIRE(py >= 0);

        float txe = screenRes / 255.0; // max translation x error
        float tye = screenRes / 255.0; // max translation y error

        float rx = (x / 255.0) * screenRes;
        float ry = (y / 255.0) * screenRes;

        // tests that the original results fits inside results with its logical error
        REQUIRE(text.x < rx + txe);
        REQUIRE(text.y < ry + tye);
        REQUIRE(text.x > rx - txe);
        REQUIRE(text.y > ry - tye);

        // compute the result and add the precision, see text.vs
        rx = rx + txe * (px / 255.0);
        ry = ry + tye * (py / 255.0);

        // result error
        float dx = fabs(text.x - rx);
        float dy = fabs(text.y - ry);

        // theoritical floating point precision error on precision encoding, see glfontstash.h
        float perror = 0.00196f;

        float epxe = txe * perror; // theoritical encoded error on translation x
        float epye = tye * perror; // theoritical encoded error on translation y

        // test that final result with its precision added is lower than the theoritical one
        REQUIRE(dx <= epxe);
        REQUIRE(dy <= epye);
    }
}

void updateAtlas(void* _userPtr, unsigned int _xoff, unsigned int _yoff,
                         unsigned int _width, unsigned int _height, const unsigned int* _pixels) {

}

void createAtlas(void* _userPtr, unsigned int _width, unsigned int _height) {
    REQUIRE(_width == ATLAS_WIDTH);
    REQUIRE(_height == ATLAS_HEIGHT);
}

bool errorCallback(void* _userPtr, fsuint buffer, GLFONSError error) {
    UserPtr* ptr = static_cast<UserPtr*>(_userPtr);

    REQUIRE(error == GLFONSError::ID_OVERFLOW);
    REQUIRE(ptr->bufferId == buffer);

    return false;
}

FONScontext* initContext(void* _usrPtr) {
    GLFONSparams params;

    params.errorCallback = errorCallback;
    params.createAtlas = createAtlas;
    params.createTexTransforms = createTexTransforms;
    params.updateAtlas = updateAtlas;
    params.updateTransforms = updateTransforms;

    return glfonsCreate(ATLAS_WIDTH, ATLAS_HEIGHT, FONS_ZERO_TOPLEFT, params, _usrPtr);
}

int initFont(FONScontext* _context) {
    unsigned int dataSize;
    unsigned char* data = bytesFromResource("Roboto-Regular.ttf", &dataSize);

    return fonsAddFont(_context, "droid-serif", data, dataSize);
}

TEST_CASE( "Test context initialization", "[Core][Fontstash][glfonsCreate]" ) {
    FONScontext* context = initContext(nullptr);

    REQUIRE(context != NULL);

    glfonsDelete(context);
}

TEST_CASE( "Test .ttf file initialization", "[Core][Fontstash][fonsAddFont]" ) {
    FONScontext* context = initContext(nullptr);
    int font = initFont(context);

    REQUIRE(font != FONS_INVALID);

    glfonsDelete(context);
}

TEST_CASE( "Test the buffer creation and the size of the required texture transform", "[Core][Fontstash][glfonsBufferCreate]" ) {
    FONScontext* context = initContext(nullptr);

    fsuint buffer;
    glfonsBufferCreate(context, TEXT_BUFFER_SIZE, &buffer);

    glfonsDelete(context);
}

TEST_CASE( "Test that the overflow callback gets called for the right overflow size", "[Core][Fontstash][errorCallback]" ) {
    UserPtr p;

    FONScontext* context = initContext(&p);
    int font = initFont(context);

    glfonsBufferCreate(context, TEXT_BUFFER_SIZE, &p.bufferId);
    glfonsBindBuffer(context, p.bufferId);

    fsuint id[ID_OVERFLOW_SIZE + 1];
    // create an overflow
    glfonsGenText(context, ID_OVERFLOW_SIZE + 1, id);

    glfonsDelete(context);
}

TEST_CASE( "Test that the number of vertices correspond to the logic", "[Core][Fontstash][glfonsVertices]" ) {
    UserPtr p;

    FONScontext* context = initContext(&p);
    int font = initFont(context);

    glfonsBufferCreate(context, TEXT_BUFFER_SIZE, &p.bufferId);
    glfonsBindBuffer(context, p.bufferId);

    fonsSetSize(context, 15.0);
    fonsSetFont(context, font);

    fsuint id;
    glfonsGenText(context, 1, &id);

    std::string text("tangram");
    glfonsRasterize(context, id, text.c_str());

    std::vector<float> vertices;
    int nverts = 0;
    glfonsVertices(context, &vertices, &nverts);

    REQUIRE(nverts == text.size() * 6); // shoud have 6 vertices per glyph

    glfonsDelete(context);
}

TEST_CASE( "Test that unpacking the encoded transforms give expected results", "[Core][Fontstash][glfonsTransform]" ) {
    UserPtr p;
    FONScontext* context = initContext(&p);
    int font = initFont(context);

    glfonsBufferCreate(context, TEXT_BUFFER_SIZE, &p.bufferId);
    glfonsBindBuffer(context, p.bufferId);

    fonsSetSize(context, 15.0);
    fonsSetFont(context, font);

    p.screenRes = 1024;

    glfonsScreenSize(context, p.screenRes, p.screenRes);

    for(int i = 0; i < 1024; i+=24) {
        Text text;

        glfonsGenText(context, 1, &text.textId);

        text.x = i;
        text.y = i / 2.0;
        text.rotation = i * M_PI;
        text.alpha = 0.5;

        std::string str("tangram");
        glfonsRasterize(context, text.textId, str.c_str());
        glfonsTransform(context, text.textId, text.x, text.y, text.rotation, text.alpha);

        p.texts.push_back(text);
    }

    glfonsUpdateTransforms(context, nullptr);

    std::vector<float> vertices;
    int nverts = 0;
    glfonsVertices(context, &vertices, &nverts);

    glfonsDelete(context);
}
<commit_msg>update unit tests<commit_after>#define CATCH_CONFIG_MAIN
#include "catch/catch.hpp"

#include <iostream>
#include <vector>
#include "tangram.h"
#define GLFONTSTASH_IMPLEMENTATION
#include "glfontstash.h"

#define ATLAS_WIDTH         512
#define ATLAS_HEIGHT        512
#define TEXT_BUFFER_SIZE    32
#define ID_OVERFLOW_SIZE    TEXT_BUFFER_SIZE * TEXT_BUFFER_SIZE

struct Text {
    fsuint textId;
    float x;
    float y;
    float rotation;
    float alpha;
};

struct UserPtr {
    int screenRes;
    fsuint bufferId;
    std::vector<Text> texts;
};

void createTexTransforms(void* _userPtr, unsigned int _width, unsigned int _height) {
    REQUIRE(_width == TEXT_BUFFER_SIZE);
    REQUIRE(_height == TEXT_BUFFER_SIZE * 2);
}

void updateTransforms(void* _userPtr, unsigned int _xoff, unsigned int _yoff, unsigned int _width,
                              unsigned int _height, const unsigned int* _pixels, void* _ownerPtr) {
    UserPtr* ptr = static_cast<UserPtr*>(_userPtr);

    float screenRes = (float) ptr->screenRes;

    for(auto text : ptr->texts) {
        float i = fmod(text.textId * 2, TEXT_BUFFER_SIZE);
        float j = (text.textId * 2) / TEXT_BUFFER_SIZE;

        REQUIRE(i < TEXT_BUFFER_SIZE);
        REQUIRE(j < TEXT_BUFFER_SIZE * 2);

        unsigned int p = (unsigned int) (j * TEXT_BUFFER_SIZE + i);

        unsigned int packByte1 = _pixels[p];
        unsigned int packByte2 = _pixels[p + 1];

        int x = ((packByte1 & 0x000000ff) >>  0);
        int y = ((packByte1 & 0x0000ff00) >>  8);
        int r = ((packByte1 & 0x00ff0000) >> 16);
        int a = ((packByte1 & 0xff000000) >> 24);

        REQUIRE(a < 256); REQUIRE(a >= 0);
        REQUIRE(r < 256); REQUIRE(r >= 0);
        REQUIRE(x < 256); REQUIRE(x >= 0);
        REQUIRE(y < 256); REQUIRE(y >= 0);

        int px = (packByte2 & 0x000000ff) >> 0;
        int py = (packByte2 & 0x0000ff00) >> 8;

        REQUIRE(px < 256); REQUIRE(px >= 0);
        REQUIRE(py < 256); REQUIRE(py >= 0);

        float txe = screenRes / 255.0; // max translation x error
        float tye = screenRes / 255.0; // max translation y error

        float rx = (x / 255.0) * screenRes;
        float ry = (y / 255.0) * screenRes;

        // tests that the original results fits inside results with its logical error
        REQUIRE(text.x < rx + txe);
        REQUIRE(text.y < ry + tye);
        REQUIRE(text.x > rx - txe);
        REQUIRE(text.y > ry - tye);

        // compute the result and add the precision, see text.vs
        rx = rx + txe * (px / 255.0);
        ry = ry + tye * (py / 255.0);

        // result error
        float dx = fabs(text.x - rx);
        float dy = fabs(text.y - ry);

        // theoritical floating point precision error on precision encoding, see glfontstash.h
        float perror = 0.00196f;

        float epxe = txe * perror; // theoritical encoded error on translation x
        float epye = tye * perror; // theoritical encoded error on translation y

        // test that final result with its precision added is lower than the theoritical one
        REQUIRE(dx <= epxe);
        REQUIRE(dy <= epye);
    }
}

void updateAtlas(void* _userPtr, unsigned int _xoff, unsigned int _yoff,
                         unsigned int _width, unsigned int _height, const unsigned int* _pixels) {

}

void createAtlas(void* _userPtr, unsigned int _width, unsigned int _height) {
    REQUIRE(_width == ATLAS_WIDTH);
    REQUIRE(_height == ATLAS_HEIGHT);
}

bool errorCallback(void* _userPtr, fsuint buffer, GLFONSError error) {
    UserPtr* ptr = static_cast<UserPtr*>(_userPtr);

    REQUIRE(error == GLFONSError::ID_OVERFLOW);
    REQUIRE(ptr->bufferId == buffer);

    return false;
}

FONScontext* initContext(void* _usrPtr) {
    GLFONSparams params;

    params.errorCallback = errorCallback;
    params.createAtlas = createAtlas;
    params.createTexTransforms = createTexTransforms;
    params.updateAtlas = updateAtlas;
    params.updateTransforms = updateTransforms;

    return glfonsCreate(ATLAS_WIDTH, ATLAS_HEIGHT, FONS_ZERO_TOPLEFT, params, _usrPtr);
}

int initFont(FONScontext* _context) {
    unsigned int dataSize;
    unsigned char* data = bytesFromResource("Roboto-Regular.ttf", &dataSize);

    return fonsAddFont(_context, "droid-serif", data, dataSize);
}

TEST_CASE( "Test context initialization", "[Core][Fontstash][glfonsCreate]" ) {
    FONScontext* context = initContext(nullptr);

    REQUIRE(context != NULL);

    glfonsDelete(context);
}

TEST_CASE( "Test .ttf file initialization", "[Core][Fontstash][fonsAddFont]" ) {
    FONScontext* context = initContext(nullptr);
    int font = initFont(context);

    REQUIRE(font != FONS_INVALID);

    glfonsDelete(context);
}

TEST_CASE( "Test the buffer creation and the size of the required texture transform", "[Core][Fontstash][glfonsBufferCreate]" ) {
    FONScontext* context = initContext(nullptr);

    fsuint buffer;
    glfonsBufferCreate(context, TEXT_BUFFER_SIZE, &buffer);

    glfonsDelete(context);
}

TEST_CASE( "Test that the overflow callback gets called for the right overflow size", "[Core][Fontstash][errorCallback]" ) {
    UserPtr p;

    FONScontext* context = initContext(&p);
    int font = initFont(context);

    glfonsBufferCreate(context, TEXT_BUFFER_SIZE, &p.bufferId);
    glfonsBindBuffer(context, p.bufferId);

    fsuint id[ID_OVERFLOW_SIZE + 1];
    // create an overflow
    glfonsGenText(context, ID_OVERFLOW_SIZE + 1, id);

    glfonsDelete(context);
}

TEST_CASE( "Test that the number of vertices correspond to the logic", "[Core][Fontstash][glfonsVertices]" ) {
    UserPtr p;

    FONScontext* context = initContext(&p);
    int font = initFont(context);

    glfonsBufferCreate(context, TEXT_BUFFER_SIZE, &p.bufferId);
    glfonsBindBuffer(context, p.bufferId);

    fonsSetSize(context, 15.0);
    fonsSetFont(context, font);

    fsuint id;
    glfonsGenText(context, 1, &id);

    std::string text("tangram");
    glfonsRasterize(context, id, text.c_str());

    std::vector<float> vertices;
    int size = glfonsVerticesSize(context);
    vertices.resize(size * INNER_DATA_OFFSET);
    glfonsVertices(context, reinterpret_cast<float*>(vertices.data()));

    REQUIRE(size == text.size() * 6); // shoud have 6 vertices per glyph

    glfonsDelete(context);
}

TEST_CASE( "Test that unpacking the encoded transforms give expected results", "[Core][Fontstash][glfonsTransform]" ) {
    UserPtr p;
    FONScontext* context = initContext(&p);
    int font = initFont(context);

    glfonsBufferCreate(context, TEXT_BUFFER_SIZE, &p.bufferId);
    glfonsBindBuffer(context, p.bufferId);

    fonsSetSize(context, 15.0);
    fonsSetFont(context, font);

    p.screenRes = 1024;

    glfonsScreenSize(context, p.screenRes, p.screenRes);

    for(int i = 0; i < 1024; i+=24) {
        Text text;

        glfonsGenText(context, 1, &text.textId);

        text.x = i;
        text.y = i / 2.0;
        text.rotation = i * M_PI;
        text.alpha = 0.5;

        std::string str("tangram");
        glfonsRasterize(context, text.textId, str.c_str());
        glfonsTransform(context, text.textId, text.x, text.y, text.rotation, text.alpha);

        p.texts.push_back(text);
    }

    glfonsUpdateTransforms(context, nullptr);

    std::vector<float> vertices;
    int size = glfonsVerticesSize(context);
    vertices.resize(size * INNER_DATA_OFFSET);
    glfonsVertices(context, reinterpret_cast<float*>(vertices.data()));

    glfonsDelete(context);
}
<|endoftext|>


<commit_before>// Copyright (c) 2007-2010 Paul Hodge. All rights reserved.

#include "common_headers.h"

#include "builtins.h"
#include "term.h"
#include "type.h"

namespace circa {

bool check_invariants(Term* term, std::string& result)
{
    if (term->value_type == NULL) {
        result = "TaggedValue has null type";
        ca_assert(false);
        return false;
    }

    if (term->type != NULL
            && (term->value_type != &as_type(term->type))
            && term->type != ANY_TYPE
            && !is_branch(term)) {
        result = "Value has wrong type: term->type is " + term->type->name + ", tag is "
            + term->value_type->name;
        ca_assert(false);
        return false;
    }

    if (term->nestedContents.owningTerm != term) {
        result = "Term.nestedContents has wrong owningTerm";
        return false;
    }

    if (term->owningBranch != NULL) {
        Branch& branch = *term->owningBranch;
        if ((term->index >= branch.length())
                || (branch[term->index] != term)) {
            result = "Term.index doesn't resolve to this term in owningBranch";
            return false;
        }
    }

    return true;
}

} // namespace circa
<commit_msg>Bug fix in check_invariants<commit_after>// Copyright (c) 2007-2010 Paul Hodge. All rights reserved.

#include "common_headers.h"

#include "builtins.h"
#include "term.h"
#include "type.h"

namespace circa {

bool check_invariants(Term* term, std::string& result)
{
    if (term->value_type == NULL) {
        result = "TaggedValue has null type";
        return false;
    }

    if (term->type != NULL
            && term->type != ANY_TYPE
            && !value_fits_type(term, type_contents(term->type))) {
        result = "Value has wrong type: term->type is " + term->type->name + ", tag is "
            + term->value_type->name;
        return false;
    }

    if (term->nestedContents.owningTerm != term) {
        result = "Term.nestedContents has wrong owningTerm";
        return false;
    }

    if (term->owningBranch != NULL) {
        Branch& branch = *term->owningBranch;
        if ((term->index >= branch.length())
                || (branch[term->index] != term)) {
            result = "Term.index doesn't resolve to this term in owningBranch";
            return false;
        }
    }

    return true;
}

} // namespace circa
<|endoftext|>


<commit_before>/*
 * imageio.hpp
 *
 *  Created on: Aug 25, 2009
 *      Author: rasmussn
 */

#ifndef IMAGEIO_HPP_
#define IMAGEIO_HPP_

#include "../columns/Communicator.hpp"
#include "../include/pv_types.h"

int getImageInfo(    const char * filename, PV::Communicator * comm, PVLayerLoc * loc);
int getImageInfoPVP( const char * filename, PV::Communicator * comm, PVLayerLoc * loc);
int getImageInfoGDAL(const char * filename, PV::Communicator * comm, PVLayerLoc * loc);

int gatherImageFile(    const char * filename,
                        PV::Communicator * comm, const PVLayerLoc * loc, unsigned char * buf);
int gatherImageFile(    const char * filename,
                        PV::Communicator * comm, const PVLayerLoc * loc, pvdata_t * buf);
int gatherImageFilePVP( const char * filename,
                        PV::Communicator * comm, const PVLayerLoc * loc, unsigned char * buf);
int gatherImageFileGDAL(const char * filename,
                        PV::Communicator * comm, const PVLayerLoc * loc, unsigned char * buf);

int scatterImageFile(    const char * filename, int offsetX, int offsetY,
                         PV::Communicator * comm, PVLayerLoc * loc, unsigned char * buf);
int scatterImageFilePVP( const char * filename,
                         PV::Communicator * comm, PVLayerLoc * loc, unsigned char * buf);
int scatterImageFileGDAL(const char * filename, int offsetX, int offsetY,
                         PV::Communicator * comm, PVLayerLoc * loc, unsigned char * buf);

int scatter(PV::Communicator * comm, PVLayerLoc * loc, unsigned char * buf);
int gather (PV::Communicator * comm, const PVLayerLoc * loc,
            unsigned char * dstBuf, unsigned char * srcBuf);

int scatter(PV::Communicator * comm, PVLayerLoc * loc, float * buf);
int gather (PV::Communicator * comm, const PVLayerLoc * loc, float * buf);

int writeWithBorders(const char * filename, PVLayerLoc * loc, float * buf);

#endif /* IMAGEIO_HPP_ */
<commit_msg>Added out of bounds check for image patch offset.  Also renamed to xOffset, yOffset to be consistent with usage in this imageio file.<commit_after>/*
 * imageio.hpp
 *
 *  Created on: Aug 25, 2009
 *      Author: rasmussn
 */

#ifndef IMAGEIO_HPP_
#define IMAGEIO_HPP_

#include "../columns/Communicator.hpp"
#include "../include/pv_types.h"

int getImageInfo(    const char * filename, PV::Communicator * comm, PVLayerLoc * loc);
int getImageInfoPVP( const char * filename, PV::Communicator * comm, PVLayerLoc * loc);
int getImageInfoGDAL(const char * filename, PV::Communicator * comm, PVLayerLoc * loc);

int gatherImageFile(    const char * filename,
                        PV::Communicator * comm, const PVLayerLoc * loc, unsigned char * buf);
int gatherImageFile(    const char * filename,
                        PV::Communicator * comm, const PVLayerLoc * loc, pvdata_t * buf);
int gatherImageFilePVP( const char * filename,
                        PV::Communicator * comm, const PVLayerLoc * loc, unsigned char * buf);
int gatherImageFileGDAL(const char * filename,
                        PV::Communicator * comm, const PVLayerLoc * loc, unsigned char * buf);

int scatterImageFile(    const char * filename, int xOffset, int yOffset,
                         PV::Communicator * comm, PVLayerLoc * loc, unsigned char * buf);
int scatterImageFilePVP( const char * filename,
                         PV::Communicator * comm, PVLayerLoc * loc, unsigned char * buf);
int scatterImageFileGDAL(const char * filename, int xOffset, int yOffset,
                         PV::Communicator * comm, PVLayerLoc * loc, unsigned char * buf);

int scatter(PV::Communicator * comm, PVLayerLoc * loc, unsigned char * buf);
int gather (PV::Communicator * comm, const PVLayerLoc * loc,
            unsigned char * dstBuf, unsigned char * srcBuf);

int scatter(PV::Communicator * comm, PVLayerLoc * loc, float * buf);
int gather (PV::Communicator * comm, const PVLayerLoc * loc, float * buf);

int writeWithBorders(const char * filename, PVLayerLoc * loc, float * buf);

#endif /* IMAGEIO_HPP_ */
<|endoftext|>


<commit_before>/*
* Copyright (C) 2008-2012 J-P Nurmi <jpnurmi@gmail.com>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
* License for more details.
*/

#include "ircdecoder_p.h"
#include "irccodecplugin.h"
#include <QCoreApplication>
#include <QPluginLoader>
#include <QStringList>
#include <QDebug>
#include <QMap>
#include <QDir>

typedef QMap<QByteArray, IrcCodecPlugin*> IrcCodecPluginMap;
Q_GLOBAL_STATIC(IrcCodecPluginMap, irc_codec_plugins)

IrcDecoder::IrcDecoder()
{
    d.fallback = QTextCodec::codecForName("UTF-8");
}

IrcDecoder::~IrcDecoder()
{
}

QByteArray IrcDecoder::encoding() const
{
    return d.fallback->name();
}

void IrcDecoder::setEncoding(const QByteArray& encoding)
{
    if (QTextCodec::availableCodecs().contains(encoding))
        d.fallback = QTextCodec::codecForName(encoding);
}

QString IrcDecoder::decode(const QByteArray& data) const
{
    static QByteArray pluginKey;
    static bool initialized = false;
    if (!initialized)
    {
        pluginKey = const_cast<IrcDecoder*>(this)->initialize();
        initialized = true;
    }

    QByteArray name = d.fallback->name();
    IrcCodecPlugin* plugin = irc_codec_plugins()->value(pluginKey);
    if (plugin)
        name = plugin->codecForData(data);

    QTextCodec* codec = QTextCodec::codecForName(name);
    if (!codec)
        codec = d.fallback;
    Q_ASSERT(codec);
    return codec->toUnicode(data);
}

QByteArray IrcDecoder::initialize()
{
    bool loaded = loadPlugins();
    QByteArray pluginKey = qgetenv("COMMUNI_CODEC_PLUGIN");
    if (!pluginKey.isEmpty() && !irc_codec_plugins()->contains(pluginKey))
    {
        qWarning() << "IrcDecoder:" << pluginKey << "plugin not loaded";
        if (loaded)
            qWarning() << "IrcDecoder: available plugins:" << irc_codec_plugins()->keys();
    }
    if (!loaded)
        qWarning() << "IrcDecoder: no plugins available";

    if (pluginKey.isEmpty())
        pluginKey = "uchardet";
    return pluginKey;
}

bool IrcDecoder::loadPlugins()
{
    foreach (const QString& path, QCoreApplication::libraryPaths())
    {
        QDir dir(path);
        if (!dir.cd("communi"))
            continue;

        foreach (const QFileInfo& file, dir.entryInfoList(QDir::Files))
        {
            QPluginLoader loader(file.absoluteFilePath());
            IrcCodecPlugin* plugin = qobject_cast<IrcCodecPlugin*>(loader.instance());
            if (plugin)
                irc_codec_plugins()->insert(plugin->key(), plugin);
        }
    }
    return !irc_codec_plugins()->isEmpty();
}
<commit_msg>IrcDecoder: add support for COMMUNI_PLUGIN_PATH in conjunction with QT_PLUGIN_PATH<commit_after>/*
* Copyright (C) 2008-2012 J-P Nurmi <jpnurmi@gmail.com>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
* License for more details.
*/

#include "ircdecoder_p.h"
#include "irccodecplugin.h"
#include <QCoreApplication>
#include <QPluginLoader>
#include <QStringList>
#include <QDebug>
#include <QMap>
#include <QDir>

typedef QMap<QByteArray, IrcCodecPlugin*> IrcCodecPluginMap;
Q_GLOBAL_STATIC(IrcCodecPluginMap, irc_codec_plugins)

IrcDecoder::IrcDecoder()
{
    d.fallback = QTextCodec::codecForName("UTF-8");
}

IrcDecoder::~IrcDecoder()
{
}

QByteArray IrcDecoder::encoding() const
{
    return d.fallback->name();
}

void IrcDecoder::setEncoding(const QByteArray& encoding)
{
    if (QTextCodec::availableCodecs().contains(encoding))
        d.fallback = QTextCodec::codecForName(encoding);
}

QString IrcDecoder::decode(const QByteArray& data) const
{
    static QByteArray pluginKey;
    static bool initialized = false;
    if (!initialized)
    {
        pluginKey = const_cast<IrcDecoder*>(this)->initialize();
        initialized = true;
    }

    QByteArray name = d.fallback->name();
    IrcCodecPlugin* plugin = irc_codec_plugins()->value(pluginKey);
    if (plugin)
        name = plugin->codecForData(data);

    QTextCodec* codec = QTextCodec::codecForName(name);
    if (!codec)
        codec = d.fallback;
    Q_ASSERT(codec);
    return codec->toUnicode(data);
}

QByteArray IrcDecoder::initialize()
{
    bool loaded = loadPlugins();
    QByteArray pluginKey = qgetenv("COMMUNI_CODEC_PLUGIN");
    if (!pluginKey.isEmpty() && !irc_codec_plugins()->contains(pluginKey))
    {
        qWarning() << "IrcDecoder:" << pluginKey << "plugin not loaded";
        if (loaded)
            qWarning() << "IrcDecoder: available plugins:" << irc_codec_plugins()->keys();
    }
    if (!loaded)
        qWarning() << "IrcDecoder: no plugins available";

    if (pluginKey.isEmpty())
        pluginKey = "uchardet";
    return pluginKey;
}

#if defined(Q_OS_WIN)
#define COMMUNI_PATH_SEPARATOR ';'
#else
#define COMMUNI_PATH_SEPARATOR ':'
#endif

static QStringList pluginPaths()
{
    QStringList paths = QCoreApplication::libraryPaths();
    const QByteArray env = qgetenv("COMMUNI_PLUGIN_PATH");
    if (!env.isEmpty())
    {
        foreach (const QString& path, QFile::decodeName(env).split(COMMUNI_PATH_SEPARATOR, QString::SkipEmptyParts))
        {
            QString canonicalPath = QDir(path).canonicalPath();
            if (!canonicalPath.isEmpty() && !paths.contains(canonicalPath))
                paths += canonicalPath;
        }
    }
    return paths;
}

bool IrcDecoder::loadPlugins()
{
    foreach (const QString& path, pluginPaths())
    {
        QDir dir(path);
        if (!dir.cd("communi"))
            continue;

        foreach (const QFileInfo& file, dir.entryInfoList(QDir::Files))
        {
            QPluginLoader loader(file.absoluteFilePath());
            IrcCodecPlugin* plugin = qobject_cast<IrcCodecPlugin*>(loader.instance());
            if (plugin)
                irc_codec_plugins()->insert(plugin->key(), plugin);
        }
    }
    return !irc_codec_plugins()->isEmpty();
}
<|endoftext|>


<commit_before>#include "S3StreamDefaults.h"
#include <ossim/base/ossimPreferences.h>
#include <ossim/base/ossimEnvironmentUtility.h>
#include <ossim/base/ossimTrace.h>

ossim_int64 ossim::S3StreamDefaults::m_readBlocksize = 32768;
ossim_int64 ossim::S3StreamDefaults::m_nReadCacheHeaders = 10000;
bool ossim::S3StreamDefaults::m_cacheInvalidLocations = true;

static ossimTrace traceDebug("ossimS3StreamDefaults:debug");

void ossim::S3StreamDefaults::loadDefaults()
{
   if(traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "ossim::S3StreamDefaults::loadDefaults() DEBUG: entered.....\n";
   }
   ossimString s3ReadBlocksize       = ossimEnvironmentUtility::instance()->getEnvironmentVariable("OSSIM_PLUGINS_AWS_S3_READBLOCKSIZE");
   ossimString nReadCacheHeaders     = ossimEnvironmentUtility::instance()->getEnvironmentVariable("OSSIM_PLUGINS_AWS_S3_NREADCACHEHEADERS");
   ossimString cacheInvalidLocations = ossimEnvironmentUtility::instance()->getEnvironmentVariable("OSSIM_PLUGINS_AWS_S3_CACHEINVALIDLOCATIONS");

   if(s3ReadBlocksize.empty())
   {
       s3ReadBlocksize = ossimPreferences::instance()->findPreference("ossim.plugins.aws.s3.readBlocksize");
   }
   if(cacheInvalidLocations.empty())
   {
       cacheInvalidLocations = ossimPreferences::instance()->findPreference("ossim.plugins.aws.s3.cacheInvalidLocations");
   }
   if(!cacheInvalidLocations.empty())
   {
      m_cacheInvalidLocations = cacheInvalidLocations.toBool();
   }
   if(!s3ReadBlocksize.empty())
   {
     ossim_int64 blockSize = s3ReadBlocksize.toInt64();
     if(blockSize > 0)
     {
         ossimString byteType(s3ReadBlocksize.begin()+(s3ReadBlocksize.size()-1), s3ReadBlocksize.end());
         byteType.upcase();
         m_readBlocksize = blockSize;
         if ( byteType == "K")
         {
            m_readBlocksize *=static_cast<ossim_int64>(1024);
         }
         else if ( byteType == "M")
         {
            m_readBlocksize *=static_cast<ossim_int64>(1048576);
         }
         else if ( byteType == "G")
         {
            m_readBlocksize *=static_cast<ossim_int64>(1073741824);
         }
     }
   }
   if(nReadCacheHeaders.empty())
   {
     nReadCacheHeaders = ossimPreferences::instance()->findPreference("ossim.plugins.aws.s3.nReadCacheHeaders");
   }
   if(!nReadCacheHeaders.empty())
   {
      m_nReadCacheHeaders =  nReadCacheHeaders.toInt64();
      if(m_nReadCacheHeaders < 0)
      {
        m_nReadCacheHeaders = 10000;
      }
   }
   if(traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "m_readBlocksize: " << m_readBlocksize << "\n";
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "m_nReadCacheHeaders: " << m_nReadCacheHeaders << "\n";
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "ossim::S3StreamDefaults::loadDefaults() DEBUG: leaving.....\n";
   }
}
<commit_msg>Forgot to check this into dev<commit_after>#include "S3StreamDefaults.h"
#include <ossim/base/ossimPreferences.h>
#include <ossim/base/ossimEnvironmentUtility.h>
#include <ossim/base/ossimTrace.h>

ossim_int64 ossim::S3StreamDefaults::m_readBlocksize = 32768;
ossim_int64 ossim::S3StreamDefaults::m_nReadCacheHeaders = 10000;
bool ossim::S3StreamDefaults::m_cacheInvalidLocations = true;

static ossimTrace traceDebug("ossimS3StreamDefaults:debug");

void ossim::S3StreamDefaults::loadDefaults()
{
   if(traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "ossim::S3StreamDefaults::loadDefaults() DEBUG: entered.....\n";
   }
   ossimString s3ReadBlocksize       = ossimEnvironmentUtility::instance()->getEnvironmentVariable("OSSIM_PLUGINS_AWS_S3_READBLOCKSIZE");
   ossimString nReadCacheHeaders     = ossimEnvironmentUtility::instance()->getEnvironmentVariable("OSSIM_PLUGINS_AWS_S3_NREADCACHEHEADERS");
   ossimString cacheInvalidLocations = ossimEnvironmentUtility::instance()->getEnvironmentVariable("OSSIM_PLUGINS_AWS_S3_CACHEINVALIDLOCATIONS");

   if(s3ReadBlocksize.empty())
   {
       s3ReadBlocksize = ossimPreferences::instance()->findPreference("ossim.plugins.aws.s3.readBlocksize");
   }
   if(cacheInvalidLocations.empty())
   {
       cacheInvalidLocations = ossimPreferences::instance()->findPreference("ossim.plugins.aws.s3.cacheInvalidLocations");
   }
   if(!cacheInvalidLocations.empty())
   {
      m_cacheInvalidLocations = cacheInvalidLocations.toBool();
   }
   if(!s3ReadBlocksize.empty())
   {
     ossim_int64 blockSize = s3ReadBlocksize.memoryUnitToInt64();
   }
   if(nReadCacheHeaders.empty())
   {
     nReadCacheHeaders = ossimPreferences::instance()->findPreference("ossim.plugins.aws.s3.nReadCacheHeaders");
   }
   if(!nReadCacheHeaders.empty())
   {
      m_nReadCacheHeaders =  nReadCacheHeaders.toInt64();
      if(m_nReadCacheHeaders < 0)
      {
        m_nReadCacheHeaders = 10000;
      }
   }
   if(traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "m_readBlocksize: " << m_readBlocksize << "\n";
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "m_nReadCacheHeaders: " << m_nReadCacheHeaders << "\n";
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "ossim::S3StreamDefaults::loadDefaults() DEBUG: leaving.....\n";
   }
}
<|endoftext|>


<commit_before>// @(#)root/win32gdk:$Name:  $:$Id: TGWin32VirtualGLProxy.cxx,v 1.6 2004/09/13 09:56:33 brun Exp $
// Author: Valeriy Onuchin   05/08/04

/*************************************************************************
 * Copyright (C) 1995-2004,Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TGWin32ProxyDefs.h"
#include "TGWin32VirtualGLProxy.h"
#include "TGWin32.h"
#include "TROOT.h"

static TVirtualGL *gKernelGL = 0;

//____________________________________________________________________________
TGWin32VirtualGLProxy::TGWin32VirtualGLProxy()
{
   //

   fMaxResponseTime = 1000;
}

//____________________________________________________________________________
TVirtualGL *TGWin32VirtualGLProxy::RealObject()
{
   //

   if (!gKernelGL) {
      gKernelGL = (TVirtualGL *)gROOT->GetListOfSpecials()->FindObject("gVirtualGL");
   }

   return gKernelGL;
}

RETURN_PROXY_OBJECT(VirtualGL)
RETURN_METHOD_ARG1(VirtualGL,Window_t,CreateGLWindow,Window_t,wind)
RETURN_METHOD_ARG1(VirtualGL,ULong_t,CreateContext,Window_t,wind)
VOID_METHOD_ARG1(VirtualGL,DeleteContext,ULong_t,ctx,1)
VOID_METHOD_ARG2(VirtualGL,MakeCurrent,Window_t,wind,ULong_t,ctx,1)
VOID_METHOD_ARG1(VirtualGL,SwapBuffers,Window_t,wind,1)
VOID_METHOD_ARG1(VirtualGL,NewGLModelView,Int_t,ilist,1)
VOID_METHOD_ARG2(VirtualGL,AddRotation,Double_t*,rotmatrix,Double_t*,extraangles,1)
VOID_METHOD_ARG1(VirtualGL,ClearColor,Int_t,colors,1)
VOID_METHOD_ARG4(VirtualGL,ClearGLColor,Float_t,red,Float_t,green,Float_t,blue,Float_t,alpha,1)
VOID_METHOD_ARG1(VirtualGL,ClearGL,UInt_t,bufbits,1)
RETURN_METHOD_ARG1(VirtualGL,Int_t,CreateGLLists,Int_t,range)
VOID_METHOD_ARG2(VirtualGL,DeleteGLLists,Int_t,ilist,Int_t,range,1)
VOID_METHOD_ARG0(VirtualGL,EndGLList,1)
VOID_METHOD_ARG1(VirtualGL,BeginGLCmd,EG3D2GLmode,mode,1)
VOID_METHOD_ARG1(VirtualGL,DisableGL,EG3D2GLmode,mode,1)
VOID_METHOD_ARG1(VirtualGL,EnableGL,EG3D2GLmode,mode,1)
VOID_METHOD_ARG2(VirtualGL,GetGL,EG3D2GLmode,modeu,UChar_t*,params,1)
VOID_METHOD_ARG2(VirtualGL,GetGL,EG3D2GLmode,moded,Double_t*,params,1)
VOID_METHOD_ARG2(VirtualGL,GetGL,EG3D2GLmode,modef,Float_t*,params,1)
VOID_METHOD_ARG2(VirtualGL,GetGL,EG3D2GLmode,modei,Int_t*,params,1)
RETURN_METHOD_ARG0(VirtualGL,Int_t,GetGLError)
VOID_METHOD_ARG0(VirtualGL,EndGLCmd,1)
VOID_METHOD_ARG0(VirtualGL,FlushGL,1)
VOID_METHOD_ARG1(VirtualGL,FrontGLFace,EG3D2GLmode,faceflag,1)
VOID_METHOD_ARG1(VirtualGL,MultGLMatrix,Double_t*,mat,1)
VOID_METHOD_ARG2(VirtualGL,NewGLList,UInt_t,ilist,EG3D2GLmode,mode,1)
VOID_METHOD_ARG2(VirtualGL,NewModelView,Double_t*,angles,Double_t*,delta,1)
VOID_METHOD_ARG3(VirtualGL,NewProjectionView,Double_t*,viewboxmin,Double_t*,viewboxmax,Bool_t,perspective,1)
VOID_METHOD_ARG3(VirtualGL,PaintCone,Float_t*,vertex,Int_t,ndiv,Int_t,nstacks,1)
VOID_METHOD_ARG3(VirtualGL,PaintPolyLine,Int_t,n,Float_t*,p,Option_t*,option,1)
VOID_METHOD_ARG3(VirtualGL,PaintPolyLine,Int_t,nd,Double_t*,pd,Option_t*,option,1)
VOID_METHOD_ARG2(VirtualGL,PaintGLPointsObject,const TPoints3DABC*,points,Option_t*,option,1)
VOID_METHOD_ARG1(VirtualGL,PaintBrik,Float_t*,vertex,1)
VOID_METHOD_ARG3(VirtualGL,PaintXtru,Float_t*,vertex,Int_t,nxy,Int_t,nz,1)
VOID_METHOD_ARG2(VirtualGL,PolygonGLMode,EG3D2GLmode,face,EG3D2GLmode,mode,1)
VOID_METHOD_ARG0(VirtualGL,PopGLMatrix,1)
VOID_METHOD_ARG0(VirtualGL,PushGLMatrix,1)
VOID_METHOD_ARG4(VirtualGL,RotateGL,Double_t,angle,Double_t,x,Double_t,y,Double_t,z,1)
VOID_METHOD_ARG3(VirtualGL,RotateGL,Double_t,Theta,Double_t,Phi,Double_t,Psi,1)
VOID_METHOD_ARG1(VirtualGL,RunGLList,Int_t,list,1)
VOID_METHOD_ARG3(VirtualGL,TranslateGL,Double_t,x,Double_t,y,Double_t,z,1)
VOID_METHOD_ARG1(VirtualGL,SetGLColor,Float_t*,rgb,1)
VOID_METHOD_ARG1(VirtualGL,SetGLColorIndex,Int_t,color,1)
VOID_METHOD_ARG1(VirtualGL,SetGLLineWidth,Float_t,width,1)
VOID_METHOD_ARG1(VirtualGL,SetGLPointSize,Float_t,size,1)
VOID_METHOD_ARG1(VirtualGL,SetStack,Double_t*,matrix,1)
VOID_METHOD_ARG1(VirtualGL,SetRootLight,Bool_t,flag,1)
VOID_METHOD_ARG1(VirtualGL,ShadeGLModel,EG3D2GLmode,mode,1)
VOID_METHOD_ARG2(VirtualGL,SetLineAttr,Color_t,color,Int_t,width,1)
VOID_METHOD_ARG3(VirtualGL,UpdateMatrix,Double_t*,translate,Double_t *,rotate,Bool_t,reflection,1)
VOID_METHOD_ARG1(VirtualGL,ClearGLDepth,Float_t,val,1)
VOID_METHOD_ARG1(VirtualGL,MatrixModeGL,EG3D2GLmode,mode,1)
VOID_METHOD_ARG0(VirtualGL,NewMVGL,1)
VOID_METHOD_ARG0(VirtualGL,NewPRGL,1)
VOID_METHOD_ARG6(VirtualGL,FrustumGL,Double_t,xmin,Double_t,xmax,Double_t,ymin,Double_t,ymax,Double_t,znear,Double_t,zfar,1)
VOID_METHOD_ARG3(VirtualGL,GLLight,EG3D2GLmode,name,EG3D2GLmode, prop, const Float_t*,lig_prop,1)
VOID_METHOD_ARG2(VirtualGL,LightModel,EG3D2GLmode,name,const Float_t*,lig_prop,1)
VOID_METHOD_ARG2(VirtualGL,LightModel,EG3D2GLmode,names,Int_t,lig_prop,1)
VOID_METHOD_ARG1(VirtualGL,CullFaceGL,EG3D2GLmode,mode,1)
VOID_METHOD_ARG4(VirtualGL,ViewportGL,Int_t,x,Int_t,y,Int_t,w,Int_t,h,1)
VOID_METHOD_ARG2(VirtualGL,MaterialGL,EG3D2GLmode,face,const Float_t*,mat_prop,1)
VOID_METHOD_ARG2(VirtualGL,MaterialGL,EG3D2GLmode,faces,Float_t,mat_prop,1)
VOID_METHOD_ARG1(VirtualGL,BeginGL, EG3D2GLmode, mode, 1)
VOID_METHOD_ARG0(VirtualGL,EndGL,1)
VOID_METHOD_ARG1(VirtualGL,SetGLVertex,const Double_t*,vertexd,1)
VOID_METHOD_ARG1(VirtualGL,SetGLVertex,Float_t*,vertexf,1)
VOID_METHOD_ARG1(VirtualGL,SetGLNormal,const Double_t*,normal,1)
VOID_METHOD_ARG1(VirtualGL,SetTrueColorMode,Bool_t,flag,1);
VOID_METHOD_ARG3(VirtualGL,PaintGLPoints,Int_t,n,Float_t*,p,Option_t*,option,1)
RETURN_METHOD_ARG0(VirtualGL,Bool_t,GetTrueColorMode)
RETURN_METHOD_ARG0(VirtualGL,Bool_t,GetRootLight)
VOID_METHOD_ARG3(VirtualGL, PaintPolyMarker, const Double_t *, v, Style_t, s, UInt_t, sz, 1)
VOID_METHOD_ARG6(VirtualGL, DrawSelectionBox, Double_t, xmin, Double_t, xmax, Double_t, ymin, Double_t, ymax, Double_t, zmin, Double_t, zmax, 1)
RETURN_METHOD_ARG0(VirtualGL, Int_t, ExitSelectionMode)
VOID_METHOD_ARG4(VirtualGL, EnterSelectionMode, UInt_t *, buff, Int_t, size, Event_t *, ev, Int_t *, viewport, 1)
VOID_METHOD_ARG1(VirtualGL, GLLoadName, UInt_t, name, 1)
VOID_METHOD_ARG5(VirtualGL, DrawFaceSet, const Double_t *, pnts, const Int_t *, pols, const Double_t *, normals, const Float_t *, mat, UInt_t, size, 1)
VOID_METHOD_ARG1(VirtualGL, TraverseGraph, TGLRender *, render, 1)
RETURN_METHOD_ARG4(VirtualGL, TGLSceneObject *, SelectObject, TGLRender *, render, Int_t, x, Int_t, y, Int_t, camera)
VOID_METHOD_ARG4(VirtualGL, MoveSelected, TGLRender *, render, Double_t, x, Double_t, y, Double_t, z, 1)
VOID_METHOD_ARG1(VirtualGL, EndMovement, TGLRender *, render, 1)
VOID_METHOD_ARG1(VirtualGL, Invalidate, TGLRender *, render, 1)
VOID_METHOD_ARG1(VirtualGL, DrawSphere, const Float_t *, color, 1)
<commit_msg>Increase fMaxResponseTime from 1000 to 5000 milliseconds in the constructor. This fixes a problem with thread clashes under Windows when picking very large graphics structures.<commit_after>// @(#)root/win32gdk:$Name:  $:$Id: TGWin32VirtualGLProxy.cxx,v 1.7 2004/09/29 06:55:13 brun Exp $
// Author: Valeriy Onuchin   05/08/04

/*************************************************************************
 * Copyright (C) 1995-2004,Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TGWin32ProxyDefs.h"
#include "TGWin32VirtualGLProxy.h"
#include "TGWin32.h"
#include "TROOT.h"

static TVirtualGL *gKernelGL = 0;

//____________________________________________________________________________
TGWin32VirtualGLProxy::TGWin32VirtualGLProxy()
{
   //

   fMaxResponseTime = 5000;
}

//____________________________________________________________________________
TVirtualGL *TGWin32VirtualGLProxy::RealObject()
{
   //

   if (!gKernelGL) {
      gKernelGL = (TVirtualGL *)gROOT->GetListOfSpecials()->FindObject("gVirtualGL");
   }

   return gKernelGL;
}

RETURN_PROXY_OBJECT(VirtualGL)
RETURN_METHOD_ARG1(VirtualGL,Window_t,CreateGLWindow,Window_t,wind)
RETURN_METHOD_ARG1(VirtualGL,ULong_t,CreateContext,Window_t,wind)
VOID_METHOD_ARG1(VirtualGL,DeleteContext,ULong_t,ctx,1)
VOID_METHOD_ARG2(VirtualGL,MakeCurrent,Window_t,wind,ULong_t,ctx,1)
VOID_METHOD_ARG1(VirtualGL,SwapBuffers,Window_t,wind,1)
VOID_METHOD_ARG1(VirtualGL,NewGLModelView,Int_t,ilist,1)
VOID_METHOD_ARG2(VirtualGL,AddRotation,Double_t*,rotmatrix,Double_t*,extraangles,1)
VOID_METHOD_ARG1(VirtualGL,ClearColor,Int_t,colors,1)
VOID_METHOD_ARG4(VirtualGL,ClearGLColor,Float_t,red,Float_t,green,Float_t,blue,Float_t,alpha,1)
VOID_METHOD_ARG1(VirtualGL,ClearGL,UInt_t,bufbits,1)
RETURN_METHOD_ARG1(VirtualGL,Int_t,CreateGLLists,Int_t,range)
VOID_METHOD_ARG2(VirtualGL,DeleteGLLists,Int_t,ilist,Int_t,range,1)
VOID_METHOD_ARG0(VirtualGL,EndGLList,1)
VOID_METHOD_ARG1(VirtualGL,BeginGLCmd,EG3D2GLmode,mode,1)
VOID_METHOD_ARG1(VirtualGL,DisableGL,EG3D2GLmode,mode,1)
VOID_METHOD_ARG1(VirtualGL,EnableGL,EG3D2GLmode,mode,1)
VOID_METHOD_ARG2(VirtualGL,GetGL,EG3D2GLmode,modeu,UChar_t*,params,1)
VOID_METHOD_ARG2(VirtualGL,GetGL,EG3D2GLmode,moded,Double_t*,params,1)
VOID_METHOD_ARG2(VirtualGL,GetGL,EG3D2GLmode,modef,Float_t*,params,1)
VOID_METHOD_ARG2(VirtualGL,GetGL,EG3D2GLmode,modei,Int_t*,params,1)
RETURN_METHOD_ARG0(VirtualGL,Int_t,GetGLError)
VOID_METHOD_ARG0(VirtualGL,EndGLCmd,1)
VOID_METHOD_ARG0(VirtualGL,FlushGL,1)
VOID_METHOD_ARG1(VirtualGL,FrontGLFace,EG3D2GLmode,faceflag,1)
VOID_METHOD_ARG1(VirtualGL,MultGLMatrix,Double_t*,mat,1)
VOID_METHOD_ARG2(VirtualGL,NewGLList,UInt_t,ilist,EG3D2GLmode,mode,1)
VOID_METHOD_ARG2(VirtualGL,NewModelView,Double_t*,angles,Double_t*,delta,1)
VOID_METHOD_ARG3(VirtualGL,NewProjectionView,Double_t*,viewboxmin,Double_t*,viewboxmax,Bool_t,perspective,1)
VOID_METHOD_ARG3(VirtualGL,PaintCone,Float_t*,vertex,Int_t,ndiv,Int_t,nstacks,1)
VOID_METHOD_ARG3(VirtualGL,PaintPolyLine,Int_t,n,Float_t*,p,Option_t*,option,1)
VOID_METHOD_ARG3(VirtualGL,PaintPolyLine,Int_t,nd,Double_t*,pd,Option_t*,option,1)
VOID_METHOD_ARG2(VirtualGL,PaintGLPointsObject,const TPoints3DABC*,points,Option_t*,option,1)
VOID_METHOD_ARG1(VirtualGL,PaintBrik,Float_t*,vertex,1)
VOID_METHOD_ARG3(VirtualGL,PaintXtru,Float_t*,vertex,Int_t,nxy,Int_t,nz,1)
VOID_METHOD_ARG2(VirtualGL,PolygonGLMode,EG3D2GLmode,face,EG3D2GLmode,mode,1)
VOID_METHOD_ARG0(VirtualGL,PopGLMatrix,1)
VOID_METHOD_ARG0(VirtualGL,PushGLMatrix,1)
VOID_METHOD_ARG4(VirtualGL,RotateGL,Double_t,angle,Double_t,x,Double_t,y,Double_t,z,1)
VOID_METHOD_ARG3(VirtualGL,RotateGL,Double_t,Theta,Double_t,Phi,Double_t,Psi,1)
VOID_METHOD_ARG1(VirtualGL,RunGLList,Int_t,list,1)
VOID_METHOD_ARG3(VirtualGL,TranslateGL,Double_t,x,Double_t,y,Double_t,z,1)
VOID_METHOD_ARG1(VirtualGL,SetGLColor,Float_t*,rgb,1)
VOID_METHOD_ARG1(VirtualGL,SetGLColorIndex,Int_t,color,1)
VOID_METHOD_ARG1(VirtualGL,SetGLLineWidth,Float_t,width,1)
VOID_METHOD_ARG1(VirtualGL,SetGLPointSize,Float_t,size,1)
VOID_METHOD_ARG1(VirtualGL,SetStack,Double_t*,matrix,1)
VOID_METHOD_ARG1(VirtualGL,SetRootLight,Bool_t,flag,1)
VOID_METHOD_ARG1(VirtualGL,ShadeGLModel,EG3D2GLmode,mode,1)
VOID_METHOD_ARG2(VirtualGL,SetLineAttr,Color_t,color,Int_t,width,1)
VOID_METHOD_ARG3(VirtualGL,UpdateMatrix,Double_t*,translate,Double_t *,rotate,Bool_t,reflection,1)
VOID_METHOD_ARG1(VirtualGL,ClearGLDepth,Float_t,val,1)
VOID_METHOD_ARG1(VirtualGL,MatrixModeGL,EG3D2GLmode,mode,1)
VOID_METHOD_ARG0(VirtualGL,NewMVGL,1)
VOID_METHOD_ARG0(VirtualGL,NewPRGL,1)
VOID_METHOD_ARG6(VirtualGL,FrustumGL,Double_t,xmin,Double_t,xmax,Double_t,ymin,Double_t,ymax,Double_t,znear,Double_t,zfar,1)
VOID_METHOD_ARG3(VirtualGL,GLLight,EG3D2GLmode,name,EG3D2GLmode, prop, const Float_t*,lig_prop,1)
VOID_METHOD_ARG2(VirtualGL,LightModel,EG3D2GLmode,name,const Float_t*,lig_prop,1)
VOID_METHOD_ARG2(VirtualGL,LightModel,EG3D2GLmode,names,Int_t,lig_prop,1)
VOID_METHOD_ARG1(VirtualGL,CullFaceGL,EG3D2GLmode,mode,1)
VOID_METHOD_ARG4(VirtualGL,ViewportGL,Int_t,x,Int_t,y,Int_t,w,Int_t,h,1)
VOID_METHOD_ARG2(VirtualGL,MaterialGL,EG3D2GLmode,face,const Float_t*,mat_prop,1)
VOID_METHOD_ARG2(VirtualGL,MaterialGL,EG3D2GLmode,faces,Float_t,mat_prop,1)
VOID_METHOD_ARG1(VirtualGL,BeginGL, EG3D2GLmode, mode, 1)
VOID_METHOD_ARG0(VirtualGL,EndGL,1)
VOID_METHOD_ARG1(VirtualGL,SetGLVertex,const Double_t*,vertexd,1)
VOID_METHOD_ARG1(VirtualGL,SetGLVertex,Float_t*,vertexf,1)
VOID_METHOD_ARG1(VirtualGL,SetGLNormal,const Double_t*,normal,1)
VOID_METHOD_ARG1(VirtualGL,SetTrueColorMode,Bool_t,flag,1);
VOID_METHOD_ARG3(VirtualGL,PaintGLPoints,Int_t,n,Float_t*,p,Option_t*,option,1)
RETURN_METHOD_ARG0(VirtualGL,Bool_t,GetTrueColorMode)
RETURN_METHOD_ARG0(VirtualGL,Bool_t,GetRootLight)
VOID_METHOD_ARG3(VirtualGL, PaintPolyMarker, const Double_t *, v, Style_t, s, UInt_t, sz, 1)
VOID_METHOD_ARG6(VirtualGL, DrawSelectionBox, Double_t, xmin, Double_t, xmax, Double_t, ymin, Double_t, ymax, Double_t, zmin, Double_t, zmax, 1)
RETURN_METHOD_ARG0(VirtualGL, Int_t, ExitSelectionMode)
VOID_METHOD_ARG4(VirtualGL, EnterSelectionMode, UInt_t *, buff, Int_t, size, Event_t *, ev, Int_t *, viewport, 1)
VOID_METHOD_ARG1(VirtualGL, GLLoadName, UInt_t, name, 1)
VOID_METHOD_ARG5(VirtualGL, DrawFaceSet, const Double_t *, pnts, const Int_t *, pols, const Double_t *, normals, const Float_t *, mat, UInt_t, size, 1)
VOID_METHOD_ARG1(VirtualGL, TraverseGraph, TGLRender *, render, 1)
RETURN_METHOD_ARG4(VirtualGL, TGLSceneObject *, SelectObject, TGLRender *, render, Int_t, x, Int_t, y, Int_t, camera)
VOID_METHOD_ARG4(VirtualGL, MoveSelected, TGLRender *, render, Double_t, x, Double_t, y, Double_t, z, 1)
VOID_METHOD_ARG1(VirtualGL, EndMovement, TGLRender *, render, 1)
VOID_METHOD_ARG1(VirtualGL, Invalidate, TGLRender *, render, 1)
VOID_METHOD_ARG1(VirtualGL, DrawSphere, const Float_t *, color, 1)
<|endoftext|>


<commit_before>#ifndef WITHOUT_OBSERVATION

#include "PresentWeatherObservationLayer.h"
#include "Config.h"
#include "LonLatToXYTransformation.h"
#include "State.h"
#include "ValueTools.h"
#include <timeseries/ParameterTools.h>

namespace SmartMet
{
namespace Plugin
{
namespace Dali
{
namespace
{
bool priority_sort(const StationSymbolPriority& rh1, const StationSymbolPriority& rh2)
{
  return (rh1.priority > rh2.priority);
}

float convert_possible_wawa_2_ww(float theValue)
{
  static const float wwCodeArray[100] = {
      0,  1,  2,  3,  4,  5,  0,  0,  0,  0,  10, 0,  13, 0,  0,  0,  0,  0,  18, 0,
      28, 21, 20, 21, 22, 24, 29, 0,  0,  0,  42, 41, 43, 45, 47, 48, 0,  0,  0,  0,
      61, 63, 65, 61, 65, 71, 75, 66, 67, 0,  50, 51, 53, 55, 56, 57, 57, 58, 59, 0,
      60, 61, 63, 65, 66, 67, 67, 68, 69, 0,  70, 71, 73, 75, 79, 79, 79, 77, 78, 0,
      80, 80, 81, 81, 82, 85, 86, 86, 0,  89, 92, 17, 93, 96, 17, 97, 99, 0,  0,  8};

  if (theValue >= 100 && theValue <= 199)
    return wwCodeArray[static_cast<int>(theValue - 100)];
  return theValue;
}

int get_symbol(float wawa)
{
  float value = convert_possible_wawa_2_ww(wawa);
  if (value != kFloatMissing && value > 3)
  {
    if (value == 99)
      return 48;  // synop fontin viimeinen arvo 255 osuu synop arvolle 98, onneksi myös 99 löytyy
                  // fontista, mutta sen sijainti on vain 48
    else
      return (157 + value);
  }
  return 106;  // Missing symbol 'Z'
}

int get_symbol_priority(int symbol)
{
  switch (symbol)
  {
    case 106:
      return 0;
      break;
    case 170:
    case 171:
    case 172:
    case 173:
      return 1;
      break;
    case 162:
    case 163:
    case 164:
    case 165:
    case 167:
    case 168:
    case 169:
    case 174:
    case 177:
    case 178:
    case 179:
    case 180:
    case 181:
    case 182:
    case 183:
    case 184:
    case 185:
    case 186:
    case 198:
    case 207:
    case 208:
    case 213:
    case 215:
    case 217:
    case 218:
    case 227:
    case 235:
    case 242:
    case 244:
    case 246:
    case 248:
    case 249:
    case 250:
    case 251:
      return 5;
      break;
    case 187:
    case 188:
    case 189:
    case 193:
    case 195:
    case 197:
    case 199:
    case 200:
    case 209:
    case 210:
    case 219:
    case 220:
    case 225:
    case 228:
    case 229:
    case 233:
    case 234:
    case 236:
    case 237:
    case 240:
      return 7;
      break;
    case 161:
    case 175:
    case 211:
    case 216:
    case 221:
    case 223:
    case 230:
    case 231:
    case 238:
    case 252:
    case 253:
      return 8;
      break;
    case 201:
    case 202:
    case 203:
    case 204:
    case 205:
    case 206:
    case 212:
    case 239:
    case 241:
    case 243:
    case 245:
    case 247:
      return 9;
      break;
    case 166:
    case 176:
    case 190:
    case 191:
    case 192:
    case 194:
    case 196:
    case 214:
    case 222:
    case 224:
    case 226:
    case 232:
    case 254:
    case 255:
    case 48:
      return 10;
      break;
  }

  return 0;
}

}  // namespace

void PresentWeatherObservationLayer::getParameters(
    const boost::posix_time::ptime& requested_timestep,
    std::vector<Spine::Parameter>& parameters,
    boost::posix_time::ptime& starttime,
    boost::posix_time::ptime& endtime) const
{
  try
  {
    endtime = requested_timestep;
    starttime = requested_timestep;

    parameters.push_back(TS::makeParameter("fmisid"));
    parameters.push_back(TS::makeParameter("longitude"));
    parameters.push_back(TS::makeParameter("latitude"));
    parameters.push_back(TS::makeParameter("ww_aws"));
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Gettings parameters for finnish road observations failed!");
  }
}

StationSymbolPriorities PresentWeatherObservationLayer::processResultSet(
    const State& theState,
    const ResultSet& theResultSet,
    const boost::posix_time::ptime& requested_timestep) const
{
  try
  {
    auto zone = theState.getGeoEngine().getTimeZones().time_zone_from_string("UTC");
    auto requested_local_time = boost::local_time::local_date_time(requested_timestep, zone);

    // Transformation object
    auto transformation = LonLatToXYTransformation(projection);

    StationSymbolPriorities ssps;
    TS::Value none = TS::None();
    for (auto& result_set_item : theResultSet)
    {
      StationSymbolPriority ssp;
      ssp.fmisid = result_set_item.first;
      // FMISID: data independent
      const auto& longitude_result_set_vector = result_set_item.second.at(1);
      if (longitude_result_set_vector.size() == 0)
        continue;
      auto lon = get_double(longitude_result_set_vector.at(0).value);
      // Latitude: data independent
      const auto& latitude_result_set_vector = result_set_item.second.at(2);
      auto lat = get_double(latitude_result_set_vector.at(0).value);

      // Transform to screen coordinates
      if (transformation.transform(lon, lat))
      {
        ssp.longitude = lon;
        ssp.latitude = lat;
      }
      else
      {
        throw Fmi::Exception::Trace(
            BCP, "Transforming longitude, latitude to screen coordinates failed!");
      }

      const auto& wawa_result_set_vector = result_set_item.second.at(3);
      auto wawa_val = get_double(wawa_result_set_vector.at(0).value);

      // Symbol
      ssp.symbol = get_symbol(wawa_val);
      // Priority
      ssp.priority = get_symbol_priority(ssp.symbol);

      ssps.push_back(ssp);
    }

    // Sort according to priority
    std::sort(ssps.begin(), ssps.end(), priority_sort);

    return ssps;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Processing result set of wawa failed!");
  }
}

}  // namespace Dali
}  // namespace Plugin
}  // namespace SmartMet

#endif  // WITHOUT_OBSERVATION
<commit_msg>Added 'clang-format off/on' block to wawa code table for clarity<commit_after>#ifndef WITHOUT_OBSERVATION

#include "PresentWeatherObservationLayer.h"
#include "Config.h"
#include "LonLatToXYTransformation.h"
#include "State.h"
#include "ValueTools.h"
#include <timeseries/ParameterTools.h>

namespace SmartMet
{
namespace Plugin
{
namespace Dali
{
namespace
{
bool priority_sort(const StationSymbolPriority& rh1, const StationSymbolPriority& rh2)
{
  return (rh1.priority > rh2.priority);
}

float convert_possible_wawa_2_ww(float theValue)
{
  // clang-format off
  static const float wwCodeArray[100] = {
      0,  1,  2,  3,  4,  5,  0,  0,  0,  0,
      10, 0,  13, 0,  0,  0,  0,  0,  18, 0,
      28, 21, 20, 21, 22, 24, 29, 0,  0,  0,
      42, 41, 43, 45, 47, 48, 0,  0,  0,  0,
      61, 63, 65, 61, 65, 71, 75, 66, 67, 0,
      50, 51, 53, 55, 56, 57, 57, 58, 59, 0,
      60, 61, 63, 65, 66, 67, 67, 68, 69, 0,
      70, 71, 73, 75, 79, 79, 79, 77, 78, 0,
      80, 80, 81, 81, 82, 85, 86, 86, 0, 89,
      92, 17, 93, 96, 17, 97, 99, 0,  0,  8};
  // clang-format on

  if (theValue >= 100 && theValue <= 199)
    return wwCodeArray[static_cast<int>(theValue - 100)];
  return theValue;
}

int get_symbol(float wawa)
{
  float value = convert_possible_wawa_2_ww(wawa);
  if (value != kFloatMissing && value > 3)
  {
    // the last value 255 is synop value 98, luckily also 99 is available
    // but at location 48
    if (value == 99)
      return 48;
    else
      return (157 + value);
  }
  return 106;  // Missing symbol 'Z'
}

int get_symbol_priority(int symbol)
{
  switch (symbol)
  {
    case 106:
      return 0;
      break;
    case 170:
    case 171:
    case 172:
    case 173:
      return 1;
      break;
    case 162:
    case 163:
    case 164:
    case 165:
    case 167:
    case 168:
    case 169:
    case 174:
    case 177:
    case 178:
    case 179:
    case 180:
    case 181:
    case 182:
    case 183:
    case 184:
    case 185:
    case 186:
    case 198:
    case 207:
    case 208:
    case 213:
    case 215:
    case 217:
    case 218:
    case 227:
    case 235:
    case 242:
    case 244:
    case 246:
    case 248:
    case 249:
    case 250:
    case 251:
      return 5;
      break;
    case 187:
    case 188:
    case 189:
    case 193:
    case 195:
    case 197:
    case 199:
    case 200:
    case 209:
    case 210:
    case 219:
    case 220:
    case 225:
    case 228:
    case 229:
    case 233:
    case 234:
    case 236:
    case 237:
    case 240:
      return 7;
      break;
    case 161:
    case 175:
    case 211:
    case 216:
    case 221:
    case 223:
    case 230:
    case 231:
    case 238:
    case 252:
    case 253:
      return 8;
      break;
    case 201:
    case 202:
    case 203:
    case 204:
    case 205:
    case 206:
    case 212:
    case 239:
    case 241:
    case 243:
    case 245:
    case 247:
      return 9;
      break;
    case 166:
    case 176:
    case 190:
    case 191:
    case 192:
    case 194:
    case 196:
    case 214:
    case 222:
    case 224:
    case 226:
    case 232:
    case 254:
    case 255:
    case 48:
      return 10;
      break;
  }

  return 0;
}

}  // namespace

void PresentWeatherObservationLayer::getParameters(
    const boost::posix_time::ptime& requested_timestep,
    std::vector<Spine::Parameter>& parameters,
    boost::posix_time::ptime& starttime,
    boost::posix_time::ptime& endtime) const
{
  try
  {
    endtime = requested_timestep;
    starttime = requested_timestep;

    parameters.push_back(TS::makeParameter("fmisid"));
    parameters.push_back(TS::makeParameter("longitude"));
    parameters.push_back(TS::makeParameter("latitude"));
    parameters.push_back(TS::makeParameter("ww_aws"));
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Gettings parameters for finnish road observations failed!");
  }
}

StationSymbolPriorities PresentWeatherObservationLayer::processResultSet(
    const State& theState,
    const ResultSet& theResultSet,
    const boost::posix_time::ptime& requested_timestep) const
{
  try
  {
    auto zone = theState.getGeoEngine().getTimeZones().time_zone_from_string("UTC");
    auto requested_local_time = boost::local_time::local_date_time(requested_timestep, zone);

    // Transformation object
    auto transformation = LonLatToXYTransformation(projection);

    StationSymbolPriorities ssps;
    TS::Value none = TS::None();
    for (auto& result_set_item : theResultSet)
    {
      StationSymbolPriority ssp;
      ssp.fmisid = result_set_item.first;
      // FMISID: data independent
      const auto& longitude_result_set_vector = result_set_item.second.at(1);
      if (longitude_result_set_vector.size() == 0)
        continue;
      auto lon = get_double(longitude_result_set_vector.at(0).value);
      // Latitude: data independent
      const auto& latitude_result_set_vector = result_set_item.second.at(2);
      auto lat = get_double(latitude_result_set_vector.at(0).value);

      // Transform to screen coordinates
      if (transformation.transform(lon, lat))
      {
        ssp.longitude = lon;
        ssp.latitude = lat;
      }
      else
      {
        throw Fmi::Exception::Trace(
            BCP, "Transforming longitude, latitude to screen coordinates failed!");
      }

      const auto& wawa_result_set_vector = result_set_item.second.at(3);
      auto wawa_val = get_double(wawa_result_set_vector.at(0).value);

      // Symbol
      ssp.symbol = get_symbol(wawa_val);
      // Priority
      ssp.priority = get_symbol_priority(ssp.symbol);

      ssps.push_back(ssp);
    }

    // Sort according to priority
    std::sort(ssps.begin(), ssps.end(), priority_sort);

    return ssps;
  }
  catch (...)
  {
    throw Fmi::Exception::Trace(BCP, "Processing result set of wawa failed!");
  }
}

}  // namespace Dali
}  // namespace Plugin
}  // namespace SmartMet

#endif  // WITHOUT_OBSERVATION
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved.
 *
 * 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.
 */
//
// Created by sancar koyunlu on 5/23/13.

#include <boost/foreach.hpp>
#include "hazelcast/client/aws/AWSClient.h"
#include "hazelcast/client/ClientProperties.h"

#include "hazelcast/util/Util.h"
#include "hazelcast/client/exception/IllegalArgumentException.h"
#include "hazelcast/client/MemberAttributeEvent.h"
#include "hazelcast/client/spi/ClientContext.h"
#include "hazelcast/client/spi/LifecycleService.h"
#include "hazelcast/client/spi/ClusterService.h"
#include "hazelcast/client/connection/ConnectionManager.h"
#include "hazelcast/client/connection/Connection.h"
#include "hazelcast/client/serialization/pimpl/SerializationService.h"
#include "hazelcast/client/LifecycleEvent.h"
#include "hazelcast/client/spi/ServerListenerService.h"
#include "hazelcast/client/spi/PartitionService.h"
#include "hazelcast/client/ClientConfig.h"

namespace hazelcast {
    namespace client {
        namespace connection {
            ClusterListenerThread::ClusterListenerThread(spi::ClientContext &clientContext)
                    : startLatch(1), clientContext(clientContext), deletingConnection(false),
                      workerThread((util::Thread *)NULL) {
            }

            void ClusterListenerThread::staticRun(util::ThreadArgs &args) {
                ClusterListenerThread *clusterListenerThread = (ClusterListenerThread *) args.arg0;
                int memberPort = *((int *)args.arg1);
                clusterListenerThread->run(args.currentThread, memberPort);
            }

            void ClusterListenerThread::run(util::Thread *currentThread, int memberPort) {
                workerThread = currentThread;
                awsMemberPort = memberPort;

                Address previousConnectionAddr;
                Address *previousConnectionAddrPtr = NULL;
                spi::LifecycleService &lifecycleService = clientContext.getLifecycleService();
                while (lifecycleService.isRunning()) {
                    try {
                        if (conn.get() == NULL) {
                            try {
                                conn = clientContext.getClusterService().connectToOne(previousConnectionAddrPtr);
                                previousConnectionAddr = conn->getRemoteEndpoint();
                                previousConnectionAddrPtr = &previousConnectionAddr;
                            } catch (std::exception &e) {
                                if (lifecycleService.isRunning()) {
                                    util::ILogger::getLogger().severe(
                                            std::string("Error while connecting to cluster! =>") + e.what());
                                    lifecycleService.shutdown();
                                }
                                /**
                                 * Do nothing except returning here. Since client and cluster service may have been
                                 * already been destructed, any access to startLatch or any other client variable
                                 * may cause invalid memory access.
                                 */
                                return;
                            }
                        }

                        isInitialMembersLoaded = false;
                        isRegistrationIdReceived = false;
                        loadInitialMemberList();
                        clientContext.getServerListenerService().triggerFailedListeners();
                        startLatch.countDown();
                        listenMembershipEvents();
                        currentThread->interruptibleSleep(1);
                    } catch (std::exception &e) {
                        if (lifecycleService.isRunning()) {
                            util::ILogger::getLogger().warning(
                                    std::string("Error while listening cluster events! -> ") + e.what());
                        }

                        clientContext.getConnectionManager().onCloseOwnerConnection();
                        if (deletingConnection.compareAndSet(false, true)) {
                            if (conn.get()) {
                                util::IOUtil::closeResource(conn.get(), "Error while listening cluster events");
                                conn.reset();
                                lifecycleService.fireLifecycleEvent(LifecycleEvent::CLIENT_DISCONNECTED);
                            }
                            deletingConnection = false;
                        }
                        if (clientContext.getLifecycleService().isRunning()) {
                            currentThread->interruptibleSleep(1);
                        }
                    }
                }
            }

            void ClusterListenerThread::stop() {
                startLatch.countDown();
                if (deletingConnection.compareAndSet(false, true)) {
                    if (conn.get()) {
                        util::IOUtil::closeResource(conn.get(), "Cluster listener thread is stopping");
                        conn.reset();
                        clientContext.getLifecycleService().fireLifecycleEvent(LifecycleEvent::CLIENT_DISCONNECTED);
                    }
                    deletingConnection = false;
                }
                util::Thread *worker = workerThread;
                if (worker) {
                    workerThread = (util::Thread *) NULL;
                    worker->cancel();
                    worker->join();
                    delete worker;
                }
            }

            std::set<Address, addressComparator> ClusterListenerThread::getSocketAddresses() const {
                std::set<Address, addressComparator> addresses;
                if (!members.empty()) {
                    std::vector<Address> clusterAddresses = getClusterAddresses();
                    addresses.insert(clusterAddresses.begin(), clusterAddresses.end());
                }
                std::vector<Address> configAddresses = getConfigAddresses();
                addresses.insert(configAddresses.begin(), configAddresses.end());
                std::vector<Address> awsAddresses = getAwsAddresses();
                addresses.insert(awsAddresses.begin(), awsAddresses.end());

                if (addresses.empty()) {
                    addresses.insert(Address("127.0.0.1", 5701));
                }

                return addresses;
            }

            void ClusterListenerThread::loadInitialMemberList() {
                std::auto_ptr<protocol::ClientMessage> request =
                        protocol::codec::ClientAddMembershipListenerCodec::RequestParameters::encode(false);

                request->setCorrelationId(clientContext.getConnectionManager().getNextCallId());

                conn->writeBlocking(*request);

                std::auto_ptr<protocol::ClientMessage> response;

                do {
                    response = conn->readBlocking();
                    if (protocol::codec::ClientAddMembershipListenerCodec::ResponseParameters::TYPE ==
                        response->getMessageType()) {
                        protocol::codec::ClientAddMembershipListenerCodec::ResponseParameters result = protocol::codec::ClientAddMembershipListenerCodec::ResponseParameters::decode(
                                *response);
                        registrationId = result.response;
                        isRegistrationIdReceived = true;
                    } else {
                        handle(response);
                    }
                } while (!isInitialMembersLoaded || !isRegistrationIdReceived);
            }

            void ClusterListenerThread::listenMembershipEvents() {
                while (clientContext.getLifecycleService().isRunning()) {
                    std::auto_ptr<protocol::ClientMessage> clientMessage = conn->readBlocking();
                    if (!clientContext.getLifecycleService().isRunning()) {
                        break;
                    }

                    handle(clientMessage);
                }
            }

            void ClusterListenerThread::updateMembersRef() {
                std::auto_ptr<std::map<Address, Member, addressComparator> > addrMap(
                        new std::map<Address, Member, addressComparator>());
                for (std::vector<Member>::const_iterator it = members.begin(); it != members.end(); ++it) {
                    (*addrMap)[it->getAddress()] = *it;
                }
                clientContext.getClusterService().setMembers(addrMap);
            }

            std::vector<Address> ClusterListenerThread::getClusterAddresses() const {
                std::vector<Address> socketAddresses;
                for (std::vector<Member>::const_iterator it = members.begin(); it != members.end(); ++it) {
                    socketAddresses.push_back(it->getAddress());
                }
                return socketAddresses;
            }

            std::vector<Address>  ClusterListenerThread::getConfigAddresses() const {
                std::vector<Address> socketAddresses;
                std::set<Address, addressComparator> &configAddresses = clientContext.getClientConfig().getAddresses();
                std::set<Address, addressComparator>::iterator it;

                for (it = configAddresses.begin(); it != configAddresses.end(); ++it) {
                    socketAddresses.push_back((*it));
                }

                return socketAddresses;
            }

            std::vector<Address> ClusterListenerThread::getAwsAddresses() const {
                std::vector<Address> awsAdresses;
                config::ClientAwsConfig &awsConfig = clientContext.getClientConfig().getNetworkConfig().getAwsConfig();
                if (awsConfig.isEnabled()) {
                    try {
                        aws::AWSClient awsClient(awsConfig);
                        typedef std::map<std::string, std::string> AddressMap;
                        BOOST_FOREACH(const AddressMap::value_type &addressPair , awsClient.getAddresses()) {
                            awsAdresses.push_back(Address(addressPair.first, awsMemberPort));
                        }
                    } catch (exception::IException &e) {
                        util::ILogger::getLogger().warning(std::string("Aws addresses failed to load: ") + e.what());
                    }
                }

                return awsAdresses;
            }

            void ClusterListenerThread::handleMember(const Member &member, const int32_t &eventType) {
                switch (eventType) {
                    case MembershipEvent::MEMBER_ADDED:
                        memberAdded(member);
                        break;
                    case MembershipEvent::MEMBER_REMOVED:
                        memberRemoved(member);
                        break;
                    default:
                        char buf[50];
                        util::snprintf(buf, 50, "Unknown event type :%d", eventType);
                        util::ILogger::getLogger().warning(buf);
                }
                clientContext.getPartitionService().wakeup();
            }

            void ClusterListenerThread::handleMemberList(const std::vector<Member> &initialMembers) {
                std::auto_ptr<std::map<std::string, Member> > prevMembers;
                if (members.size() > 0) {
                    prevMembers = std::auto_ptr<std::map<std::string, Member> >(new std::map<std::string, Member>);
                    for (std::vector<Member>::const_iterator member = members.begin();
                         member != members.end(); ++member) {
                        (*prevMembers)[member->getUuid()] = *member;
                    }
                    members.clear();
                }

                for (std::vector<Member>::const_iterator initialMember = initialMembers.begin();
                     initialMember != initialMembers.end(); ++initialMember) {
                    members.push_back(*initialMember);
                }

                std::vector<MembershipEvent> events = detectMembershipEvents(prevMembers);
                if (events.size() != 0) {
                    applyMemberListChanges();
                }
                fireMembershipEvents(events);

                isInitialMembersLoaded = true;
            }

            void ClusterListenerThread::handleMemberAttributeChange(const std::string &uuid, const std::string &key,
                                                                    const int32_t &operationType,
                                                                    std::auto_ptr<std::string> value) {
                // find and update the member in local list
                std::auto_ptr<std::map<Address, Member, addressComparator> > addrMap(new std::map<Address, Member, addressComparator>());
                std::vector<Member>::const_iterator foundMember = members.end();
                MemberAttributeEvent::MemberAttributeOperationType type = (MemberAttributeEvent::MemberAttributeOperationType) operationType;
                for (std::vector<Member>::iterator it = members.begin(); it != members.end(); ++it) {
                    if (it->getUuid() == uuid) {
                        switch (operationType) {
                            case MemberAttributeEvent::PUT:
                                it->setAttribute(key, *value);
                                break;
                            case MemberAttributeEvent::REMOVE:
                                it->removeAttribute(key);
                                break;
                            default:
                                char buf[50];
                                util::snprintf(buf, 50, "Not a known OperationType: %d", operationType);
                                throw exception::IllegalArgumentException("Member::updateAttribute", buf);
                        }
                        foundMember = it;
                    }
                    (*addrMap)[it->getAddress()] = *it;
                }

                if (members.end() != foundMember) {
                    clientContext.getClusterService().setMembers(addrMap);

                    // fire event
                    MemberAttributeEvent event(clientContext.getCluster(), *foundMember, type, key, *value, members);

                    clientContext.getClusterService().fireMemberAttributeEvent(event);
                }
            }

            void ClusterListenerThread::memberAdded(const Member &member) {
                members.push_back(member);

                applyMemberListChanges();

                MembershipEvent event(clientContext.getCluster(), member, MembershipEvent::MEMBER_ADDED, members);

                clientContext.getClusterService().fireMembershipEvent(event);
            }

            void ClusterListenerThread::memberRemoved(const Member &member) {
                for (std::vector<Member>::iterator it = members.begin(); it != members.end(); ++it) {
                    if (member == *it) {
                        members.erase(it);
                        break;
                    }
                }

                applyMemberListChanges();

                clientContext.getConnectionManager().removeEndpoint(member.getAddress());

                MembershipEvent event(clientContext.getCluster(), member, MembershipEvent::MEMBER_REMOVED,
                                      members);

                clientContext.getClusterService().fireMembershipEvent(event);
            }

            std::vector<MembershipEvent> ClusterListenerThread::detectMembershipEvents(
                    std::auto_ptr<std::map<std::string, Member> > prevMembers) const {
                std::vector<MembershipEvent> events;
                std::vector<Member> eventMembers(members);
                if (NULL != prevMembers.get()) {
                    for (std::vector<Member>::const_iterator member = members.begin();
                         member != members.end(); ++member) {
                        std::map<std::string, Member>::iterator former = prevMembers->find(member->getUuid());
                        if (former == prevMembers->end()) {
                            events.push_back(
                                    MembershipEvent(clientContext.getCluster(), *member, MembershipEvent::MEMBER_ADDED,
                                                    eventMembers));
                        } else {
                            prevMembers->erase(former);
                        }
                    }
                    for (std::map<std::string, Member>::const_iterator it = prevMembers->begin();
                         it != prevMembers->end(); ++it) {
                        MembershipEvent event(clientContext.getCluster(), it->second, MembershipEvent::MEMBER_REMOVED,
                                              eventMembers);
                        events.push_back(event);
                        const Address &address = it->second.getAddress();

                        if (!clientContext.getClusterService().isMemberExists(address)) {
                            clientContext.getConnectionManager().removeEndpoint(address);
                        }
                    }
                } else {
                    for (std::vector<Member>::const_iterator member = members.begin();
                         member != members.end(); ++member) {
                        events.push_back(
                                MembershipEvent(clientContext.getCluster(), *member, MembershipEvent::MEMBER_ADDED,
                                                eventMembers));
                    }
                }
                return events;
            }

            void ClusterListenerThread::applyMemberListChanges() {
                updateMembersRef();

                util::ILogger::getLogger().info(clientContext.getClusterService().membersString());
            }

            void ClusterListenerThread::fireMembershipEvents(const std::vector<MembershipEvent> &events) const {
                for (std::vector<MembershipEvent>::const_iterator it = events.begin(); it != events.end(); ++it) {
                    clientContext.getClusterService().fireMembershipEvent(*it);
                }
            }

            bool ClusterListenerThread::awaitStart() {
                startLatch.await();
                return !clientContext.getClusterService().getMemberList().empty();
            }
        }
    }
}

<commit_msg>Do not delete the cluster thread on shutdown since the thread may sometime finish after this ClusterService.shutdown and before hazelcast client destructor exit. (#315)<commit_after>/*
 * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved.
 *
 * 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.
 */
//
// Created by sancar koyunlu on 5/23/13.

#include <boost/foreach.hpp>
#include "hazelcast/client/aws/AWSClient.h"
#include "hazelcast/client/ClientProperties.h"

#include "hazelcast/util/Util.h"
#include "hazelcast/client/exception/IllegalArgumentException.h"
#include "hazelcast/client/MemberAttributeEvent.h"
#include "hazelcast/client/spi/ClientContext.h"
#include "hazelcast/client/spi/LifecycleService.h"
#include "hazelcast/client/spi/ClusterService.h"
#include "hazelcast/client/connection/ConnectionManager.h"
#include "hazelcast/client/connection/Connection.h"
#include "hazelcast/client/serialization/pimpl/SerializationService.h"
#include "hazelcast/client/LifecycleEvent.h"
#include "hazelcast/client/spi/ServerListenerService.h"
#include "hazelcast/client/spi/PartitionService.h"
#include "hazelcast/client/ClientConfig.h"

namespace hazelcast {
    namespace client {
        namespace connection {
            ClusterListenerThread::ClusterListenerThread(spi::ClientContext &clientContext)
                    : startLatch(1), clientContext(clientContext), deletingConnection(false),
                      workerThread((util::Thread *)NULL) {
            }

            void ClusterListenerThread::staticRun(util::ThreadArgs &args) {
                ClusterListenerThread *clusterListenerThread = (ClusterListenerThread *) args.arg0;
                int memberPort = *((int *)args.arg1);
                clusterListenerThread->run(args.currentThread, memberPort);
            }

            void ClusterListenerThread::run(util::Thread *currentThread, int memberPort) {
                workerThread = currentThread;
                awsMemberPort = memberPort;

                Address previousConnectionAddr;
                Address *previousConnectionAddrPtr = NULL;
                spi::LifecycleService &lifecycleService = clientContext.getLifecycleService();
                while (lifecycleService.isRunning()) {
                    try {
                        if (conn.get() == NULL) {
                            try {
                                conn = clientContext.getClusterService().connectToOne(previousConnectionAddrPtr);
                                previousConnectionAddr = conn->getRemoteEndpoint();
                                previousConnectionAddrPtr = &previousConnectionAddr;
                            } catch (std::exception &e) {
                                if (lifecycleService.isRunning()) {
                                    util::ILogger::getLogger().severe(
                                            std::string("Error while connecting to cluster! =>") + e.what());
                                    lifecycleService.shutdown();
                                }
                                /**
                                 * Do nothing except returning here. Since client and cluster service may have been
                                 * already been destructed, any access to startLatch or any other client variable
                                 * may cause invalid memory access.
                                 */
                                return;
                            }
                        }

                        isInitialMembersLoaded = false;
                        isRegistrationIdReceived = false;
                        loadInitialMemberList();
                        clientContext.getServerListenerService().triggerFailedListeners();
                        startLatch.countDown();
                        listenMembershipEvents();
                        currentThread->interruptibleSleep(1);
                    } catch (std::exception &e) {
                        if (lifecycleService.isRunning()) {
                            util::ILogger::getLogger().warning(
                                    std::string("Error while listening cluster events! -> ") + e.what());
                        }

                        clientContext.getConnectionManager().onCloseOwnerConnection();
                        if (deletingConnection.compareAndSet(false, true)) {
                            if (conn.get()) {
                                util::IOUtil::closeResource(conn.get(), "Error while listening cluster events");
                                conn.reset();
                                lifecycleService.fireLifecycleEvent(LifecycleEvent::CLIENT_DISCONNECTED);
                            }
                            deletingConnection = false;
                        }
                        if (clientContext.getLifecycleService().isRunning()) {
                            currentThread->interruptibleSleep(1);
                        }
                    }
                }
            }

            void ClusterListenerThread::stop() {
                startLatch.countDown();
                if (deletingConnection.compareAndSet(false, true)) {
                    if (conn.get()) {
                        util::IOUtil::closeResource(conn.get(), "Cluster listener thread is stopping");
                        conn.reset();
                        clientContext.getLifecycleService().fireLifecycleEvent(LifecycleEvent::CLIENT_DISCONNECTED);
                    }
                    deletingConnection = false;
                }
                util::Thread *worker = workerThread;
                if (worker) {
                    workerThread = (util::Thread *) NULL;
                    worker->cancel();
                    worker->join();
                }
            }

            std::set<Address, addressComparator> ClusterListenerThread::getSocketAddresses() const {
                std::set<Address, addressComparator> addresses;
                if (!members.empty()) {
                    std::vector<Address> clusterAddresses = getClusterAddresses();
                    addresses.insert(clusterAddresses.begin(), clusterAddresses.end());
                }
                std::vector<Address> configAddresses = getConfigAddresses();
                addresses.insert(configAddresses.begin(), configAddresses.end());
                std::vector<Address> awsAddresses = getAwsAddresses();
                addresses.insert(awsAddresses.begin(), awsAddresses.end());

                if (addresses.empty()) {
                    addresses.insert(Address("127.0.0.1", 5701));
                }

                return addresses;
            }

            void ClusterListenerThread::loadInitialMemberList() {
                std::auto_ptr<protocol::ClientMessage> request =
                        protocol::codec::ClientAddMembershipListenerCodec::RequestParameters::encode(false);

                request->setCorrelationId(clientContext.getConnectionManager().getNextCallId());

                conn->writeBlocking(*request);

                std::auto_ptr<protocol::ClientMessage> response;

                do {
                    response = conn->readBlocking();
                    if (protocol::codec::ClientAddMembershipListenerCodec::ResponseParameters::TYPE ==
                        response->getMessageType()) {
                        protocol::codec::ClientAddMembershipListenerCodec::ResponseParameters result = protocol::codec::ClientAddMembershipListenerCodec::ResponseParameters::decode(
                                *response);
                        registrationId = result.response;
                        isRegistrationIdReceived = true;
                    } else {
                        handle(response);
                    }
                } while (!isInitialMembersLoaded || !isRegistrationIdReceived);
            }

            void ClusterListenerThread::listenMembershipEvents() {
                while (clientContext.getLifecycleService().isRunning()) {
                    std::auto_ptr<protocol::ClientMessage> clientMessage = conn->readBlocking();
                    if (!clientContext.getLifecycleService().isRunning()) {
                        break;
                    }

                    handle(clientMessage);
                }
            }

            void ClusterListenerThread::updateMembersRef() {
                std::auto_ptr<std::map<Address, Member, addressComparator> > addrMap(
                        new std::map<Address, Member, addressComparator>());
                for (std::vector<Member>::const_iterator it = members.begin(); it != members.end(); ++it) {
                    (*addrMap)[it->getAddress()] = *it;
                }
                clientContext.getClusterService().setMembers(addrMap);
            }

            std::vector<Address> ClusterListenerThread::getClusterAddresses() const {
                std::vector<Address> socketAddresses;
                for (std::vector<Member>::const_iterator it = members.begin(); it != members.end(); ++it) {
                    socketAddresses.push_back(it->getAddress());
                }
                return socketAddresses;
            }

            std::vector<Address>  ClusterListenerThread::getConfigAddresses() const {
                std::vector<Address> socketAddresses;
                std::set<Address, addressComparator> &configAddresses = clientContext.getClientConfig().getAddresses();
                std::set<Address, addressComparator>::iterator it;

                for (it = configAddresses.begin(); it != configAddresses.end(); ++it) {
                    socketAddresses.push_back((*it));
                }

                return socketAddresses;
            }

            std::vector<Address> ClusterListenerThread::getAwsAddresses() const {
                std::vector<Address> awsAdresses;
                config::ClientAwsConfig &awsConfig = clientContext.getClientConfig().getNetworkConfig().getAwsConfig();
                if (awsConfig.isEnabled()) {
                    try {
                        aws::AWSClient awsClient(awsConfig);
                        typedef std::map<std::string, std::string> AddressMap;
                        BOOST_FOREACH(const AddressMap::value_type &addressPair , awsClient.getAddresses()) {
                            awsAdresses.push_back(Address(addressPair.first, awsMemberPort));
                        }
                    } catch (exception::IException &e) {
                        util::ILogger::getLogger().warning(std::string("Aws addresses failed to load: ") + e.what());
                    }
                }

                return awsAdresses;
            }

            void ClusterListenerThread::handleMember(const Member &member, const int32_t &eventType) {
                switch (eventType) {
                    case MembershipEvent::MEMBER_ADDED:
                        memberAdded(member);
                        break;
                    case MembershipEvent::MEMBER_REMOVED:
                        memberRemoved(member);
                        break;
                    default:
                        char buf[50];
                        util::snprintf(buf, 50, "Unknown event type :%d", eventType);
                        util::ILogger::getLogger().warning(buf);
                }
                clientContext.getPartitionService().wakeup();
            }

            void ClusterListenerThread::handleMemberList(const std::vector<Member> &initialMembers) {
                std::auto_ptr<std::map<std::string, Member> > prevMembers;
                if (members.size() > 0) {
                    prevMembers = std::auto_ptr<std::map<std::string, Member> >(new std::map<std::string, Member>);
                    for (std::vector<Member>::const_iterator member = members.begin();
                         member != members.end(); ++member) {
                        (*prevMembers)[member->getUuid()] = *member;
                    }
                    members.clear();
                }

                for (std::vector<Member>::const_iterator initialMember = initialMembers.begin();
                     initialMember != initialMembers.end(); ++initialMember) {
                    members.push_back(*initialMember);
                }

                std::vector<MembershipEvent> events = detectMembershipEvents(prevMembers);
                if (events.size() != 0) {
                    applyMemberListChanges();
                }
                fireMembershipEvents(events);

                isInitialMembersLoaded = true;
            }

            void ClusterListenerThread::handleMemberAttributeChange(const std::string &uuid, const std::string &key,
                                                                    const int32_t &operationType,
                                                                    std::auto_ptr<std::string> value) {
                // find and update the member in local list
                std::auto_ptr<std::map<Address, Member, addressComparator> > addrMap(new std::map<Address, Member, addressComparator>());
                std::vector<Member>::const_iterator foundMember = members.end();
                MemberAttributeEvent::MemberAttributeOperationType type = (MemberAttributeEvent::MemberAttributeOperationType) operationType;
                for (std::vector<Member>::iterator it = members.begin(); it != members.end(); ++it) {
                    if (it->getUuid() == uuid) {
                        switch (operationType) {
                            case MemberAttributeEvent::PUT:
                                it->setAttribute(key, *value);
                                break;
                            case MemberAttributeEvent::REMOVE:
                                it->removeAttribute(key);
                                break;
                            default:
                                char buf[50];
                                util::snprintf(buf, 50, "Not a known OperationType: %d", operationType);
                                throw exception::IllegalArgumentException("Member::updateAttribute", buf);
                        }
                        foundMember = it;
                    }
                    (*addrMap)[it->getAddress()] = *it;
                }

                if (members.end() != foundMember) {
                    clientContext.getClusterService().setMembers(addrMap);

                    // fire event
                    MemberAttributeEvent event(clientContext.getCluster(), *foundMember, type, key, *value, members);

                    clientContext.getClusterService().fireMemberAttributeEvent(event);
                }
            }

            void ClusterListenerThread::memberAdded(const Member &member) {
                members.push_back(member);

                applyMemberListChanges();

                MembershipEvent event(clientContext.getCluster(), member, MembershipEvent::MEMBER_ADDED, members);

                clientContext.getClusterService().fireMembershipEvent(event);
            }

            void ClusterListenerThread::memberRemoved(const Member &member) {
                for (std::vector<Member>::iterator it = members.begin(); it != members.end(); ++it) {
                    if (member == *it) {
                        members.erase(it);
                        break;
                    }
                }

                applyMemberListChanges();

                clientContext.getConnectionManager().removeEndpoint(member.getAddress());

                MembershipEvent event(clientContext.getCluster(), member, MembershipEvent::MEMBER_REMOVED,
                                      members);

                clientContext.getClusterService().fireMembershipEvent(event);
            }

            std::vector<MembershipEvent> ClusterListenerThread::detectMembershipEvents(
                    std::auto_ptr<std::map<std::string, Member> > prevMembers) const {
                std::vector<MembershipEvent> events;
                std::vector<Member> eventMembers(members);
                if (NULL != prevMembers.get()) {
                    for (std::vector<Member>::const_iterator member = members.begin();
                         member != members.end(); ++member) {
                        std::map<std::string, Member>::iterator former = prevMembers->find(member->getUuid());
                        if (former == prevMembers->end()) {
                            events.push_back(
                                    MembershipEvent(clientContext.getCluster(), *member, MembershipEvent::MEMBER_ADDED,
                                                    eventMembers));
                        } else {
                            prevMembers->erase(former);
                        }
                    }
                    for (std::map<std::string, Member>::const_iterator it = prevMembers->begin();
                         it != prevMembers->end(); ++it) {
                        MembershipEvent event(clientContext.getCluster(), it->second, MembershipEvent::MEMBER_REMOVED,
                                              eventMembers);
                        events.push_back(event);
                        const Address &address = it->second.getAddress();

                        if (!clientContext.getClusterService().isMemberExists(address)) {
                            clientContext.getConnectionManager().removeEndpoint(address);
                        }
                    }
                } else {
                    for (std::vector<Member>::const_iterator member = members.begin();
                         member != members.end(); ++member) {
                        events.push_back(
                                MembershipEvent(clientContext.getCluster(), *member, MembershipEvent::MEMBER_ADDED,
                                                eventMembers));
                    }
                }
                return events;
            }

            void ClusterListenerThread::applyMemberListChanges() {
                updateMembersRef();

                util::ILogger::getLogger().info(clientContext.getClusterService().membersString());
            }

            void ClusterListenerThread::fireMembershipEvents(const std::vector<MembershipEvent> &events) const {
                for (std::vector<MembershipEvent>::const_iterator it = events.begin(); it != events.end(); ++it) {
                    clientContext.getClusterService().fireMembershipEvent(*it);
                }
            }

            bool ClusterListenerThread::awaitStart() {
                startLatch.await();
                return !clientContext.getClusterService().getMemberList().empty();
            }
        }
    }
}

<|endoftext|>