<commit_before>/*
	This file is part of the Util library.
	Copyright (C) 2007-2012 Benjamin Eikel <benjamin@eikel.org>
	Copyright (C) 2007-2012 Claudius Jähn <claudius@uni-paderborn.de>
	Copyright (C) 2007-2012 Ralf Petring <ralf@petring.net>

	This library is subject to the terms of the Mozilla Public License, v. 2.0.
	You should have received a copy of the MPL along with this library; see the
	file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
#if defined(UTIL_HAVE_LIB_X11) and defined(UTIL_HAVE_LIB_EGL)

#include "WindowEGL.h"
#include "WindowX11Data.h"
#include "../StringUtils.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <EGL/egl.h>
#include <memory>
#include <stdexcept>

namespace Util {
namespace UI {

extern Key keySymToKey(KeySym sym);

struct WindowEGL::WindowEGLData {
		EGLDisplay display;
		EGLContext context;
		EGLSurface surface;

		WindowEGLData() :
			display(EGL_NO_DISPLAY), context(EGL_NO_CONTEXT), surface(EGL_NO_SURFACE) {
		}

		~WindowEGLData() {
			if (display != EGL_NO_DISPLAY) {
				eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
				if (surface != EGL_NO_SURFACE) {
					eglDestroySurface(display, surface);
				}
				if (context != EGL_NO_CONTEXT) {
					eglDestroyContext(display, context);
				}
				eglTerminate(display);
			}
		}
};

WindowEGL::WindowEGL(const Window::Properties & properties) :
		WindowX11(properties), eglData(new WindowEGLData) {

	eglData->display = eglGetDisplay(x11Data->display);
	if (eglData->display == EGL_NO_DISPLAY) {
		throw std::runtime_error("Failed to open display.");
	}

	EGLint versionMajor;
	EGLint versionMinor;
	if (eglInitialize(eglData->display, &versionMajor, &versionMinor) == EGL_FALSE) {
		throw std::runtime_error("Failed to initialize display.");
	}

	// EGL version 1.3 is needed for EGL_CONTEXT_CLIENT_VERSION
	if ((versionMajor < 1) || ((versionMajor == 1) && (versionMinor < 3))) {
		throw std::runtime_error("EGL version less than 1.3 detected.");
	}

	// Define attributes of desired framebuffer configurations
	EGLint fbAttribs[] = { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, EGL_BUFFER_SIZE, 24, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 8,
							EGL_NATIVE_RENDERABLE, EGL_TRUE, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE };
	// Request a single framebuffer configuration
	EGLConfig fbConfig;
	EGLint fbCount;
	if (eglChooseConfig(eglData->display, fbAttribs, &fbConfig, 1, &fbCount) == EGL_FALSE) {
		throw std::runtime_error("Failed to retrieve a matching framebuffer configuration.");
	}

	if (fbCount == 0) {
		// FIXME: Workaround: Use eglGetConfigs instead of eglChooseConfig, because sometimes eglChooseConfig does not find matching configurations.
		EGLConfig fbConfigs[200];
		eglGetConfigs(eglData->display, fbConfigs, 200, &fbCount);
		for (EGLint i = 0; i < fbCount; ++i) {
			EGLint value;
			// We want to render into a window
			eglGetConfigAttrib(eglData->display, fbConfigs[i], EGL_SURFACE_TYPE, &value);
			if (!(value & EGL_WINDOW_BIT)) {
				continue;
			}
			// We want a configuration with a depth buffer
			eglGetConfigAttrib(eglData->display, fbConfigs[i], EGL_DEPTH_SIZE, &value);
			if (value == 0) {
				continue;
			}
			fbConfig = fbConfigs[i];
		}
	}

	if (fbCount == 0) {
		throw std::runtime_error("No matching framebuffer configurations found.");
	}

	EGLint visualID;
	eglGetConfigAttrib(eglData->display, fbConfig, EGL_NATIVE_VISUAL_ID, &visualID);

	const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
	eglData->context = eglCreateContext(eglData->display, fbConfig, EGL_NO_CONTEXT, contextAttribs);
	if (eglData->context == EGL_NO_CONTEXT) {
		throw std::runtime_error("Failed to create OpenGL ES 2.x context. " +
								 StringUtils::toString(eglGetError()));
	}

	// Create X11 window
	XVisualInfo templateInfo;
	templateInfo.visualid = visualID;
	int visualCount;
	XVisualInfo * visualsInfo = XGetVisualInfo(x11Data->display, VisualIDMask, &templateInfo, &visualCount);
	if (visualsInfo == nullptr) {
		throw std::runtime_error("Failed to find a matching visual.");
	} else if (visualCount != 1) {
		XFree(visualsInfo);
		throw std::runtime_error("More than one visual found.");
	}

	x11Data->colorMap = XCreateColormap(x11Data->display, RootWindow(x11Data->display, visualsInfo[0].screen), visualsInfo[0].visual, AllocNone);
	x11Data->freeColorMap = true;

	XSetWindowAttributes windowAttribs;
	windowAttribs.colormap = x11Data->colorMap;
	windowAttribs.background_pixmap = None;
	windowAttribs.border_pixel = 0;
	windowAttribs.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask;

	x11Data->window = XCreateWindow(x11Data->display, RootWindow(x11Data->display, visualsInfo[0].screen),
								 0, 0, properties.clientAreaWidth, properties.clientAreaHeight,
								 0, visualsInfo[0].depth,
								 InputOutput, visualsInfo[0].visual, CWBorderPixel | CWColormap | CWEventMask, &windowAttribs);

	XFree(visualsInfo);

	if (!x11Data->window) {
		throw std::runtime_error("Failed to create window.");
	} else {
		x11Data->freeWindow = true;
	}

	if (properties.borderless) {
		x11Data->removeWindowBorder();
	}
	if (!properties.resizable) {
		x11Data->fixWindowSize(static_cast<int>(properties.clientAreaWidth),
							   static_cast<int>(properties.clientAreaHeight));
	}

	x11Data->inputMethod = XOpenIM(x11Data->display, nullptr, nullptr, nullptr);
	if (x11Data->inputMethod == nullptr) {
		throw std::runtime_error("Failed to create input method.");
	}

	x11Data->inputContext = XCreateIC(x11Data->inputMethod,
								   XNInputStyle, XIMPreeditNone | XIMStatusNone,
								   XNClientWindow, x11Data->window,
								   XNFocusWindow, x11Data->window,
								   nullptr);
	if (x11Data->inputContext == nullptr) {
		throw std::runtime_error("Failed to create input context.");
	}

	XStoreName(x11Data->display, x11Data->window, properties.title.c_str());

	XMapWindow(x11Data->display, x11Data->window);
	if (properties.positioned) {
		XMoveWindow(x11Data->display, x11Data->window, properties.posX, properties.posY);
	}

	eglData->surface = eglCreateWindowSurface(eglData->display, fbConfig, x11Data->window, nullptr);
	if (eglData->surface == EGL_NO_SURFACE) {
		throw std::runtime_error("Failed to create window surface.");
	}

	eglMakeCurrent(eglData->display, eglData->surface, eglData->surface, eglData->context);
}

WindowEGL::~WindowEGL() = default;

void WindowEGL::swapBuffers() {
	eglSwapBuffers(eglData->display, eglData->surface);
}

}
}

#endif /* defined(UTIL_HAVE_LIB_X11) and defined(UTIL_HAVE_LIB_EGL) */
<commit_msg>Add eglErrorToString<commit_after>/*
	This file is part of the Util library.
	Copyright (C) 2007-2012 Benjamin Eikel <benjamin@eikel.org>
	Copyright (C) 2007-2012 Claudius Jähn <claudius@uni-paderborn.de>
	Copyright (C) 2007-2012 Ralf Petring <ralf@petring.net>

	This library is subject to the terms of the Mozilla Public License, v. 2.0.
	You should have received a copy of the MPL along with this library; see the
	file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
#if defined(UTIL_HAVE_LIB_X11) and defined(UTIL_HAVE_LIB_EGL)

#include "WindowEGL.h"
#include "WindowX11Data.h"
#include "../StringUtils.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <EGL/egl.h>
#include <memory>
#include <stdexcept>

namespace Util {
namespace UI {

extern Key keySymToKey(KeySym sym);

struct WindowEGL::WindowEGLData {
		EGLDisplay display;
		EGLContext context;
		EGLSurface surface;

		WindowEGLData() :
			display(EGL_NO_DISPLAY), context(EGL_NO_CONTEXT), surface(EGL_NO_SURFACE) {
		}

		~WindowEGLData() {
			if (display != EGL_NO_DISPLAY) {
				eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
				if (surface != EGL_NO_SURFACE) {
					eglDestroySurface(display, surface);
				}
				if (context != EGL_NO_CONTEXT) {
					eglDestroyContext(display, context);
				}
				eglTerminate(display);
			}
		}
};

static std::string eglErrorToString(const EGLint errorCode) {
	const std::string strErrorCode = StringUtils::toString(errorCode);
	switch(errorCode) {
		case EGL_SUCCESS:
			return "EGL_SUCCESS/" + strErrorCode + ": The last function succeeded without error.";
		case EGL_NOT_INITIALIZED:
			return "EGL_NOT_INITIALIZED/" + strErrorCode + ": EGL is not initialized, or could not be initialized, for the specified EGL display connection.";
		case EGL_BAD_ACCESS:
			return "EGL_BAD_ACCESS/" + strErrorCode + ": EGL cannot access a requested resource (for example a context is bound in another thread).";
		case EGL_BAD_ALLOC:
			return "EGL_BAD_ALLOC/" + strErrorCode + ": EGL failed to allocate resources for the requested operation.";
		case EGL_BAD_ATTRIBUTE:
			return "EGL_BAD_ATTRIBUTE/" + strErrorCode + ": An unrecognized attribute or attribute value was passed in the attribute list.";
		case EGL_BAD_CONTEXT:
			return "EGL_BAD_CONTEXT/" + strErrorCode + ": An EGLContext argument does not name a valid EGL rendering context.";
		case EGL_BAD_CONFIG:
			return "EGL_BAD_CONFIG/" + strErrorCode + ": An EGLConfig argument does not name a valid EGL frame buffer configuration.";
		case EGL_BAD_CURRENT_SURFACE:
			return "EGL_BAD_CURRENT_SURFACE/" + strErrorCode + ": The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid.";
		case EGL_BAD_DISPLAY:
			return "EGL_BAD_DISPLAY/" + strErrorCode + ": An EGLDisplay argument does not name a valid EGL display connection.";
		case EGL_BAD_SURFACE:
			return "EGL_BAD_SURFACE/" + strErrorCode + ": An EGLSurface argument does not name a valid surface (window, pixel buffer or pixmap) configured for GL rendering.";
		case EGL_BAD_MATCH:
			return "EGL_BAD_MATCH/" + strErrorCode + ": Arguments are inconsistent (for example, a valid context requires buffers not supplied by a valid surface).";
		case EGL_BAD_PARAMETER:
			return "EGL_BAD_PARAMETER/" + strErrorCode + ": One or more argument values are invalid.";
		case EGL_BAD_NATIVE_PIXMAP:
			return "EGL_BAD_NATIVE_PIXMAP/" + strErrorCode + ": A NativePixmapType argument does not refer to a valid native pixmap.";
		case EGL_BAD_NATIVE_WINDOW:
			return "EGL_BAD_NATIVE_WINDOW/" + strErrorCode + ": A NativeWindowType argument does not refer to a valid native window.";
		case EGL_CONTEXT_LOST:
			return "EGL_CONTEXT_LOST/" + strErrorCode + ": A power management event has occurred. The application must destroy all contexts and reinitialise OpenGL ES state and objects to continue rendering.";
		default:
			return "";
	}
}

WindowEGL::WindowEGL(const Window::Properties & properties) :
		WindowX11(properties), eglData(new WindowEGLData) {

	eglData->display = eglGetDisplay(x11Data->display);
	if (eglData->display == EGL_NO_DISPLAY) {
		throw std::runtime_error("Failed to open display.");
	}

	EGLint versionMajor;
	EGLint versionMinor;
	if (eglInitialize(eglData->display, &versionMajor, &versionMinor) == EGL_FALSE) {
		throw std::runtime_error("Failed to initialize display.");
	}

	// EGL version 1.3 is needed for EGL_CONTEXT_CLIENT_VERSION
	if ((versionMajor < 1) || ((versionMajor == 1) && (versionMinor < 3))) {
		throw std::runtime_error("EGL version less than 1.3 detected.");
	}

	// Define attributes of desired framebuffer configurations
	EGLint fbAttribs[] = { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, EGL_BUFFER_SIZE, 24, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 8,
							EGL_NATIVE_RENDERABLE, EGL_TRUE, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE };
	// Request a single framebuffer configuration
	EGLConfig fbConfig;
	EGLint fbCount;
	if (eglChooseConfig(eglData->display, fbAttribs, &fbConfig, 1, &fbCount) == EGL_FALSE) {
		throw std::runtime_error("Failed to retrieve a matching framebuffer configuration.");
	}

	if (fbCount == 0) {
		// FIXME: Workaround: Use eglGetConfigs instead of eglChooseConfig, because sometimes eglChooseConfig does not find matching configurations.
		EGLConfig fbConfigs[200];
		eglGetConfigs(eglData->display, fbConfigs, 200, &fbCount);
		for (EGLint i = 0; i < fbCount; ++i) {
			EGLint value;
			// We want to render into a window
			eglGetConfigAttrib(eglData->display, fbConfigs[i], EGL_SURFACE_TYPE, &value);
			if (!(value & EGL_WINDOW_BIT)) {
				continue;
			}
			// We want a configuration with a depth buffer
			eglGetConfigAttrib(eglData->display, fbConfigs[i], EGL_DEPTH_SIZE, &value);
			if (value == 0) {
				continue;
			}
			fbConfig = fbConfigs[i];
		}
	}

	if (fbCount == 0) {
		throw std::runtime_error("No matching framebuffer configurations found.");
	}

	EGLint visualID;
	eglGetConfigAttrib(eglData->display, fbConfig, EGL_NATIVE_VISUAL_ID, &visualID);

	const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
	eglData->context = eglCreateContext(eglData->display, fbConfig, EGL_NO_CONTEXT, contextAttribs);
	if (eglData->context == EGL_NO_CONTEXT) {
		throw std::runtime_error("Failed to create OpenGL ES 2.x context. " +
								 eglErrorToString(eglGetError()));
	}

	// Create X11 window
	XVisualInfo templateInfo;
	templateInfo.visualid = visualID;
	int visualCount;
	XVisualInfo * visualsInfo = XGetVisualInfo(x11Data->display, VisualIDMask, &templateInfo, &visualCount);
	if (visualsInfo == nullptr) {
		throw std::runtime_error("Failed to find a matching visual.");
	} else if (visualCount != 1) {
		XFree(visualsInfo);
		throw std::runtime_error("More than one visual found.");
	}

	x11Data->colorMap = XCreateColormap(x11Data->display, RootWindow(x11Data->display, visualsInfo[0].screen), visualsInfo[0].visual, AllocNone);
	x11Data->freeColorMap = true;

	XSetWindowAttributes windowAttribs;
	windowAttribs.colormap = x11Data->colorMap;
	windowAttribs.background_pixmap = None;
	windowAttribs.border_pixel = 0;
	windowAttribs.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask;

	x11Data->window = XCreateWindow(x11Data->display, RootWindow(x11Data->display, visualsInfo[0].screen),
								 0, 0, properties.clientAreaWidth, properties.clientAreaHeight,
								 0, visualsInfo[0].depth,
								 InputOutput, visualsInfo[0].visual, CWBorderPixel | CWColormap | CWEventMask, &windowAttribs);

	XFree(visualsInfo);

	if (!x11Data->window) {
		throw std::runtime_error("Failed to create window.");
	} else {
		x11Data->freeWindow = true;
	}

	if (properties.borderless) {
		x11Data->removeWindowBorder();
	}
	if (!properties.resizable) {
		x11Data->fixWindowSize(static_cast<int>(properties.clientAreaWidth),
							   static_cast<int>(properties.clientAreaHeight));
	}

	x11Data->inputMethod = XOpenIM(x11Data->display, nullptr, nullptr, nullptr);
	if (x11Data->inputMethod == nullptr) {
		throw std::runtime_error("Failed to create input method.");
	}

	x11Data->inputContext = XCreateIC(x11Data->inputMethod,
								   XNInputStyle, XIMPreeditNone | XIMStatusNone,
								   XNClientWindow, x11Data->window,
								   XNFocusWindow, x11Data->window,
								   nullptr);
	if (x11Data->inputContext == nullptr) {
		throw std::runtime_error("Failed to create input context.");
	}

	XStoreName(x11Data->display, x11Data->window, properties.title.c_str());

	XMapWindow(x11Data->display, x11Data->window);
	if (properties.positioned) {
		XMoveWindow(x11Data->display, x11Data->window, properties.posX, properties.posY);
	}

	eglData->surface = eglCreateWindowSurface(eglData->display, fbConfig, x11Data->window, nullptr);
	if (eglData->surface == EGL_NO_SURFACE) {
		throw std::runtime_error("Failed to create window surface.");
	}

	eglMakeCurrent(eglData->display, eglData->surface, eglData->surface, eglData->context);
}

WindowEGL::~WindowEGL() = default;

void WindowEGL::swapBuffers() {
	eglSwapBuffers(eglData->display, eglData->surface);
}

}
}

#endif /* defined(UTIL_HAVE_LIB_X11) and defined(UTIL_HAVE_LIB_EGL) */
<|endoftext|>


<commit_before>#include "ctreestateaddstatement.h"

/* Constructor */
CTreeStateAddStatement::CTreeStateAddStatement(TreeState* prev, QString s)
{
    previous = prev;

    desired = previous; // TODO: copy constructor
    desired->addChildStatement(s);
}

/* Update the state to the one with the add */
void CTreeStateAddStatement::execute()
{
    current = desired;
}

/* Revert to the state before the add */
void CTreeStateAddStatement::undo()
{
    current = previous;
}

/* Re-add the statement after undo */
void CTreeStateAddStatement::redo()
{
    current = desired;
}
<commit_msg>Updated to use copy constructor<commit_after>#include "ctreestateaddstatement.h"

/* Constructor */
CTreeStateAddStatement::CTreeStateAddStatement(TreeState* prev, QString s)
{
    previous = prev;

    desired = TreeState(prev);
    desired->addChildStatement(s);
}

/* Update the state to the one with the add */
void CTreeStateAddStatement::execute()
{
    current = desired;
}

/* Revert to the state before the add */
void CTreeStateAddStatement::undo()
{
    current = previous;
}

/* Re-add the statement after undo */
void CTreeStateAddStatement::redo()
{
    current = desired;
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#ifndef _Stroika_Foundation_Common_KeyValuePair_inl_
#define _Stroika_Foundation_Common_KeyValuePair_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

namespace Stroika {
    namespace Foundation {
        namespace Common {

            /*
             ********************************************************************************
             ******************** Common::KeyValuePair<KEY_TYPE,VALUE_TYPE> *****************
             ********************************************************************************
             */
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename K2, typename V2,
                      enable_if_t<
                          is_copy_constructible<K2>::value and
                              is_copy_constructible<V2>::value and
                              is_convertible<const K2&, K2>::value and
                              is_convertible<const V2&, V2>::value,
                          int>
                          ENABLE_IF>
            inline constexpr KeyValuePair<KEY_TYPE, VALUE_TYPE>::KeyValuePair (const KeyType& key, const ValueType& value)
                : fKey (key)
                , fValue (value)
            {
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2,
                      enable_if_t<
                          is_constructible<KEY_TYPE, const KEY_TYPE2&>::value and
                              is_constructible<VALUE_TYPE, const VALUE_TYPE2&>::value and
                              is_convertible<const KEY_TYPE2&, KEY_TYPE>::value and
                              is_convertible<const VALUE_TYPE2&, VALUE_TYPE>::value,
                          int>
                          ENABLE_IF_CONVERTIBLE>
            inline constexpr KeyValuePair<KEY_TYPE, VALUE_TYPE>::KeyValuePair (const pair<KEY_TYPE2, VALUE_TYPE2>& src)
                : fKey (src.first)
                , fValue (src.second)
            {
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2,
                      enable_if_t<
                          is_constructible<KEY_TYPE, const KEY_TYPE2&>::value and
                              is_constructible<VALUE_TYPE, const VALUE_TYPE2&>::value and
                              !(is_convertible<const KEY_TYPE2&, KEY_TYPE>::value and is_convertible<const VALUE_TYPE2&, VALUE_TYPE>::value),
                          int>
                          ENABLE_IF_NOT_CONVERTIBLE>
            inline constexpr KeyValuePair<KEY_TYPE, VALUE_TYPE>::KeyValuePair (const pair<KEY_TYPE2, VALUE_TYPE2>& src)
                : fKey (src.first)
                , fValue (src.second)
            {
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2,
                      enable_if_t<
                          is_constructible<KEY_TYPE, const KEY_TYPE2&>::value and
                              is_constructible<VALUE_TYPE, const VALUE_TYPE2&>::value and
                              (is_convertible<const KEY_TYPE2&, KEY_TYPE>::value and is_convertible<const VALUE_TYPE2&, VALUE_TYPE>::value),
                          int>
                          ENABLE_IF_CONVERTIBLE>
            inline constexpr KeyValuePair<KEY_TYPE, VALUE_TYPE>::KeyValuePair (const KeyValuePair<KEY_TYPE2, VALUE_TYPE2>& src)
                : fKey (src.fKey)
                , fValue (src.fValue)
            {
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2,
                      enable_if_t<
                          is_constructible<KEY_TYPE, const KEY_TYPE2&>::value and
                              is_constructible<VALUE_TYPE, const VALUE_TYPE2&>::value and
                              !(is_convertible<const KEY_TYPE2&, KEY_TYPE>::value and is_convertible<const VALUE_TYPE2&, VALUE_TYPE>::value),
                          int>
                          ENABLE_IF_NOT_CONVERTIBLE>
            inline constexpr KeyValuePair<KEY_TYPE, VALUE_TYPE>::KeyValuePair (const KeyValuePair<KEY_TYPE2, VALUE_TYPE2>& src)
                : fKey (src.fKey)
                , fValue (src.fValue)
            {
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2>
            KeyValuePair<KEY_TYPE, VALUE_TYPE>& KeyValuePair<KEY_TYPE, VALUE_TYPE>::operator= (const pair<KEY_TYPE2, VALUE_TYPE2>& rhs)
            {
                fKey   = rhs.first;
                fValue = rhs.second;
                return *this;
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2>
            KeyValuePair<KEY_TYPE, VALUE_TYPE>& KeyValuePair<KEY_TYPE, VALUE_TYPE>::operator= (const KeyValuePair<KEY_TYPE2, VALUE_TYPE2>& rhs)
            {
                rhs = _Right.fKey;
                rhs = _Right.fValue;
                return *this;
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2>
            KeyValuePair<KEY_TYPE, VALUE_TYPE>& KeyValuePair<KEY_TYPE, VALUE_TYPE>::operator= (pair<KEY_TYPE2, VALUE_TYPE2>&& rhs)
            {
                fKey   = std::forward<KEY_TYPE2> (rhs.first);
                fValue = std::forward<VALUE_TYPE2> (rhs.second);
                return *this;
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2>
            KeyValuePair<KEY_TYPE, VALUE_TYPE>& KeyValuePair<KEY_TYPE, VALUE_TYPE>::operator= (KeyValuePair<KEY_TYPE2, VALUE_TYPE2>&& rhs)
            {
                fKey   = std::forward<KEY_TYPE2> (rhs.fKey);
                fValue = std::forward<VALUE_TYPE2> (rhs.fValue);
                return *this;
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            inline bool KeyValuePair<KEY_TYPE, VALUE_TYPE>::Equals (const KeyValuePair<KeyType, ValueType>& rhs) const
            {
                return fKey == rhs.fKey and fValue == rhs.fValue;
            }

            /*
             ********************************************************************************
             ************************** KeyValuePair operators ******************************
             ********************************************************************************
             */
            template <typename KEY_TYPE, typename VALUE_TYPE>
            inline bool operator== (const KeyValuePair<KEY_TYPE, VALUE_TYPE>& lhs, const KeyValuePair<KEY_TYPE, VALUE_TYPE>& rhs)
            {
                return lhs.Equals (rhs);
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            inline bool operator!= (const KeyValuePair<KEY_TYPE, VALUE_TYPE>& lhs, const KeyValuePair<KEY_TYPE, VALUE_TYPE>& rhs)
            {
                return not lhs.Equals (rhs);
            }
        }
    }
}
#endif /*_Stroika_Foundation_Common_KeyValuePair_inl_*/
<commit_msg>fixed a few types with KeyValuePair<> change<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#ifndef _Stroika_Foundation_Common_KeyValuePair_inl_
#define _Stroika_Foundation_Common_KeyValuePair_inl_ 1

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */

namespace Stroika {
    namespace Foundation {
        namespace Common {

            /*
             ********************************************************************************
             ******************** Common::KeyValuePair<KEY_TYPE,VALUE_TYPE> *****************
             ********************************************************************************
             */
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename K2, typename V2,
                      enable_if_t<
                          is_copy_constructible<K2>::value and
                              is_copy_constructible<V2>::value and
                              is_convertible<const K2&, K2>::value and
                              is_convertible<const V2&, V2>::value,
                          int>
                          ENABLE_IF>
            inline constexpr KeyValuePair<KEY_TYPE, VALUE_TYPE>::KeyValuePair (const KeyType& key, const ValueType& value)
                : fKey (key)
                , fValue (value)
            {
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2,
                      enable_if_t<
                          is_constructible<KEY_TYPE, const KEY_TYPE2&>::value and
                              is_constructible<VALUE_TYPE, const VALUE_TYPE2&>::value and
                              is_convertible<const KEY_TYPE2&, KEY_TYPE>::value and
                              is_convertible<const VALUE_TYPE2&, VALUE_TYPE>::value,
                          int>
                          ENABLE_IF_CONVERTIBLE>
            inline constexpr KeyValuePair<KEY_TYPE, VALUE_TYPE>::KeyValuePair (const pair<KEY_TYPE2, VALUE_TYPE2>& src)
                : fKey (src.first)
                , fValue (src.second)
            {
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2,
                      enable_if_t<
                          is_constructible<KEY_TYPE, const KEY_TYPE2&>::value and
                              is_constructible<VALUE_TYPE, const VALUE_TYPE2&>::value and
                              !(is_convertible<const KEY_TYPE2&, KEY_TYPE>::value and is_convertible<const VALUE_TYPE2&, VALUE_TYPE>::value),
                          int>
                          ENABLE_IF_NOT_CONVERTIBLE>
            inline constexpr KeyValuePair<KEY_TYPE, VALUE_TYPE>::KeyValuePair (const pair<KEY_TYPE2, VALUE_TYPE2>& src)
                : fKey (src.first)
                , fValue (src.second)
            {
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2,
                      enable_if_t<
                          is_constructible<KEY_TYPE, const KEY_TYPE2&>::value and
                              is_constructible<VALUE_TYPE, const VALUE_TYPE2&>::value and
                              (is_convertible<const KEY_TYPE2&, KEY_TYPE>::value and is_convertible<const VALUE_TYPE2&, VALUE_TYPE>::value),
                          int>
                          ENABLE_IF_CONVERTIBLE>
            inline constexpr KeyValuePair<KEY_TYPE, VALUE_TYPE>::KeyValuePair (const KeyValuePair<KEY_TYPE2, VALUE_TYPE2>& src)
                : fKey (src.fKey)
                , fValue (src.fValue)
            {
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2,
                      enable_if_t<
                          is_constructible<KEY_TYPE, const KEY_TYPE2&>::value and
                              is_constructible<VALUE_TYPE, const VALUE_TYPE2&>::value and
                              !(is_convertible<const KEY_TYPE2&, KEY_TYPE>::value and is_convertible<const VALUE_TYPE2&, VALUE_TYPE>::value),
                          int>
                          ENABLE_IF_NOT_CONVERTIBLE>
            inline constexpr KeyValuePair<KEY_TYPE, VALUE_TYPE>::KeyValuePair (const KeyValuePair<KEY_TYPE2, VALUE_TYPE2>& src)
                : fKey (src.fKey)
                , fValue (src.fValue)
            {
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2>
            KeyValuePair<KEY_TYPE, VALUE_TYPE>& KeyValuePair<KEY_TYPE, VALUE_TYPE>::operator= (const pair<KEY_TYPE2, VALUE_TYPE2>& rhs)
            {
                fKey   = rhs.first;
                fValue = rhs.second;
                return *this;
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2>
            inline KeyValuePair<KEY_TYPE, VALUE_TYPE>& KeyValuePair<KEY_TYPE, VALUE_TYPE>::operator= (const KeyValuePair<KEY_TYPE2, VALUE_TYPE2>& rhs)
            {
                rhs = rhs.fKey;
                rhs = rhs.fValue;
                return *this;
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2>
            inline KeyValuePair<KEY_TYPE, VALUE_TYPE>& KeyValuePair<KEY_TYPE, VALUE_TYPE>::operator= (pair<KEY_TYPE2, VALUE_TYPE2>&& rhs)
            {
                fKey   = std::forward<KEY_TYPE2> (rhs.first);
                fValue = std::forward<VALUE_TYPE2> (rhs.second);
                return *this;
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            template <typename KEY_TYPE2, typename VALUE_TYPE2>
            inline KeyValuePair<KEY_TYPE, VALUE_TYPE>& KeyValuePair<KEY_TYPE, VALUE_TYPE>::operator= (KeyValuePair<KEY_TYPE2, VALUE_TYPE2>&& rhs)
            {
                fKey   = std::forward<KEY_TYPE2> (rhs.fKey);
                fValue = std::forward<VALUE_TYPE2> (rhs.fValue);
                return *this;
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            inline bool KeyValuePair<KEY_TYPE, VALUE_TYPE>::Equals (const KeyValuePair<KeyType, ValueType>& rhs) const
            {
                return fKey == rhs.fKey and fValue == rhs.fValue;
            }

            /*
             ********************************************************************************
             ************************** KeyValuePair operators ******************************
             ********************************************************************************
             */
            template <typename KEY_TYPE, typename VALUE_TYPE>
            inline bool operator== (const KeyValuePair<KEY_TYPE, VALUE_TYPE>& lhs, const KeyValuePair<KEY_TYPE, VALUE_TYPE>& rhs)
            {
                return lhs.Equals (rhs);
            }
            template <typename KEY_TYPE, typename VALUE_TYPE>
            inline bool operator!= (const KeyValuePair<KEY_TYPE, VALUE_TYPE>& lhs, const KeyValuePair<KEY_TYPE, VALUE_TYPE>& rhs)
            {
                return not lhs.Equals (rhs);
            }
        }
    }
}
#endif /*_Stroika_Foundation_Common_KeyValuePair_inl_*/
<|endoftext|>


<commit_before>//=============================================================================================================
/**
* @file     pervertexphongalphamaterial.cpp
* @author   Lorenz Esch <Lorenz.Esch@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     January, 2017
*
* @section  LICENSE
*
* Copyright (C) 2017, Lorenz Esch and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    PerVertexPhongAlphaMaterial class definition
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "pervertexphongalphamaterial.h"

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QColor>
#include <Qt3DRender/qeffect.h>
#include <Qt3DRender/qtechnique.h>
#include <Qt3DRender/qshaderprogram.h>
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qrenderpass.h>
#include <QFilterKey>
#include <Qt3DRender/qdepthtest.h>
#include <Qt3DRender/qblendequation.h>
#include <Qt3DRender/qblendequationarguments.h>
#include <Qt3DRender/qnodepthmask.h>
#include <Qt3DRender/qgraphicsapifilter.h>

#include <QUrl>
#include <QVector3D>
#include <QVector4D>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace DISP3DLIB;
using namespace Qt3DRender;

//*************************************************************************************************************
//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

PerVertexPhongAlphaMaterial::PerVertexPhongAlphaMaterial(QNode *parent)
: QMaterial(parent)
, m_pVertexEffect(new QEffect())
, m_pDiffuseParameter(new QParameter(QStringLiteral("kd"), QColor::fromRgbF(0.7f, 0.7f, 0.7f, 1.0f)))
, m_pSpecularParameter(new QParameter(QStringLiteral("ks"), QColor::fromRgbF(0.1f, 0.1f, 0.1f, 1.0f)))
, m_pShininessParameter(new QParameter(QStringLiteral("shininess"), 15.0f))
, m_pAlphaParameter(new QParameter("alpha", 0.5f))
, m_pVertexGL3Technique(new QTechnique())
, m_pVertexGL3RenderPass(new QRenderPass())
, m_pVertexGL3Shader(new QShaderProgram())
, m_pVertexGL2Technique(new QTechnique())
, m_pVertexGL2RenderPass(new QRenderPass())
, m_pVertexES2Technique(new QTechnique())
, m_pVertexES2RenderPass(new QRenderPass())
, m_pVertexES2Shader(new QShaderProgram())
, m_pFilterKey(new QFilterKey)
, m_pNoDepthMask(new QNoDepthMask())
, m_pBlendState(new QBlendEquationArguments())
, m_pBlendEquation(new QBlendEquation())
{
    this->init();
}

//*************************************************************************************************************

PerVertexPhongAlphaMaterial::~PerVertexPhongAlphaMaterial()
{
}

//*************************************************************************************************************

void PerVertexPhongAlphaMaterial::init()
{
    //Set shader
    m_pVertexGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/model/materials/shaders/gl3/pervertexphongalpha.vert"))));
    m_pVertexGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/model/materials/shaders/gl3/pervertexphongalpha.frag"))));
    m_pVertexES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/model/materials/shaders/es2/pervertexphongalpha.vert"))));
    m_pVertexES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/model/materials/shaders/es2/pervertexphongalpha.frag"))));

    m_pVertexGL3RenderPass->setShaderProgram(m_pVertexGL3Shader);
    m_pVertexGL3RenderPass->setShaderProgram(m_pVertexES2Shader);
    m_pVertexGL3RenderPass->setShaderProgram(m_pVertexES2Shader);

    //Set OpenGL version
    m_pVertexGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
    m_pVertexGL3Technique->graphicsApiFilter()->setMajorVersion(4);
    m_pVertexGL3Technique->graphicsApiFilter()->setMinorVersion(0);
    m_pVertexGL3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);

        m_pVertexGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
    m_pVertexGL3Technique->graphicsApiFilter()->setMajorVersion(2);
    m_pVertexGL3Technique->graphicsApiFilter()->setMinorVersion(0);
    m_pVertexGL3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);

    m_pVertexGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGLES);
    m_pVertexGL3Technique->graphicsApiFilter()->setMajorVersion(2);
    m_pVertexGL3Technique->graphicsApiFilter()->setMinorVersion(0);
    m_pVertexGL3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);

    //Setup transparency
    m_pBlendState->setSourceRgb(QBlendEquationArguments::SourceAlpha);
    m_pBlendState->setDestinationRgb(QBlendEquationArguments::OneMinusSourceAlpha);
    m_pBlendEquation->setBlendFunction(QBlendEquation::Add);

    m_pVertexGL3RenderPass->addRenderState(m_pBlendEquation);
    m_pVertexGL2RenderPass->addRenderState(m_pBlendEquation);
    m_pVertexES2RenderPass->addRenderState(m_pBlendEquation);

    m_pVertexGL3RenderPass->addRenderState(m_pNoDepthMask);
    m_pVertexGL2RenderPass->addRenderState(m_pNoDepthMask);
    m_pVertexES2RenderPass->addRenderState(m_pNoDepthMask);

    m_pVertexGL3RenderPass->addRenderState(m_pBlendState);
    m_pVertexGL2RenderPass->addRenderState(m_pBlendState);
    m_pVertexES2RenderPass->addRenderState(m_pBlendState);

    m_pFilterKey->setName(QStringLiteral("renderingStyle"));
    m_pFilterKey->setValue(QStringLiteral("forward"));

    m_pVertexGL3Technique->addFilterKey(m_pFilterKey);
    m_pVertexGL2Technique->addFilterKey(m_pFilterKey);
    m_pVertexES2Technique->addFilterKey(m_pFilterKey);

    m_pVertexGL3Technique->addRenderPass(m_pVertexGL3RenderPass);
    m_pVertexGL2Technique->addRenderPass(m_pVertexGL2RenderPass);
    m_pVertexES2Technique->addRenderPass(m_pVertexES2RenderPass);

    m_pVertexEffect->addTechnique(m_pVertexGL3Technique);
    m_pVertexEffect->addTechnique(m_pVertexGL2Technique);
    m_pVertexEffect->addTechnique(m_pVertexES2Technique);

    m_pVertexEffect->addParameter(m_pDiffuseParameter);
    m_pVertexEffect->addParameter(m_pSpecularParameter);
    m_pVertexEffect->addParameter(m_pShininessParameter);
    m_pVertexEffect->addParameter(m_pAlphaParameter);

    this->setEffect(m_pVertexEffect);
}

//*************************************************************************************************************

float PerVertexPhongAlphaMaterial::alpha()
{
    return m_pAlphaParameter->value().toFloat();
}

//*************************************************************************************************************

void PerVertexPhongAlphaMaterial::setAlpha(float alpha)
{
    m_pAlphaParameter->setValue(alpha);
}

<commit_msg>[LIB-149] Fix naming bug<commit_after>//=============================================================================================================
/**
* @file     pervertexphongalphamaterial.cpp
* @author   Lorenz Esch <Lorenz.Esch@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     January, 2017
*
* @section  LICENSE
*
* Copyright (C) 2017, Lorenz Esch and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    PerVertexPhongAlphaMaterial class definition
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "pervertexphongalphamaterial.h"

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QColor>
#include <Qt3DRender/qeffect.h>
#include <Qt3DRender/qtechnique.h>
#include <Qt3DRender/qshaderprogram.h>
#include <Qt3DRender/qparameter.h>
#include <Qt3DRender/qrenderpass.h>
#include <QFilterKey>
#include <Qt3DRender/qdepthtest.h>
#include <Qt3DRender/qblendequation.h>
#include <Qt3DRender/qblendequationarguments.h>
#include <Qt3DRender/qnodepthmask.h>
#include <Qt3DRender/qgraphicsapifilter.h>

#include <QUrl>
#include <QVector3D>
#include <QVector4D>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace DISP3DLIB;
using namespace Qt3DRender;

//*************************************************************************************************************
//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

PerVertexPhongAlphaMaterial::PerVertexPhongAlphaMaterial(QNode *parent)
: QMaterial(parent)
, m_pVertexEffect(new QEffect())
, m_pDiffuseParameter(new QParameter(QStringLiteral("kd"), QColor::fromRgbF(0.7f, 0.7f, 0.7f, 1.0f)))
, m_pSpecularParameter(new QParameter(QStringLiteral("ks"), QColor::fromRgbF(0.1f, 0.1f, 0.1f, 1.0f)))
, m_pShininessParameter(new QParameter(QStringLiteral("shininess"), 15.0f))
, m_pAlphaParameter(new QParameter("alpha", 0.5f))
, m_pVertexGL3Technique(new QTechnique())
, m_pVertexGL3RenderPass(new QRenderPass())
, m_pVertexGL3Shader(new QShaderProgram())
, m_pVertexGL2Technique(new QTechnique())
, m_pVertexGL2RenderPass(new QRenderPass())
, m_pVertexES2Technique(new QTechnique())
, m_pVertexES2RenderPass(new QRenderPass())
, m_pVertexES2Shader(new QShaderProgram())
, m_pFilterKey(new QFilterKey)
, m_pNoDepthMask(new QNoDepthMask())
, m_pBlendState(new QBlendEquationArguments())
, m_pBlendEquation(new QBlendEquation())
{
    this->init();
}

//*************************************************************************************************************

PerVertexPhongAlphaMaterial::~PerVertexPhongAlphaMaterial()
{
}

//*************************************************************************************************************

void PerVertexPhongAlphaMaterial::init()
{
    //Set shader
    m_pVertexGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/model/materials/shaders/gl3/pervertexphongalpha.vert"))));
    m_pVertexGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/model/materials/shaders/gl3/pervertexphongalpha.frag"))));
    m_pVertexES2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/model/materials/shaders/es2/pervertexphongalpha.vert"))));
    m_pVertexES2Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/model/materials/shaders/es2/pervertexphongalpha.frag"))));

    m_pVertexGL3RenderPass->setShaderProgram(m_pVertexGL3Shader);
    m_pVertexGL3RenderPass->setShaderProgram(m_pVertexES2Shader);
    m_pVertexGL3RenderPass->setShaderProgram(m_pVertexES2Shader);

    //Set OpenGL version
    m_pVertexGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
    m_pVertexGL3Technique->graphicsApiFilter()->setMajorVersion(4);
    m_pVertexGL3Technique->graphicsApiFilter()->setMinorVersion(0);
    m_pVertexGL3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);

    m_pVertexGL2Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
    m_pVertexGL2Technique->graphicsApiFilter()->setMajorVersion(2);
    m_pVertexGL2Technique->graphicsApiFilter()->setMinorVersion(0);
    m_pVertexGL2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);

    m_pVertexES2Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGLES);
    m_pVertexES2Technique->graphicsApiFilter()->setMajorVersion(2);
    m_pVertexES2Technique->graphicsApiFilter()->setMinorVersion(0);
    m_pVertexES2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);

    //Setup transparency
    m_pBlendState->setSourceRgb(QBlendEquationArguments::SourceAlpha);
    m_pBlendState->setDestinationRgb(QBlendEquationArguments::OneMinusSourceAlpha);
    m_pBlendEquation->setBlendFunction(QBlendEquation::Add);

    m_pVertexGL3RenderPass->addRenderState(m_pBlendEquation);
    m_pVertexGL2RenderPass->addRenderState(m_pBlendEquation);
    m_pVertexES2RenderPass->addRenderState(m_pBlendEquation);

    m_pVertexGL3RenderPass->addRenderState(m_pNoDepthMask);
    m_pVertexGL2RenderPass->addRenderState(m_pNoDepthMask);
    m_pVertexES2RenderPass->addRenderState(m_pNoDepthMask);

    m_pVertexGL3RenderPass->addRenderState(m_pBlendState);
    m_pVertexGL2RenderPass->addRenderState(m_pBlendState);
    m_pVertexES2RenderPass->addRenderState(m_pBlendState);

    m_pFilterKey->setName(QStringLiteral("renderingStyle"));
    m_pFilterKey->setValue(QStringLiteral("forward"));

    m_pVertexGL3Technique->addFilterKey(m_pFilterKey);
    m_pVertexGL2Technique->addFilterKey(m_pFilterKey);
    m_pVertexES2Technique->addFilterKey(m_pFilterKey);

    m_pVertexGL3Technique->addRenderPass(m_pVertexGL3RenderPass);
    m_pVertexGL2Technique->addRenderPass(m_pVertexGL2RenderPass);
    m_pVertexES2Technique->addRenderPass(m_pVertexES2RenderPass);

    m_pVertexEffect->addTechnique(m_pVertexGL3Technique);
    m_pVertexEffect->addTechnique(m_pVertexGL2Technique);
    m_pVertexEffect->addTechnique(m_pVertexES2Technique);

    m_pVertexEffect->addParameter(m_pDiffuseParameter);
    m_pVertexEffect->addParameter(m_pSpecularParameter);
    m_pVertexEffect->addParameter(m_pShininessParameter);
    m_pVertexEffect->addParameter(m_pAlphaParameter);

    this->setEffect(m_pVertexEffect);
}

//*************************************************************************************************************

float PerVertexPhongAlphaMaterial::alpha()
{
    return m_pAlphaParameter->value().toFloat();
}

//*************************************************************************************************************

void PerVertexPhongAlphaMaterial::setAlpha(float alpha)
{
    m_pAlphaParameter->setValue(alpha);
}

<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "filehandle.h"
#include "common/continuation/continuation.h"
#include "common/logging.h"
#include "connection/datanodeconnection.h"
#include "reader/block_reader.h"
#include "hdfspp/events.h"

#include <future>
#include <tuple>

#define FMT_THIS_ADDR "this=" << (void*)this

namespace hdfs {

using ::hadoop::hdfs::LocatedBlocksProto;

FileHandle::~FileHandle() {}

FileHandleImpl::FileHandleImpl(const std::string & cluster_name,
                               const std::string & path,
                               ::asio::io_service *io_service, const std::string &client_name,
                                 const std::shared_ptr<const struct FileInfo> file_info,
                                 std::shared_ptr<BadDataNodeTracker> bad_data_nodes,
                                 std::shared_ptr<LibhdfsEvents> event_handlers)
    : cluster_name_(cluster_name), path_(path), io_service_(io_service), client_name_(client_name), file_info_(file_info),
      bad_node_tracker_(bad_data_nodes), offset_(0), cancel_state_(CancelTracker::New()), event_handlers_(event_handlers) {
  LOG_TRACE(kFileHandle, << "FileHandleImpl::FileHandleImpl("
                         << FMT_THIS_ADDR << ", ...) called");

}

void FileHandleImpl::PositionRead(
    void *buf, size_t nbyte, uint64_t offset,
    const std::function<void(const Status &, size_t)> &handler) {
  LOG_TRACE(kFileHandle, << "FileHandleImpl::PositionRead("
                         << FMT_THIS_ADDR << ", buf=" << buf
                         << ", nbyte=" << nbyte << ") called");

  /* prevent usage after cancelation */
  if(cancel_state_->is_canceled()) {
    handler(Status::Canceled(), 0);
    return;
  }

  auto callback = [this, handler](const Status &status,
                                  const std::string &contacted_datanode,
                                  size_t bytes_read) {
    /* determine if DN gets marked bad */
    if (ShouldExclude(status)) {
      bad_node_tracker_->AddBadNode(contacted_datanode);
    }

    handler(status, bytes_read);
  };

  AsyncPreadSome(offset, asio::buffer(buf, nbyte), bad_node_tracker_, callback);
}

Status FileHandleImpl::PositionRead(void *buf, size_t *nbyte, off_t offset) {
  LOG_TRACE(kFileHandle, << "FileHandleImpl::[sync]PositionRead("
                         << FMT_THIS_ADDR << ", buf=" << buf
                         << ", nbyte=" << *nbyte << ") called");

  auto callstate = std::make_shared<std::promise<std::tuple<Status, size_t>>>();
  std::future<std::tuple<Status, size_t>> future(callstate->get_future());

  /* wrap async call with promise/future to make it blocking */
  auto callback = [callstate](const Status &s, size_t bytes) {
    callstate->set_value(std::make_tuple(s,bytes));
  };

  PositionRead(buf, *nbyte, offset, callback);

  /* wait for async to finish */
  auto returnstate = future.get();
  auto stat = std::get<0>(returnstate);

  if (!stat.ok()) {
    return stat;
  }

  *nbyte = std::get<1>(returnstate);
  return stat;
}

Status FileHandleImpl::Read(void *buf, size_t *nbyte) {
  LOG_TRACE(kFileHandle, << "FileHandleImpl::Read("
                         << FMT_THIS_ADDR << ", buf=" << buf
                         << ", nbyte=" << *nbyte << ") called");

  Status stat = PositionRead(buf, nbyte, offset_);
  if(!stat.ok()) {
    return stat;
  }

  offset_ += *nbyte;
  return Status::OK();
}

Status FileHandleImpl::Seek(off_t *offset, std::ios_base::seekdir whence) {
  LOG_TRACE(kFileHandle, << "FileHandleImpl::Seek("
                         << ", offset=" << *offset << ", ...) called");

  if(cancel_state_->is_canceled()) {
    return Status::Canceled();
  }

  off_t new_offset = -1;

  switch (whence) {
    case std::ios_base::beg:
      new_offset = *offset;
      break;
    case std::ios_base::cur:
      new_offset = offset_ + *offset;
      break;
    case std::ios_base::end:
      new_offset = file_info_->file_length_ + *offset;
      break;
    default:
      /* unsupported */
      return Status::InvalidArgument("Invalid Seek whence argument");
  }

  if(!CheckSeekBounds(new_offset)) {
    return Status::InvalidArgument("Seek offset out of bounds");
  }
  offset_ = new_offset;

  *offset = offset_;
  return Status::OK();
}

/* return false if seek will be out of bounds */
bool FileHandleImpl::CheckSeekBounds(ssize_t desired_position) {
  ssize_t file_length = file_info_->file_length_;

  if (desired_position < 0 || desired_position > file_length) {
    return false;
  }

  return true;
}

/*
 * Note that this method must be thread-safe w.r.t. the unsafe operations occurring
 * on the FileHandle
 */
void FileHandleImpl::AsyncPreadSome(
    size_t offset, const MutableBuffers &buffers,
    std::shared_ptr<NodeExclusionRule> excluded_nodes,
    const std::function<void(const Status &, const std::string &, size_t)> handler) {
  using ::hadoop::hdfs::DatanodeInfoProto;
  using ::hadoop::hdfs::LocatedBlockProto;

  LOG_TRACE(kFileHandle, << "FileHandleImpl::AsyncPreadSome("
                         << FMT_THIS_ADDR << ", ...) called");

  if(cancel_state_->is_canceled()) {
    handler(Status::Canceled(), "", 0);
    return;
  }

  /**
   *  Note: block and chosen_dn will end up pointing to things inside
   *  the blocks_ vector.  They shouldn't be directly deleted.
   **/
  auto block = std::find_if(
      file_info_->blocks_.begin(), file_info_->blocks_.end(), [offset](const LocatedBlockProto &p) {
        return p.offset() <= offset && offset < p.offset() + p.b().numbytes();
      });

  if (block == file_info_->blocks_.end()) {
    LOG_WARN(kFileHandle, << "FileHandleImpl::AsyncPreadSome(" << FMT_THIS_ADDR
                          << ", ...) Cannot find corresponding blocks");
    handler(Status::InvalidArgument("Cannot find corresponding blocks"), "", 0);
    return;
  }

  /**
   * If user supplies a rule use it, otherwise use the tracker.
   * User is responsible for making sure one of them isn't null.
   **/
  std::shared_ptr<NodeExclusionRule> rule =
      excluded_nodes != nullptr ? excluded_nodes : bad_node_tracker_;

  auto datanodes = block->locs();
  auto it = std::find_if(datanodes.begin(), datanodes.end(),
                         [rule](const DatanodeInfoProto &dn) {
                           return !rule->IsBadNode(dn.id().datanodeuuid());
                         });

  if (it == datanodes.end()) {
    LOG_WARN(kFileHandle, << "FileHandleImpl::AsyncPreadSome("
                          << FMT_THIS_ADDR << ", ...) No datanodes available");

    handler(Status::ResourceUnavailable("No datanodes available"), "", 0);
    return;
  }

  DatanodeInfoProto &chosen_dn = *it;

  uint64_t offset_within_block = offset - block->offset();
  uint64_t size_within_block = std::min<uint64_t>(
      block->b().numbytes() - offset_within_block, asio::buffer_size(buffers));

  // This is where we will put the logic for re-using a DN connection; we can
  //    steal the FileHandle's dn and put it back when we're done
  std::shared_ptr<DataNodeConnection> dn = CreateDataNodeConnection(io_service_, chosen_dn, &block->blocktoken());
  std::string dn_id = dn->uuid_;
  std::string client_name = client_name_;

  // Wrap the DN in a block reader to handle the state and logic of the
  //    block request protocol
  std::shared_ptr<BlockReader> reader;
  reader = CreateBlockReader(BlockReaderOptions(), dn);

  // Lambdas cannot capture copies of member variables so we'll make explicit
  //    copies for it
  auto event_handlers = event_handlers_;
  auto path = path_;
  auto cluster_name = cluster_name_;

  auto read_handler = [reader, event_handlers, cluster_name, path, dn_id, handler](const Status & status, size_t transferred) {
    auto event_resp = event_handlers->call(FILE_DN_READ_EVENT, cluster_name.c_str(), path.c_str(), transferred);
#ifndef NDEBUG
    if (event_resp.response() == event_response::kTest_Error) {
      handler(event_resp.status(), dn_id, transferred);
      return;
    }
#endif

    handler(status, dn_id, transferred);
  };

  auto connect_handler = [handler,event_handlers,cluster_name,path,read_handler,block,offset_within_block,size_within_block, buffers, reader, dn_id, client_name]
          (Status status, std::shared_ptr<DataNodeConnection> dn) {
    (void)dn;
    auto event_resp = event_handlers->call(FILE_DN_CONNECT_EVENT, cluster_name.c_str(), path.c_str(), 0);
#ifndef NDEBUG
    if (event_resp.response() == event_response::kTest_Error) {
      status = event_resp.status();
    }
#endif

    if (status.ok()) {
      reader->AsyncReadBlock(
          client_name, *block, offset_within_block,
          asio::buffer(buffers, size_within_block), read_handler);
    } else {
      handler(status, dn_id, 0);
    }
  };

  dn->Connect(connect_handler);

  return;
}

std::shared_ptr<BlockReader> FileHandleImpl::CreateBlockReader(const BlockReaderOptions &options,
                                               std::shared_ptr<DataNodeConnection> dn)
{
  std::shared_ptr<BlockReader> reader = std::make_shared<BlockReaderImpl>(options, dn, cancel_state_);

  LOG_TRACE(kFileHandle, << "FileHandleImpl::CreateBlockReader(" << FMT_THIS_ADDR
                         << ", ..., dnconn=" << dn.get()
                         << ") called.  New BlockReader = " << reader.get());

  readers_.AddReader(reader);
  return reader;
}

std::shared_ptr<DataNodeConnection> FileHandleImpl::CreateDataNodeConnection(
    ::asio::io_service * io_service,
    const ::hadoop::hdfs::DatanodeInfoProto & dn,
    const hadoop::common::TokenProto * token) {
  LOG_TRACE(kFileHandle, << "FileHandleImpl::CreateDataNodeConnection("
                         << FMT_THIS_ADDR << ", ...) called");
  return std::make_shared<DataNodeConnectionImpl>(io_service, dn, token, event_handlers_.get());
}

std::shared_ptr<LibhdfsEvents> FileHandleImpl::get_event_handlers() {
  return event_handlers_;
}

void FileHandleImpl::CancelOperations() {
  LOG_INFO(kFileHandle, << "FileHandleImpl::CancelOperations("
                        << FMT_THIS_ADDR << ") called");

  cancel_state_->set_canceled();

  /* Push update to BlockReaders that may be hung in an asio call */
  std::vector<std::shared_ptr<BlockReader>> live_readers = readers_.GetLiveReaders();
  for(auto reader : live_readers) {
    reader->CancelOperation();
  }
}

void FileHandleImpl::SetFileEventCallback(file_event_callback callback) {
  std::shared_ptr<LibhdfsEvents> new_event_handlers;
  if (event_handlers_) {
    new_event_handlers = std::make_shared<LibhdfsEvents>(*event_handlers_);
  } else {
    new_event_handlers = std::make_shared<LibhdfsEvents>();
  }
  new_event_handlers->set_file_callback(callback);
  event_handlers_ = new_event_handlers;
}

bool FileHandle::ShouldExclude(const Status &s) {
  if (s.ok()) {
    return false;
  }

  switch (s.code()) {
    /* client side resource exhaustion */
    case Status::kResourceUnavailable:
    case Status::kOperationCanceled:
      return false;
    case Status::kInvalidArgument:
    case Status::kUnimplemented:
    case Status::kException:
    default:
      return true;
  }
}

}
<commit_msg>HDFS-10543: libhdfs++: hdfsRead stops at block boundary.  Contributed by Xiaowei Zhu.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "filehandle.h"
#include "common/continuation/continuation.h"
#include "common/logging.h"
#include "connection/datanodeconnection.h"
#include "reader/block_reader.h"
#include "hdfspp/events.h"

#include <future>
#include <tuple>

#define FMT_THIS_ADDR "this=" << (void*)this

namespace hdfs {

using ::hadoop::hdfs::LocatedBlocksProto;

FileHandle::~FileHandle() {}

FileHandleImpl::FileHandleImpl(const std::string & cluster_name,
                               const std::string & path,
                               ::asio::io_service *io_service, const std::string &client_name,
                                 const std::shared_ptr<const struct FileInfo> file_info,
                                 std::shared_ptr<BadDataNodeTracker> bad_data_nodes,
                                 std::shared_ptr<LibhdfsEvents> event_handlers)
    : cluster_name_(cluster_name), path_(path), io_service_(io_service), client_name_(client_name), file_info_(file_info),
      bad_node_tracker_(bad_data_nodes), offset_(0), cancel_state_(CancelTracker::New()), event_handlers_(event_handlers) {
  LOG_TRACE(kFileHandle, << "FileHandleImpl::FileHandleImpl("
                         << FMT_THIS_ADDR << ", ...) called");

}

void FileHandleImpl::PositionRead(
    void *buf, size_t nbyte, uint64_t offset,
    const std::function<void(const Status &, size_t)> &handler) {
  LOG_TRACE(kFileHandle, << "FileHandleImpl::PositionRead("
                         << FMT_THIS_ADDR << ", buf=" << buf
                         << ", nbyte=" << nbyte << ") called");

  /* prevent usage after cancelation */
  if(cancel_state_->is_canceled()) {
    handler(Status::Canceled(), 0);
    return;
  }

  auto callback = [this, handler](const Status &status,
                                  const std::string &contacted_datanode,
                                  size_t bytes_read) {
    /* determine if DN gets marked bad */
    if (ShouldExclude(status)) {
      bad_node_tracker_->AddBadNode(contacted_datanode);
    }

    handler(status, bytes_read);
  };

  AsyncPreadSome(offset, asio::buffer(buf, nbyte), bad_node_tracker_, callback);
}

Status FileHandleImpl::PositionRead(void *buf, size_t *nbyte, off_t offset) {
  LOG_TRACE(kFileHandle, << "FileHandleImpl::[sync]PositionRead("
                         << FMT_THIS_ADDR << ", buf=" << buf
                         << ", nbyte=" << *nbyte << ") called");
  size_t totalBytesRead = 0;
  Status stat = Status::OK();
  while (*nbyte != 0 && offset < (off_t)(file_info_->file_length_)) {
    auto callstate = std::make_shared<std::promise<std::tuple<Status, size_t>>>();
    std::future<std::tuple<Status, size_t>> future(callstate->get_future());

    /* wrap async call with promise/future to make it blocking */
    auto callback = [callstate](const Status &s, size_t bytes) {
      callstate->set_value(std::make_tuple(s,bytes));
    };

    PositionRead(buf, *nbyte, offset, callback);

    /* wait for async to finish */
    auto returnstate = future.get();
    stat = std::get<0>(returnstate);

    if (!stat.ok()) {
      return stat;
    }

    size_t bytesRead = std::get<1>(returnstate);
    *nbyte = *nbyte - bytesRead;
    totalBytesRead += bytesRead;
    offset += bytesRead;
  }
  /* Update the bytes read for return */
  *nbyte = totalBytesRead;
  return stat;
}

Status FileHandleImpl::Read(void *buf, size_t *nbyte) {
  LOG_TRACE(kFileHandle, << "FileHandleImpl::Read("
                         << FMT_THIS_ADDR << ", buf=" << buf
                         << ", nbyte=" << *nbyte << ") called");

  Status stat = PositionRead(buf, nbyte, offset_);
  if(!stat.ok()) {
    return stat;
  }
  offset_ += *nbyte;

  return Status::OK();
}

Status FileHandleImpl::Seek(off_t *offset, std::ios_base::seekdir whence) {
  LOG_TRACE(kFileHandle, << "FileHandleImpl::Seek("
                         << ", offset=" << *offset << ", ...) called");

  if(cancel_state_->is_canceled()) {
    return Status::Canceled();
  }

  off_t new_offset = -1;

  switch (whence) {
    case std::ios_base::beg:
      new_offset = *offset;
      break;
    case std::ios_base::cur:
      new_offset = offset_ + *offset;
      break;
    case std::ios_base::end:
      new_offset = file_info_->file_length_ + *offset;
      break;
    default:
      /* unsupported */
      return Status::InvalidArgument("Invalid Seek whence argument");
  }

  if(!CheckSeekBounds(new_offset)) {
    return Status::InvalidArgument("Seek offset out of bounds");
  }
  offset_ = new_offset;

  *offset = offset_;
  return Status::OK();
}

/* return false if seek will be out of bounds */
bool FileHandleImpl::CheckSeekBounds(ssize_t desired_position) {
  ssize_t file_length = file_info_->file_length_;

  if (desired_position < 0 || desired_position > file_length) {
    return false;
  }

  return true;
}

/*
 * Note that this method must be thread-safe w.r.t. the unsafe operations occurring
 * on the FileHandle
 */
void FileHandleImpl::AsyncPreadSome(
    size_t offset, const MutableBuffers &buffers,
    std::shared_ptr<NodeExclusionRule> excluded_nodes,
    const std::function<void(const Status &, const std::string &, size_t)> handler) {
  using ::hadoop::hdfs::DatanodeInfoProto;
  using ::hadoop::hdfs::LocatedBlockProto;

  LOG_TRACE(kFileHandle, << "FileHandleImpl::AsyncPreadSome("
                         << FMT_THIS_ADDR << ", ...) called");

  if(cancel_state_->is_canceled()) {
    handler(Status::Canceled(), "", 0);
    return;
  }

  /**
   *  Note: block and chosen_dn will end up pointing to things inside
   *  the blocks_ vector.  They shouldn't be directly deleted.
   **/
  auto block = std::find_if(
      file_info_->blocks_.begin(), file_info_->blocks_.end(), [offset](const LocatedBlockProto &p) {
        return p.offset() <= offset && offset < p.offset() + p.b().numbytes();
      });

  if (block == file_info_->blocks_.end()) {
    LOG_WARN(kFileHandle, << "FileHandleImpl::AsyncPreadSome(" << FMT_THIS_ADDR
                          << ", ...) Cannot find corresponding blocks");
    handler(Status::InvalidArgument("Cannot find corresponding blocks"), "", 0);
    return;
  }

  /**
   * If user supplies a rule use it, otherwise use the tracker.
   * User is responsible for making sure one of them isn't null.
   **/
  std::shared_ptr<NodeExclusionRule> rule =
      excluded_nodes != nullptr ? excluded_nodes : bad_node_tracker_;

  auto datanodes = block->locs();
  auto it = std::find_if(datanodes.begin(), datanodes.end(),
                         [rule](const DatanodeInfoProto &dn) {
                           return !rule->IsBadNode(dn.id().datanodeuuid());
                         });

  if (it == datanodes.end()) {
    LOG_WARN(kFileHandle, << "FileHandleImpl::AsyncPreadSome("
                          << FMT_THIS_ADDR << ", ...) No datanodes available");

    handler(Status::ResourceUnavailable("No datanodes available"), "", 0);
    return;
  }

  DatanodeInfoProto &chosen_dn = *it;

  uint64_t offset_within_block = offset - block->offset();
  uint64_t size_within_block = std::min<uint64_t>(
      block->b().numbytes() - offset_within_block, asio::buffer_size(buffers));

  // This is where we will put the logic for re-using a DN connection; we can
  //    steal the FileHandle's dn and put it back when we're done
  std::shared_ptr<DataNodeConnection> dn = CreateDataNodeConnection(io_service_, chosen_dn, &block->blocktoken());
  std::string dn_id = dn->uuid_;
  std::string client_name = client_name_;

  // Wrap the DN in a block reader to handle the state and logic of the
  //    block request protocol
  std::shared_ptr<BlockReader> reader;
  reader = CreateBlockReader(BlockReaderOptions(), dn);

  // Lambdas cannot capture copies of member variables so we'll make explicit
  //    copies for it
  auto event_handlers = event_handlers_;
  auto path = path_;
  auto cluster_name = cluster_name_;

  auto read_handler = [reader, event_handlers, cluster_name, path, dn_id, handler](const Status & status, size_t transferred) {
    auto event_resp = event_handlers->call(FILE_DN_READ_EVENT, cluster_name.c_str(), path.c_str(), transferred);
#ifndef NDEBUG
    if (event_resp.response() == event_response::kTest_Error) {
      handler(event_resp.status(), dn_id, transferred);
      return;
    }
#endif

    handler(status, dn_id, transferred);
  };

  auto connect_handler = [handler,event_handlers,cluster_name,path,read_handler,block,offset_within_block,size_within_block, buffers, reader, dn_id, client_name]
          (Status status, std::shared_ptr<DataNodeConnection> dn) {
    (void)dn;
    auto event_resp = event_handlers->call(FILE_DN_CONNECT_EVENT, cluster_name.c_str(), path.c_str(), 0);
#ifndef NDEBUG
    if (event_resp.response() == event_response::kTest_Error) {
      status = event_resp.status();
    }
#endif

    if (status.ok()) {
      reader->AsyncReadBlock(
          client_name, *block, offset_within_block,
          asio::buffer(buffers, size_within_block), read_handler);
    } else {
      handler(status, dn_id, 0);
    }
  };

  dn->Connect(connect_handler);

  return;
}

std::shared_ptr<BlockReader> FileHandleImpl::CreateBlockReader(const BlockReaderOptions &options,
                                               std::shared_ptr<DataNodeConnection> dn)
{
  std::shared_ptr<BlockReader> reader = std::make_shared<BlockReaderImpl>(options, dn, cancel_state_);

  LOG_TRACE(kFileHandle, << "FileHandleImpl::CreateBlockReader(" << FMT_THIS_ADDR
                         << ", ..., dnconn=" << dn.get()
                         << ") called.  New BlockReader = " << reader.get());

  readers_.AddReader(reader);
  return reader;
}

std::shared_ptr<DataNodeConnection> FileHandleImpl::CreateDataNodeConnection(
    ::asio::io_service * io_service,
    const ::hadoop::hdfs::DatanodeInfoProto & dn,
    const hadoop::common::TokenProto * token) {
  LOG_TRACE(kFileHandle, << "FileHandleImpl::CreateDataNodeConnection("
                         << FMT_THIS_ADDR << ", ...) called");
  return std::make_shared<DataNodeConnectionImpl>(io_service, dn, token, event_handlers_.get());
}

std::shared_ptr<LibhdfsEvents> FileHandleImpl::get_event_handlers() {
  return event_handlers_;
}

void FileHandleImpl::CancelOperations() {
  LOG_INFO(kFileHandle, << "FileHandleImpl::CancelOperations("
                        << FMT_THIS_ADDR << ") called");

  cancel_state_->set_canceled();

  /* Push update to BlockReaders that may be hung in an asio call */
  std::vector<std::shared_ptr<BlockReader>> live_readers = readers_.GetLiveReaders();
  for(auto reader : live_readers) {
    reader->CancelOperation();
  }
}

void FileHandleImpl::SetFileEventCallback(file_event_callback callback) {
  std::shared_ptr<LibhdfsEvents> new_event_handlers;
  if (event_handlers_) {
    new_event_handlers = std::make_shared<LibhdfsEvents>(*event_handlers_);
  } else {
    new_event_handlers = std::make_shared<LibhdfsEvents>();
  }
  new_event_handlers->set_file_callback(callback);
  event_handlers_ = new_event_handlers;
}

bool FileHandle::ShouldExclude(const Status &s) {
  if (s.ok()) {
    return false;
  }

  switch (s.code()) {
    /* client side resource exhaustion */
    case Status::kResourceUnavailable:
    case Status::kOperationCanceled:
      return false;
    case Status::kInvalidArgument:
    case Status::kUnimplemented:
    case Status::kException:
    default:
      return true;
  }
}

}
<|endoftext|>


<commit_before><commit_msg>add a OpenGLContext to unix backend<commit_after><|endoftext|>