<commit_before>/**
 * @file
 *
 * @brief Contains the @ref cuda::rtc::program_t class and related code.
 */
#pragma once
#ifndef CUDA_API_WRAPPERS_NVRTC_PROGRAM_HPP_
#define CUDA_API_WRAPPERS_NVRTC_PROGRAM_HPP_

#include <cuda/nvrtc/compilation_options.hpp>
#include <cuda/nvrtc/compilation_output.hpp>
#include <cuda/nvrtc/error.hpp>
#include <cuda/nvrtc/types.hpp>
#include <cuda/api.hpp>

#include <vector>
#include <iostream>

namespace cuda {

namespace rtc {

using const_cstrings_span = span<const char* const>;
using const_cstring_pairs_span = span<::std::pair<const char* const, const char* const>>;

class program_t;

namespace detail_ {

::std::string identify(const program_t &program);

} // namespace detail_

namespace program {

namespace detail_ {

inline program::handle_t create(
	const char *program_name,
	const char *program_source,
	int num_headers,
	const char *const *header_sources,
	const char *const *header_names)
{
	program::handle_t program_handle;
	auto status = nvrtcCreateProgram(
		&program_handle, program_source, program_name, (int) num_headers, header_sources, header_names);
	throw_if_error(status, "Failed creating an NVRTC program (named " + ::std::string(program_name) + ')');
	return program_handle;
}

inline void register_global(handle_t program_handle, const char *global_to_register)
{
	auto status = nvrtcAddNameExpression(program_handle, global_to_register);
	throw_if_error(status, "Failed registering global entity " + ::std::string(global_to_register)
		+ " with " + identify(program_handle));
}

inline compilation_output_t compile(
	const char *                program_name,
	const const_cstrings_span & raw_options,
	handle_t                    program_handle)
{
	auto status = nvrtcCompileProgram(program_handle, (int) raw_options.size(), raw_options.data());
	bool succeeded = (status == status::named_t::success);
	if (not (succeeded or status == status::named_t::compilation_failure)) {
		throw rtc::runtime_error(status, "Failed invoking compiler for " + identify(program_handle));
	}
	constexpr bool do_own_handle{true};
	return compilation_output::detail_::wrap(program_handle, program_name, succeeded, do_own_handle);
}

// Note: The program_source _cannot_ be nullptr; if all of your source code is preincluded headers,
// pas the address of an empty string.
inline compilation_output_t compile(
	const char *program_name,
	const char *program_source,
	const_cstrings_span header_sources,
	const_cstrings_span header_names,
	const_cstrings_span raw_options,
	const_cstrings_span globals_to_register)
{
	assert(header_names.size() <= ::std::numeric_limits<int>::max());
	if (program_name == nullptr or *program_name == '\0') {
		throw ::std::invalid_argument("Attempt to compile a CUDA program without specifying a name");
	}
	// Note: Not rejecting empty/missing source, because we may be pre-including source files
	auto num_headers = (int) header_names.size();
	auto program_handle = create(
		program_name, program_source, num_headers, header_sources.data(), header_names.data());

	for (const auto global_to_register: globals_to_register) {
		register_global(program_handle, global_to_register);
	}

	// Note: compilation is outside of any context
	return compile(program_name, raw_options, program_handle);
}

} // namespace detail_

} // namespace program

/**
 * Wrapper class for a CUDA runtime-compilable program
 *
 * @note This class is a "reference type", not a "value type". Therefore, making changes
 * to the program is a const-respecting operation on this class.
 */
class program_t {

public: // getters

	const ::std::string& name() const { return name_; }
	const char* source() const { return source_; }
	const compilation_options_t& options() const { return options_; }
	// TODO: Think of a way to set compilation options without having
	// to break the statement, e.g. if options had a reflected enum value
	// or some such arrangement.
	compilation_options_t& options() { return options_; }
	const_cstrings_span header_names() const
	{
		return { headers_.names.data(), headers_.names.size()};
	}
	const_cstrings_span header_sources() const
	{
		return { headers_.sources.data(), headers_.sources.size()};
	}
	size_t num_headers() const { return headers_.sources.size(); }

public: // setters

	program_t& set_target(device::compute_capability_t target_compute_capability)
	{
		options_.set_target(target_compute_capability);
		return *this;
	}
	program_t& set_target(const device_t& device) { return set_target(device.compute_capability());}
	program_t& set_target(const context_t& context) { return set_target(context.device()); }
	program_t& clear_targets() { options_.targets_.clear(); return *this; }
	template <typename Container>
	program_t& set_targets(Container target_compute_capabilities)
	{
		clear_targets();
		for(const auto& compute_capability : target_compute_capabilities) {
			options_.add_target(compute_capability);
		}
		return *this;
	}
	program_t& add_target(device::compute_capability_t target_compute_capability)
	{
		options_.add_target(target_compute_capability);
		return *this;
	}
	void add_target(const device_t& device) { add_target(device.compute_capability()); }
	void add_target(const context_t& context) { add_target(context.device()); }

	program_t& set_source(const char* source) { source_ = source; return *this; }
	program_t& set_source(const ::std::string& source) { source_ = source.c_str(); return *this; }
	program_t& set_options(compilation_options_t options)
	{
		options_ = ::std::move(options);
		return *this;
	}

	template <typename HeaderNamesFwdIter, typename HeaderSourcesFwdIter>
	inline program_t& add_headers(
		HeaderNamesFwdIter header_names_start,
		HeaderNamesFwdIter header_names_end,
		HeaderSourcesFwdIter header_sources_start)
	{
		auto num_headers_to_add = header_names_end - header_names_start;
		auto new_num_headers = headers_.names.size() + num_headers_to_add;
#ifndef NDEBUG
		if (new_num_headers > ::std::numeric_limits<int>::max()) {
			throw ::std::invalid_argument("Cannot use more than "
										  + ::std::to_string(::std::numeric_limits<int>::max()) + " headers.");
		}
#endif
		headers_.names.reserve(new_num_headers);
		::std::copy_n(header_names_start, new_num_headers, ::std::back_inserter(headers_.names));
		headers_.sources.reserve(new_num_headers);
		::std::copy_n(header_sources_start, new_num_headers, ::std::back_inserter(headers_.sources));
		return *this;
	}

	template <typename HeaderNameAndSourceFwdIter>
	inline program_t& add_headers(
		HeaderNameAndSourceFwdIter named_headers_start,
		HeaderNameAndSourceFwdIter named_headers_end)
	{
		auto num_headers_to_add = named_headers_end - named_headers_start;
		auto new_num_headers = headers_.names.size() + num_headers_to_add;
#ifndef NDEBUG
		if (new_num_headers > ::std::numeric_limits<int>::max()) {
			throw ::std::invalid_argument("Cannot use more than "
										  + ::std::to_string(::std::numeric_limits<int>::max()) + " headers.");
		}
#endif
		headers_.names.reserve(new_num_headers);
		headers_.sources.reserve(new_num_headers);
		for(auto& pair_it = named_headers_start; pair_it < named_headers_end; pair_it++) {
			headers_.names.push_back(pair_it->first);
			headers_.sources.push_back(pair_it->second);
		}
		return *this;
	}

	const program_t& add_headers(
		const_cstrings_span header_names,
		const_cstrings_span header_sources)
	{
#ifndef NDEBUG
		if (header_names.size() != header_sources.size()) {
			throw ::std::invalid_argument(
				"Got " + ::std::to_string(header_names.size()) + " header names with "
				+ ::std::to_string(header_sources.size()));
		}
#endif
		return add_headers(header_names.cbegin(), header_names.cend(), header_sources.cbegin());
	}

	template <typename ContainerOfCStringPairs>
	program_t& add_headers(ContainerOfCStringPairs named_header_pairs)
	{
		return add_headers(::std::begin(named_header_pairs), ::std::end(named_header_pairs));
	}

	template <typename HeaderNamesFwdIter, typename HeaderSourcesFwdIter>
	program_t& set_headers(
		HeaderNamesFwdIter header_names_start,
		HeaderNamesFwdIter header_names_end,
		HeaderSourcesFwdIter header_sources_start)
	{
		clear_headers();
		return add_headers(header_names_start, header_names_end, header_sources_start);
	}

	program_t& set_headers(
		const_cstrings_span header_names,
		const_cstrings_span header_sources)
	{
#ifndef NDEBUG
		if (header_names.size() != header_sources.size()) {
			throw ::std::invalid_argument(
				"Got " + ::std::to_string(header_names.size()) + " header names with "
				+ ::std::to_string(header_sources.size()));
		}
#endif
		return set_headers(header_names.cbegin(), header_names.cend(), header_sources.cbegin());
	}

	template <typename ContainerOfCStringPairs>
	program_t& set_headers(ContainerOfCStringPairs named_header_pairs)
	{
		clear_headers();
		return add_headers(named_header_pairs);
	}

	program_t& clear_headers()
	{
		headers_.names.clear();
		headers_.sources.clear();
		return *this;
	}

	program_t& clear_options() { options_ = {}; return *this; }

public:

	// TODO: Support specifying all compilation option in a single string and parsing it

	compilation_output_t compile() const
	{
		if ((source_ == nullptr or *source_ == '\0') and options_.preinclude_files.empty()) {
			throw ::std::invalid_argument("Attempt to compile a CUDA program without any source code");
		}
		auto marshalled_options = marshal(options_);
		::std::vector<const char*> option_ptrs = marshalled_options.option_ptrs();
		return program::detail_::compile(
			name_.c_str(),
			source_ == nullptr ? "" : source_,
			{headers_.sources.data(), headers_.sources.size()},
			{headers_.names.data(), headers_.names.size()},
			{option_ptrs.data(), option_ptrs.size()},
			{globals_to_register_.data(), globals_to_register_.size()});
	}

	/**
	 * @brief Register a pre-mangled name of a kernel, to make available for use
	 * after compilation
	 *
	 * @param name The text of an expression, e.g. "my_global_func()", "f1", "N1::N2::n2",
	 *
	 */
	program_t& add_registered_global(const char* unmangled_name)
	{
		globals_to_register_.push_back(unmangled_name);
		return *this;
	}
	program_t& add_registered_global(const ::std::string& unmangled_name)
	{
		globals_to_register_.push_back(unmangled_name.c_str());
		return *this;
	}

	template <typename Container>
	program_t& add_registered_globals(Container&& globals_to_register)
	{
		globals_to_register_.reserve(globals_to_register_.size() + globals_to_register.size());
		::std::copy(globals_to_register.cbegin(), globals_to_register.cend(), ::std::back_inserter(globals_to_register_));
		return *this;
	}

public: // constructors and destructor
	program_t(::std::string name) : name_(::std::move(name)) {};
	program_t(const program_t&) = default;
	program_t(program_t&&) = default;
	~program_t() = default;

public: // operators

	program_t& operator=(const program_t& other) = default;
	program_t& operator=(program_t&& other) = default;

protected: // data members
	const char*           source_ { nullptr };
	::std::string         name_;
	compilation_options_t options_;
	struct {
		::std::vector<const char*> names;
		::std::vector<const char*> sources;
	} headers_;
	::std::vector<const char*> globals_to_register_;
}; // class program_t

namespace program {

inline program_t create(const char* program_name)
{
	return program_t(program_name);
}

inline program_t create(const ::std::string program_name)
{
	return program_t(program_name);
}

} // namespace program

#if CUDA_VERSION >= 11020
inline dynarray<device::compute_capability_t>
supported_targets()
{
	int num_supported_archs;
	auto status = nvrtcGetNumSupportedArchs(&num_supported_archs);
	throw_if_error(status, "Failed obtaining the number of target NVRTC architectures");
	auto raw_archs = ::std::unique_ptr<int[]>(new int[num_supported_archs]);
	status = nvrtcGetSupportedArchs(raw_archs.get());
	throw_if_error(status, "Failed obtaining the architectures supported by NVRTC");
	dynarray<device::compute_capability_t> result;
	result.reserve(num_supported_archs);
	::std::transform(raw_archs.get(), raw_archs.get() + num_supported_archs, ::std::back_inserter(result),
		[](int raw_arch) { return device::compute_capability_t::from_combined_number(raw_arch); });
	return result;
}
#endif

} // namespace rtc

} // namespace cuda

#endif // CUDA_API_WRAPPERS_NVRTC_PROGRAM_HPP_
<commit_msg>Drop unnecessary inclusion of `<iostream>` for NVRTC programs.<commit_after>/**
 * @file
 *
 * @brief Contains the @ref cuda::rtc::program_t class and related code.
 */
#pragma once
#ifndef CUDA_API_WRAPPERS_NVRTC_PROGRAM_HPP_
#define CUDA_API_WRAPPERS_NVRTC_PROGRAM_HPP_

#include <cuda/nvrtc/compilation_options.hpp>
#include <cuda/nvrtc/compilation_output.hpp>
#include <cuda/nvrtc/error.hpp>
#include <cuda/nvrtc/types.hpp>
#include <cuda/api.hpp>

#include <vector>

namespace cuda {

namespace rtc {

using const_cstrings_span = span<const char* const>;
using const_cstring_pairs_span = span<::std::pair<const char* const, const char* const>>;

class program_t;

namespace detail_ {

::std::string identify(const program_t &program);

} // namespace detail_

namespace program {

namespace detail_ {

inline program::handle_t create(
	const char *program_name,
	const char *program_source,
	int num_headers,
	const char *const *header_sources,
	const char *const *header_names)
{
	program::handle_t program_handle;
	auto status = nvrtcCreateProgram(
		&program_handle, program_source, program_name, (int) num_headers, header_sources, header_names);
	throw_if_error(status, "Failed creating an NVRTC program (named " + ::std::string(program_name) + ')');
	return program_handle;
}

inline void register_global(handle_t program_handle, const char *global_to_register)
{
	auto status = nvrtcAddNameExpression(program_handle, global_to_register);
	throw_if_error(status, "Failed registering global entity " + ::std::string(global_to_register)
		+ " with " + identify(program_handle));
}

inline compilation_output_t compile(
	const char *                program_name,
	const const_cstrings_span & raw_options,
	handle_t                    program_handle)
{
	auto status = nvrtcCompileProgram(program_handle, (int) raw_options.size(), raw_options.data());
	bool succeeded = (status == status::named_t::success);
	if (not (succeeded or status == status::named_t::compilation_failure)) {
		throw rtc::runtime_error(status, "Failed invoking compiler for " + identify(program_handle));
	}
	constexpr bool do_own_handle{true};
	return compilation_output::detail_::wrap(program_handle, program_name, succeeded, do_own_handle);
}

// Note: The program_source _cannot_ be nullptr; if all of your source code is preincluded headers,
// pas the address of an empty string.
inline compilation_output_t compile(
	const char *program_name,
	const char *program_source,
	const_cstrings_span header_sources,
	const_cstrings_span header_names,
	const_cstrings_span raw_options,
	const_cstrings_span globals_to_register)
{
	assert(header_names.size() <= ::std::numeric_limits<int>::max());
	if (program_name == nullptr or *program_name == '\0') {
		throw ::std::invalid_argument("Attempt to compile a CUDA program without specifying a name");
	}
	// Note: Not rejecting empty/missing source, because we may be pre-including source files
	auto num_headers = (int) header_names.size();
	auto program_handle = create(
		program_name, program_source, num_headers, header_sources.data(), header_names.data());

	for (const auto global_to_register: globals_to_register) {
		register_global(program_handle, global_to_register);
	}

	// Note: compilation is outside of any context
	return compile(program_name, raw_options, program_handle);
}

} // namespace detail_

} // namespace program

/**
 * Wrapper class for a CUDA runtime-compilable program
 *
 * @note This class is a "reference type", not a "value type". Therefore, making changes
 * to the program is a const-respecting operation on this class.
 */
class program_t {

public: // getters

	const ::std::string& name() const { return name_; }
	const char* source() const { return source_; }
	const compilation_options_t& options() const { return options_; }
	// TODO: Think of a way to set compilation options without having
	// to break the statement, e.g. if options had a reflected enum value
	// or some such arrangement.
	compilation_options_t& options() { return options_; }
	const_cstrings_span header_names() const
	{
		return { headers_.names.data(), headers_.names.size()};
	}
	const_cstrings_span header_sources() const
	{
		return { headers_.sources.data(), headers_.sources.size()};
	}
	size_t num_headers() const { return headers_.sources.size(); }

public: // setters

	program_t& set_target(device::compute_capability_t target_compute_capability)
	{
		options_.set_target(target_compute_capability);
		return *this;
	}
	program_t& set_target(const device_t& device) { return set_target(device.compute_capability());}
	program_t& set_target(const context_t& context) { return set_target(context.device()); }
	program_t& clear_targets() { options_.targets_.clear(); return *this; }
	template <typename Container>
	program_t& set_targets(Container target_compute_capabilities)
	{
		clear_targets();
		for(const auto& compute_capability : target_compute_capabilities) {
			options_.add_target(compute_capability);
		}
		return *this;
	}
	program_t& add_target(device::compute_capability_t target_compute_capability)
	{
		options_.add_target(target_compute_capability);
		return *this;
	}
	void add_target(const device_t& device) { add_target(device.compute_capability()); }
	void add_target(const context_t& context) { add_target(context.device()); }

	program_t& set_source(const char* source) { source_ = source; return *this; }
	program_t& set_source(const ::std::string& source) { source_ = source.c_str(); return *this; }
	program_t& set_options(compilation_options_t options)
	{
		options_ = ::std::move(options);
		return *this;
	}

	template <typename HeaderNamesFwdIter, typename HeaderSourcesFwdIter>
	inline program_t& add_headers(
		HeaderNamesFwdIter header_names_start,
		HeaderNamesFwdIter header_names_end,
		HeaderSourcesFwdIter header_sources_start)
	{
		auto num_headers_to_add = header_names_end - header_names_start;
		auto new_num_headers = headers_.names.size() + num_headers_to_add;
#ifndef NDEBUG
		if (new_num_headers > ::std::numeric_limits<int>::max()) {
			throw ::std::invalid_argument("Cannot use more than "
										  + ::std::to_string(::std::numeric_limits<int>::max()) + " headers.");
		}
#endif
		headers_.names.reserve(new_num_headers);
		::std::copy_n(header_names_start, new_num_headers, ::std::back_inserter(headers_.names));
		headers_.sources.reserve(new_num_headers);
		::std::copy_n(header_sources_start, new_num_headers, ::std::back_inserter(headers_.sources));
		return *this;
	}

	template <typename HeaderNameAndSourceFwdIter>
	inline program_t& add_headers(
		HeaderNameAndSourceFwdIter named_headers_start,
		HeaderNameAndSourceFwdIter named_headers_end)
	{
		auto num_headers_to_add = named_headers_end - named_headers_start;
		auto new_num_headers = headers_.names.size() + num_headers_to_add;
#ifndef NDEBUG
		if (new_num_headers > ::std::numeric_limits<int>::max()) {
			throw ::std::invalid_argument("Cannot use more than "
										  + ::std::to_string(::std::numeric_limits<int>::max()) + " headers.");
		}
#endif
		headers_.names.reserve(new_num_headers);
		headers_.sources.reserve(new_num_headers);
		for(auto& pair_it = named_headers_start; pair_it < named_headers_end; pair_it++) {
			headers_.names.push_back(pair_it->first);
			headers_.sources.push_back(pair_it->second);
		}
		return *this;
	}

	const program_t& add_headers(
		const_cstrings_span header_names,
		const_cstrings_span header_sources)
	{
#ifndef NDEBUG
		if (header_names.size() != header_sources.size()) {
			throw ::std::invalid_argument(
				"Got " + ::std::to_string(header_names.size()) + " header names with "
				+ ::std::to_string(header_sources.size()));
		}
#endif
		return add_headers(header_names.cbegin(), header_names.cend(), header_sources.cbegin());
	}

	template <typename ContainerOfCStringPairs>
	program_t& add_headers(ContainerOfCStringPairs named_header_pairs)
	{
		return add_headers(::std::begin(named_header_pairs), ::std::end(named_header_pairs));
	}

	template <typename HeaderNamesFwdIter, typename HeaderSourcesFwdIter>
	program_t& set_headers(
		HeaderNamesFwdIter header_names_start,
		HeaderNamesFwdIter header_names_end,
		HeaderSourcesFwdIter header_sources_start)
	{
		clear_headers();
		return add_headers(header_names_start, header_names_end, header_sources_start);
	}

	program_t& set_headers(
		const_cstrings_span header_names,
		const_cstrings_span header_sources)
	{
#ifndef NDEBUG
		if (header_names.size() != header_sources.size()) {
			throw ::std::invalid_argument(
				"Got " + ::std::to_string(header_names.size()) + " header names with "
				+ ::std::to_string(header_sources.size()));
		}
#endif
		return set_headers(header_names.cbegin(), header_names.cend(), header_sources.cbegin());
	}

	template <typename ContainerOfCStringPairs>
	program_t& set_headers(ContainerOfCStringPairs named_header_pairs)
	{
		clear_headers();
		return add_headers(named_header_pairs);
	}

	program_t& clear_headers()
	{
		headers_.names.clear();
		headers_.sources.clear();
		return *this;
	}

	program_t& clear_options() { options_ = {}; return *this; }

public:

	// TODO: Support specifying all compilation option in a single string and parsing it

	compilation_output_t compile() const
	{
		if ((source_ == nullptr or *source_ == '\0') and options_.preinclude_files.empty()) {
			throw ::std::invalid_argument("Attempt to compile a CUDA program without any source code");
		}
		auto marshalled_options = marshal(options_);
		::std::vector<const char*> option_ptrs = marshalled_options.option_ptrs();
		return program::detail_::compile(
			name_.c_str(),
			source_ == nullptr ? "" : source_,
			{headers_.sources.data(), headers_.sources.size()},
			{headers_.names.data(), headers_.names.size()},
			{option_ptrs.data(), option_ptrs.size()},
			{globals_to_register_.data(), globals_to_register_.size()});
	}

	/**
	 * @brief Register a pre-mangled name of a kernel, to make available for use
	 * after compilation
	 *
	 * @param name The text of an expression, e.g. "my_global_func()", "f1", "N1::N2::n2",
	 *
	 */
	program_t& add_registered_global(const char* unmangled_name)
	{
		globals_to_register_.push_back(unmangled_name);
		return *this;
	}
	program_t& add_registered_global(const ::std::string& unmangled_name)
	{
		globals_to_register_.push_back(unmangled_name.c_str());
		return *this;
	}

	template <typename Container>
	program_t& add_registered_globals(Container&& globals_to_register)
	{
		globals_to_register_.reserve(globals_to_register_.size() + globals_to_register.size());
		::std::copy(globals_to_register.cbegin(), globals_to_register.cend(), ::std::back_inserter(globals_to_register_));
		return *this;
	}

public: // constructors and destructor
	program_t(::std::string name) : name_(::std::move(name)) {};
	program_t(const program_t&) = default;
	program_t(program_t&&) = default;
	~program_t() = default;

public: // operators

	program_t& operator=(const program_t& other) = default;
	program_t& operator=(program_t&& other) = default;

protected: // data members
	const char*           source_ { nullptr };
	::std::string         name_;
	compilation_options_t options_;
	struct {
		::std::vector<const char*> names;
		::std::vector<const char*> sources;
	} headers_;
	::std::vector<const char*> globals_to_register_;
}; // class program_t

namespace program {

inline program_t create(const char* program_name)
{
	return program_t(program_name);
}

inline program_t create(const ::std::string program_name)
{
	return program_t(program_name);
}

} // namespace program

#if CUDA_VERSION >= 11020
inline dynarray<device::compute_capability_t>
supported_targets()
{
	int num_supported_archs;
	auto status = nvrtcGetNumSupportedArchs(&num_supported_archs);
	throw_if_error(status, "Failed obtaining the number of target NVRTC architectures");
	auto raw_archs = ::std::unique_ptr<int[]>(new int[num_supported_archs]);
	status = nvrtcGetSupportedArchs(raw_archs.get());
	throw_if_error(status, "Failed obtaining the architectures supported by NVRTC");
	dynarray<device::compute_capability_t> result;
	result.reserve(num_supported_archs);
	::std::transform(raw_archs.get(), raw_archs.get() + num_supported_archs, ::std::back_inserter(result),
		[](int raw_arch) { return device::compute_capability_t::from_combined_number(raw_arch); });
	return result;
}
#endif

} // namespace rtc

} // namespace cuda

#endif // CUDA_API_WRAPPERS_NVRTC_PROGRAM_HPP_
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C $              */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

/** @file  prdfMemTdCtlr_ipl.C
 *  @brief A state machine for memory Targeted Diagnostics (IPL only).
 */

#include <prdfMemTdCtlr.H>

// Platform includes
#include <prdfMemEccAnalysis.H>
#include <prdfMemMark.H>
#include <prdfMemoryMru.H>
#include <prdfMemScrubUtils.H>
#include <prdfMemUtils.H>
#include <prdfMemVcm.H>
#include <prdfP9McaDataBundle.H>
#include <prdfP9McaExtraSig.H>
#include <UtilHash.H> // for Util::hashString

using namespace TARGETING;

namespace PRDF
{

using namespace PlatServices;

//------------------------------------------------------------------------------

template <TARGETING::TYPE T>
uint32_t MemTdCtlr<T>::handleTdEvent( STEP_CODE_DATA_STRUCT & io_sc,
                                      TdEntry * i_entry )
{
    #define PRDF_FUNC "[MemTdCtlr::handleTdEvent] "

    // Add this entry to the queue.
    iv_queue.push( i_entry );

    return SUCCESS;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

template <TARGETING::TYPE T>
uint32_t MemTdCtlr<T>::defaultStep( STEP_CODE_DATA_STRUCT & io_sc )
{
    #define PRDF_FUNC "[MemTdCtlr::defaultStep] "

    uint32_t o_rc = SUCCESS;

    TdRankListEntry nextRank = iv_rankList.getNext( iv_stoppedRank,
                                                    iv_broadcastMode );

    do
    {
        if ( nextRank <= iv_stoppedRank ) // The command made it to the end.
        {
            PRDF_TRAC( PRDF_FUNC "The TD command made it to the end of "
                       "memory on chip: 0x%08x", iv_chip->getHuid() );

            // Clear all of the counters and maintenance ECC attentions. This
            // must be done before telling MDIA the command is done. Otherwise,
            // we may run into a race condition where MDIA may start the next
            // command and it completes before PRD clears the FIR bits for this
            // attention.
            o_rc = prepareNextCmd<T>( iv_chip );
            if ( SUCCESS != o_rc )
            {
                PRDF_ERR( PRDF_FUNC "prepareNextCmd<T>(0x%08x) failed",
                          iv_chip->getHuid() );
                break;
            }

            // The command reached the end of memory. Send a message to MDIA.
            o_rc = mdiaSendEventMsg(iv_chip->getTrgt(), MDIA::COMMAND_COMPLETE);
            if ( SUCCESS != o_rc )
            {
                PRDF_ERR( PRDF_FUNC "mdiaSendEventMsg(0x%08x,COMMAND_COMPLETE) "
                          "failed", iv_chip->getHuid() );
                break;
            }
        }
        else // There is memory left to test.
        {
            PRDF_TRAC( PRDF_FUNC "There is still memory left to test. "
                       "Calling startSfRead<T>(0x%08x, m%ds%d)",
                       nextRank.getChip()->getHuid(),
                       nextRank.getRank().getMaster(),
                       nextRank.getRank().getSlave() );

            // Start a super fast command to the end of memory.
            o_rc = startSfRead<T>( nextRank.getChip(), nextRank.getRank() );
            if ( SUCCESS != o_rc )
            {
                PRDF_ERR( PRDF_FUNC "startSfRead<T>(0x%08x,m%ds%d) failed",
                          nextRank.getChip()->getHuid(),
                          nextRank.getRank().getMaster(),
                          nextRank.getRank().getSlave() );
                break;
            }
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

template <TARGETING::TYPE T, typename D>
uint32_t __checkEcc( ExtensibleChip * i_chip, TdQueue & io_queue,
                     const MemAddr & i_addr, bool & o_errorsFound,
                     STEP_CODE_DATA_STRUCT & io_sc )
{
    #define PRDF_FUNC "[__checkEcc] "

    uint32_t o_rc = SUCCESS;

    o_errorsFound = true; // Assume true for unless nothing found.

    TargetHandle_t trgt = i_chip->getTrgt();
    HUID           huid = i_chip->getHuid();

    MemRank rank = i_addr.getRank();

    do
    {
        // Check for ECC errors.
        uint32_t eccAttns = 0;
        o_rc = checkEccFirs<T>( i_chip, eccAttns );
        if ( SUCCESS != o_rc )
        {
            PRDF_ERR( PRDF_FUNC "checkEccFirs<T>(0x%08x) failed", huid );
            break;
        }

        if ( 0 != (eccAttns & MAINT_UE) )
        {
            // Add the signature to the multi-signature list. Also, since
            // this will be a predictive callout, change the primary
            // signature as well.
            io_sc.service_data->AddSignatureList( trgt, PRDFSIG_MaintUE );
            io_sc.service_data->setSignature(     huid, PRDFSIG_MaintUE );

            // Do memory UE handling.
            o_rc = MemEcc::handleMemUe<T>( i_chip, i_addr, UE_TABLE::SCRUB_UE,
                                           io_sc );
            if ( SUCCESS != o_rc )
            {
                PRDF_ERR( PRDF_FUNC "handleMemUe<T>(0x%08x) failed",
                          i_chip->getHuid() );
                break;
            }
        }
        else if ( 0 != (eccAttns & MAINT_MPE) )
        {
            io_sc.service_data->AddSignatureList( trgt, PRDFSIG_MaintMPE );

            // Read the chip mark from markstore.
            MemMark chipMark;
            o_rc = MarkStore::readChipMark<T>( i_chip, rank, chipMark );
            if ( SUCCESS != o_rc )
            {
                PRDF_ERR( PRDF_FUNC "readChipMark<T>(0x%08x,%d) failed",
                          huid, rank.getMaster() );
                break;
            }

            // If the chip mark is not valid, then somehow the chip mark was
            // placed on a rank other than the rank in which the command
            // stopped. This would most likely be a code bug.
            PRDF_ASSERT( chipMark.isValid() );

            // Add the mark to the callout list.
            MemoryMru mm { trgt, rank, chipMark.getSymbol() };
            io_sc.service_data->SetCallout( mm );

            // Add a new VCM procedure to the queue.
            TdEntry * e = new VcmEvent<T>{ i_chip, rank, chipMark };
            io_queue.push( e );
        }
        else if ( isMfgCeCheckingEnabled() &&
                  (0 != (eccAttns & MAINT_HARD_NCE_ETE)) )
        {
            io_sc.service_data->AddSignatureList( trgt, PRDFSIG_MaintHARD_CTE );

            // Query the per-symbol counters for the hard CE symbol.
            MemUtils::MaintSymbols symData; MemSymbol junk;
            o_rc = MemUtils::collectCeStats<T>( i_chip, rank, symData, junk );
            if ( SUCCESS != o_rc )
            {
                PRDF_ERR( PRDF_FUNC "MemUtils::collectCeStats(0x%08x,m%ds%d) "
                          "failed", i_chip->GetId(), rank.getMaster(),
                          rank.getSlave() );
                break;
            }

            // The command will have finished at the end of the rank so there
            // may be more than one symbol. Add all to the callout list.
            for ( auto & s : symData )
            {
                MemoryMru memmru ( trgt, rank, s.symbol );
                io_sc.service_data->SetCallout( memmru );
            }

            // Add a TPS procedure to the queue.
            TdEntry * e = new TpsEvent<T>{ i_chip, rank };
            io_queue.push( e );
        }
        else // Nothing found.
        {
            o_errorsFound = false;
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

template
uint32_t __checkEcc<TYPE_MCA, McaDataBundle *>( ExtensibleChip * i_chip,
                                                TdQueue & io_queue,
                                                const MemAddr & i_addr,
                                                bool & o_errorsFound,
                                                STEP_CODE_DATA_STRUCT & io_sc );

/* TODO RTC 157888
template
uint32_t __checkEcc<TYPE_MBA>( ExtensibleChip * i_chip, TdQueue & io_queue,
                               const MemAddr & i_addr, bool & o_errorsFound,
                               STEP_CODE_DATA_STRUCT & io_sc );
*/

//------------------------------------------------------------------------------

template <TARGETING::TYPE T>
void MemTdCtlr<T>::collectStateCaptureData( STEP_CODE_DATA_STRUCT & io_sc,
                                            const char * i_startEnd )
{
    #define PRDF_FUNC "[MemTdCtlr<T>::collectStateCaptureData] "

    // Get the number of entries in the TD queue (limit 15)
    TdQueue::Queue queue = iv_queue.getQueue();
    uint8_t queueCount = queue.size();
    if ( 15 < queueCount ) queueCount = 15;

    // Get the buffer
    uint32_t bitLen = 22 + queueCount*10; // Header + TD queue
    BitStringBuffer bsb( bitLen );
    uint32_t curPos = 0;

    //######################################################################
    // Header data (18 bits)
    //######################################################################

    // Specifies running at IPL. Also ensures our data is non-zero. 4-bit
    bsb.setFieldJustify( curPos, 4, TD_CTLR_DATA::Version::IPL ); curPos+=4;

    uint8_t mrnk  = 0;
    uint8_t srnk  = 0;
    uint8_t phase = TdEntry::Phase::TD_PHASE_0;
    uint8_t type  = TdEntry::TdType::INVALID_EVENT;

    if ( nullptr != iv_curProcedure )
    {
        mrnk  = iv_curProcedure->getRank().getMaster(); // 3-bit
        srnk  = iv_curProcedure->getRank().getSlave();  // 3-bit
        phase = iv_curProcedure->getPhase();            // 4-bit
        type  = iv_curProcedure->getType();             // 4-bit
    }

    bsb.setFieldJustify( curPos, 3, mrnk  ); curPos+=3;
    bsb.setFieldJustify( curPos, 3, srnk  ); curPos+=3;
    bsb.setFieldJustify( curPos, 4, phase ); curPos+=4;
    bsb.setFieldJustify( curPos, 4, type  ); curPos+=4;

    //######################################################################
    // TD Request Queue (min 4 bits, max 164 bits)
    //######################################################################

    bsb.setFieldJustify( curPos, 4, queueCount ); curPos+=4; // 4-bit

    for ( uint32_t n = 0; n < queueCount; n++ )
    {
        uint8_t itMrnk = queue[n]->getRank().getMaster(); // 3-bit
        uint8_t itSrnk = queue[n]->getRank().getSlave();  // 3-bit
        uint8_t itType = queue[n]->getType();             // 4-bit

        bsb.setFieldJustify( curPos, 3, itMrnk ); curPos+=3;
        bsb.setFieldJustify( curPos, 3, itSrnk ); curPos+=3;
        bsb.setFieldJustify( curPos, 4, itType ); curPos+=4;
    }

    //######################################################################
    // Add the capture data
    //######################################################################
    CaptureData & cd = io_sc.service_data->GetCaptureData();
    cd.Add( iv_chip->getTrgt(), Util::hashString(i_startEnd), bsb );

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

// Avoid linker errors with the template.
template class MemTdCtlr<TYPE_MCBIST>;
template class MemTdCtlr<TYPE_MBA>;

//------------------------------------------------------------------------------

} // end namespace PRDF

<commit_msg>PRD: hard CE callouts during Memory Diagnostics<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C $              */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

/** @file  prdfMemTdCtlr_ipl.C
 *  @brief A state machine for memory Targeted Diagnostics (IPL only).
 */

#include <prdfMemTdCtlr.H>

// Platform includes
#include <prdfMemEccAnalysis.H>
#include <prdfMemMark.H>
#include <prdfMemoryMru.H>
#include <prdfMemScrubUtils.H>
#include <prdfMemUtils.H>
#include <prdfMemVcm.H>
#include <prdfP9McaDataBundle.H>
#include <prdfP9McaExtraSig.H>
#include <UtilHash.H> // for Util::hashString

using namespace TARGETING;

namespace PRDF
{

using namespace PlatServices;

//------------------------------------------------------------------------------

template <TARGETING::TYPE T>
uint32_t MemTdCtlr<T>::handleTdEvent( STEP_CODE_DATA_STRUCT & io_sc,
                                      TdEntry * i_entry )
{
    #define PRDF_FUNC "[MemTdCtlr::handleTdEvent] "

    // Add this entry to the queue.
    iv_queue.push( i_entry );

    return SUCCESS;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

template <TARGETING::TYPE T>
uint32_t MemTdCtlr<T>::defaultStep( STEP_CODE_DATA_STRUCT & io_sc )
{
    #define PRDF_FUNC "[MemTdCtlr::defaultStep] "

    uint32_t o_rc = SUCCESS;

    TdRankListEntry nextRank = iv_rankList.getNext( iv_stoppedRank,
                                                    iv_broadcastMode );

    do
    {
        if ( nextRank <= iv_stoppedRank ) // The command made it to the end.
        {
            PRDF_TRAC( PRDF_FUNC "The TD command made it to the end of "
                       "memory on chip: 0x%08x", iv_chip->getHuid() );

            // Clear all of the counters and maintenance ECC attentions. This
            // must be done before telling MDIA the command is done. Otherwise,
            // we may run into a race condition where MDIA may start the next
            // command and it completes before PRD clears the FIR bits for this
            // attention.
            o_rc = prepareNextCmd<T>( iv_chip );
            if ( SUCCESS != o_rc )
            {
                PRDF_ERR( PRDF_FUNC "prepareNextCmd<T>(0x%08x) failed",
                          iv_chip->getHuid() );
                break;
            }

            // The command reached the end of memory. Send a message to MDIA.
            o_rc = mdiaSendEventMsg(iv_chip->getTrgt(), MDIA::COMMAND_COMPLETE);
            if ( SUCCESS != o_rc )
            {
                PRDF_ERR( PRDF_FUNC "mdiaSendEventMsg(0x%08x,COMMAND_COMPLETE) "
                          "failed", iv_chip->getHuid() );
                break;
            }
        }
        else // There is memory left to test.
        {
            PRDF_TRAC( PRDF_FUNC "There is still memory left to test. "
                       "Calling startSfRead<T>(0x%08x, m%ds%d)",
                       nextRank.getChip()->getHuid(),
                       nextRank.getRank().getMaster(),
                       nextRank.getRank().getSlave() );

            // Start a super fast command to the end of memory.
            o_rc = startSfRead<T>( nextRank.getChip(), nextRank.getRank() );
            if ( SUCCESS != o_rc )
            {
                PRDF_ERR( PRDF_FUNC "startSfRead<T>(0x%08x,m%ds%d) failed",
                          nextRank.getChip()->getHuid(),
                          nextRank.getRank().getMaster(),
                          nextRank.getRank().getSlave() );
                break;
            }
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

template <TARGETING::TYPE T, typename D>
uint32_t __checkEcc( ExtensibleChip * i_chip, TdQueue & io_queue,
                     const MemAddr & i_addr, bool & o_errorsFound,
                     STEP_CODE_DATA_STRUCT & io_sc )
{
    #define PRDF_FUNC "[__checkEcc] "

    uint32_t o_rc = SUCCESS;

    o_errorsFound = true; // Assume true for unless nothing found.

    TargetHandle_t trgt = i_chip->getTrgt();
    HUID           huid = i_chip->getHuid();

    MemRank rank = i_addr.getRank();

    do
    {
        // Check for ECC errors.
        uint32_t eccAttns = 0;
        o_rc = checkEccFirs<T>( i_chip, eccAttns );
        if ( SUCCESS != o_rc )
        {
            PRDF_ERR( PRDF_FUNC "checkEccFirs<T>(0x%08x) failed", huid );
            break;
        }

        if ( 0 != (eccAttns & MAINT_UE) )
        {
            // Add the signature to the multi-signature list. Also, since
            // this will be a predictive callout, change the primary
            // signature as well.
            io_sc.service_data->AddSignatureList( trgt, PRDFSIG_MaintUE );
            io_sc.service_data->setSignature(     huid, PRDFSIG_MaintUE );

            // Do memory UE handling.
            o_rc = MemEcc::handleMemUe<T>( i_chip, i_addr, UE_TABLE::SCRUB_UE,
                                           io_sc );
            if ( SUCCESS != o_rc )
            {
                PRDF_ERR( PRDF_FUNC "handleMemUe<T>(0x%08x) failed",
                          i_chip->getHuid() );
                break;
            }
        }
        else if ( 0 != (eccAttns & MAINT_MPE) )
        {
            io_sc.service_data->AddSignatureList( trgt, PRDFSIG_MaintMPE );

            // Read the chip mark from markstore.
            MemMark chipMark;
            o_rc = MarkStore::readChipMark<T>( i_chip, rank, chipMark );
            if ( SUCCESS != o_rc )
            {
                PRDF_ERR( PRDF_FUNC "readChipMark<T>(0x%08x,%d) failed",
                          huid, rank.getMaster() );
                break;
            }

            // If the chip mark is not valid, then somehow the chip mark was
            // placed on a rank other than the rank in which the command
            // stopped. This would most likely be a code bug.
            PRDF_ASSERT( chipMark.isValid() );

            // Add the mark to the callout list.
            MemoryMru mm { trgt, rank, chipMark.getSymbol() };
            io_sc.service_data->SetCallout( mm );

            // Add a new VCM procedure to the queue.
            TdEntry * e = new VcmEvent<T>{ i_chip, rank, chipMark };
            io_queue.push( e );
        }
        else if ( isMfgCeCheckingEnabled() &&
                  (0 != (eccAttns & MAINT_HARD_NCE_ETE)) )
        {
            io_sc.service_data->AddSignatureList( trgt, PRDFSIG_MaintHARD_CTE );

            // Query the per-symbol counters for hard CE symbols and make
            // callouts for each failing DIMM. Note that this function creates
            // new error logs for each DIMM with a hard CE.
            D db = static_cast<D>(i_chip->getDataBundle());
            o_rc = db->getIplCeStats()->calloutHardCes(rank);
            if ( SUCCESS != o_rc )
            {
                PRDF_ERR( PRDF_FUNC "calloutHardCes(0x%02x) failed",
                          rank.getKey() );
                break;
            }

            // Add a TPS procedure to the queue.
            TdEntry * e = new TpsEvent<T>{ i_chip, rank };
            io_queue.push( e );
        }
        else // Nothing found.
        {
            o_errorsFound = false;
        }

    } while (0);

    return o_rc;

    #undef PRDF_FUNC
}

template
uint32_t __checkEcc<TYPE_MCA, McaDataBundle *>( ExtensibleChip * i_chip,
                                                TdQueue & io_queue,
                                                const MemAddr & i_addr,
                                                bool & o_errorsFound,
                                                STEP_CODE_DATA_STRUCT & io_sc );

/* TODO RTC 157888
template
uint32_t __checkEcc<TYPE_MBA>( ExtensibleChip * i_chip, TdQueue & io_queue,
                               const MemAddr & i_addr, bool & o_errorsFound,
                               STEP_CODE_DATA_STRUCT & io_sc );
*/

//------------------------------------------------------------------------------

template <TARGETING::TYPE T>
void MemTdCtlr<T>::collectStateCaptureData( STEP_CODE_DATA_STRUCT & io_sc,
                                            const char * i_startEnd )
{
    #define PRDF_FUNC "[MemTdCtlr<T>::collectStateCaptureData] "

    // Get the number of entries in the TD queue (limit 15)
    TdQueue::Queue queue = iv_queue.getQueue();
    uint8_t queueCount = queue.size();
    if ( 15 < queueCount ) queueCount = 15;

    // Get the buffer
    uint32_t bitLen = 22 + queueCount*10; // Header + TD queue
    BitStringBuffer bsb( bitLen );
    uint32_t curPos = 0;

    //######################################################################
    // Header data (18 bits)
    //######################################################################

    // Specifies running at IPL. Also ensures our data is non-zero. 4-bit
    bsb.setFieldJustify( curPos, 4, TD_CTLR_DATA::Version::IPL ); curPos+=4;

    uint8_t mrnk  = 0;
    uint8_t srnk  = 0;
    uint8_t phase = TdEntry::Phase::TD_PHASE_0;
    uint8_t type  = TdEntry::TdType::INVALID_EVENT;

    if ( nullptr != iv_curProcedure )
    {
        mrnk  = iv_curProcedure->getRank().getMaster(); // 3-bit
        srnk  = iv_curProcedure->getRank().getSlave();  // 3-bit
        phase = iv_curProcedure->getPhase();            // 4-bit
        type  = iv_curProcedure->getType();             // 4-bit
    }

    bsb.setFieldJustify( curPos, 3, mrnk  ); curPos+=3;
    bsb.setFieldJustify( curPos, 3, srnk  ); curPos+=3;
    bsb.setFieldJustify( curPos, 4, phase ); curPos+=4;
    bsb.setFieldJustify( curPos, 4, type  ); curPos+=4;

    //######################################################################
    // TD Request Queue (min 4 bits, max 164 bits)
    //######################################################################

    bsb.setFieldJustify( curPos, 4, queueCount ); curPos+=4; // 4-bit

    for ( uint32_t n = 0; n < queueCount; n++ )
    {
        uint8_t itMrnk = queue[n]->getRank().getMaster(); // 3-bit
        uint8_t itSrnk = queue[n]->getRank().getSlave();  // 3-bit
        uint8_t itType = queue[n]->getType();             // 4-bit

        bsb.setFieldJustify( curPos, 3, itMrnk ); curPos+=3;
        bsb.setFieldJustify( curPos, 3, itSrnk ); curPos+=3;
        bsb.setFieldJustify( curPos, 4, itType ); curPos+=4;
    }

    //######################################################################
    // Add the capture data
    //######################################################################
    CaptureData & cd = io_sc.service_data->GetCaptureData();
    cd.Add( iv_chip->getTrgt(), Util::hashString(i_startEnd), bsb );

    #undef PRDF_FUNC
}

//------------------------------------------------------------------------------

// Avoid linker errors with the template.
template class MemTdCtlr<TYPE_MCBIST>;
template class MemTdCtlr<TYPE_MBA>;

//------------------------------------------------------------------------------

} // end namespace PRDF

<|endoftext|>


<commit_before>/*
 * Copyright 2003,2004 The Apache Software Foundation.
 *
 * 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.
 */

/*
 * $Id$
 */

#include <xercesc/framework/psvi/XSIDCDefinition.hpp>
#include <xercesc/validators/schema/identity/IC_KeyRef.hpp>
#include <xercesc/validators/schema/identity/IC_Selector.hpp>
#include <xercesc/validators/schema/identity/XercesXPath.hpp>
#include <xercesc/framework/psvi/XSModel.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/util/StringPool.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  XSIDCDefinition: Constructors and Destructor
// ---------------------------------------------------------------------------
XSIDCDefinition::XSIDCDefinition(IdentityConstraint* const identityConstraint,
                                 XSIDCDefinition*  const   keyIC,
                                 XSAnnotation* const       headAnnot,
                                 StringList* const         stringList,
                                 XSModel* const            xsModel,
                                 MemoryManager* const      manager)
    : XSObject(XSConstants::IDENTITY_CONSTRAINT, xsModel, manager)
    , fIdentityConstraint(identityConstraint)
    , fKey(keyIC)
    , fStringList(stringList)
    , fXSAnnotationList(0)
{
    if (headAnnot)
    {
        fXSAnnotationList = new (manager) RefVectorOf<XSAnnotation>(1, false, manager);

        XSAnnotation* annot = headAnnot;
        do
        {
            fXSAnnotationList->addElement(annot);
            annot = annot->getNext();
        } while (annot);
    }

}

XSIDCDefinition::~XSIDCDefinition()
{
    if (fStringList)
        delete fStringList;

    // don't delete fKey - deleted by XSModel
    if (fXSAnnotationList)
        delete fXSAnnotationList;
}

// ---------------------------------------------------------------------------
//  XSIDCDefinition: XSObject virtual methods
// ---------------------------------------------------------------------------
const XMLCh *XSIDCDefinition::getName()
{
    return fIdentityConstraint->getIdentityConstraintName();
}

const XMLCh *XSIDCDefinition::getNamespace()
{
    return fXSModel->getURIStringPool()->getValueForId(fIdentityConstraint->getNamespaceURI());
}

XSNamespaceItem *XSIDCDefinition::getNamespaceItem()
{
    return fXSModel->getNamespaceItem(getNamespace());
}

// ---------------------------------------------------------------------------
//  XSIDCDefinition: access methods
// ---------------------------------------------------------------------------
XSIDCDefinition::IC_CATEGORY XSIDCDefinition::getCategory() const
{
    switch(fIdentityConstraint->getType()) {
        case IdentityConstraint::UNIQUE:
            return IC_UNIQUE;
        case IdentityConstraint::KEY:
            return IC_KEY;
        case IdentityConstraint::KEYREF:
            return IC_KEYREF;
        default:
            // REVISIT:
            // should never really get here... IdentityConstraint::Unknown is the other
            // choice so need a default case for completeness; should issues error?
            return IC_KEY;
    }
}

const XMLCh *XSIDCDefinition::getSelectorStr()
{
    return fIdentityConstraint->getSelector()->getXPath()->getExpression();
}

XSAnnotationList *XSIDCDefinition::getAnnotations()
{
    return fXSAnnotationList;
}

XERCES_CPP_NAMESPACE_END

<commit_msg>Change uppercase enums that were conflicting with other products.<commit_after>/*
 * Copyright 2003,2004 The Apache Software Foundation.
 *
 * 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.
 */

/*
 * $Id$
 */

#include <xercesc/framework/psvi/XSIDCDefinition.hpp>
#include <xercesc/validators/schema/identity/IC_KeyRef.hpp>
#include <xercesc/validators/schema/identity/IC_Selector.hpp>
#include <xercesc/validators/schema/identity/XercesXPath.hpp>
#include <xercesc/framework/psvi/XSModel.hpp>
#include <xercesc/framework/psvi/XSAnnotation.hpp>
#include <xercesc/util/StringPool.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  XSIDCDefinition: Constructors and Destructor
// ---------------------------------------------------------------------------
XSIDCDefinition::XSIDCDefinition(IdentityConstraint* const identityConstraint,
                                 XSIDCDefinition*  const   keyIC,
                                 XSAnnotation* const       headAnnot,
                                 StringList* const         stringList,
                                 XSModel* const            xsModel,
                                 MemoryManager* const      manager)
    : XSObject(XSConstants::IDENTITY_CONSTRAINT, xsModel, manager)
    , fIdentityConstraint(identityConstraint)
    , fKey(keyIC)
    , fStringList(stringList)
    , fXSAnnotationList(0)
{
    if (headAnnot)
    {
        fXSAnnotationList = new (manager) RefVectorOf<XSAnnotation>(1, false, manager);

        XSAnnotation* annot = headAnnot;
        do
        {
            fXSAnnotationList->addElement(annot);
            annot = annot->getNext();
        } while (annot);
    }

}

XSIDCDefinition::~XSIDCDefinition()
{
    if (fStringList)
        delete fStringList;

    // don't delete fKey - deleted by XSModel
    if (fXSAnnotationList)
        delete fXSAnnotationList;
}

// ---------------------------------------------------------------------------
//  XSIDCDefinition: XSObject virtual methods
// ---------------------------------------------------------------------------
const XMLCh *XSIDCDefinition::getName()
{
    return fIdentityConstraint->getIdentityConstraintName();
}

const XMLCh *XSIDCDefinition::getNamespace()
{
    return fXSModel->getURIStringPool()->getValueForId(fIdentityConstraint->getNamespaceURI());
}

XSNamespaceItem *XSIDCDefinition::getNamespaceItem()
{
    return fXSModel->getNamespaceItem(getNamespace());
}

// ---------------------------------------------------------------------------
//  XSIDCDefinition: access methods
// ---------------------------------------------------------------------------
XSIDCDefinition::IC_CATEGORY XSIDCDefinition::getCategory() const
{
    switch(fIdentityConstraint->getType()) {
        case IdentityConstraint::ICType_UNIQUE:
            return IC_UNIQUE;
        case IdentityConstraint::ICType_KEY:
            return IC_KEY;
        case IdentityConstraint::ICType_KEYREF:
            return IC_KEYREF;
        default:
            // REVISIT:
            // should never really get here... IdentityConstraint::Unknown is the other
            // choice so need a default case for completeness; should issues error?
            return IC_KEY;
    }
}

const XMLCh *XSIDCDefinition::getSelectorStr()
{
    return fIdentityConstraint->getSelector()->getXPath()->getExpression();
}

XSAnnotationList *XSIDCDefinition::getAnnotations()
{
    return fXSAnnotationList;
}

XERCES_CPP_NAMESPACE_END

<|endoftext|>


<commit_before>/*
 The MIT License (MIT)

 Copyright (c) [2018] [BTC.COM]

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

#include "CommonDecred.h"

extern "C" {

#include "libsph/sph_blake.h"

}

uint256 BlockHeaderDecred::getHash() const
{
  uint256 hash;
  sph_blake256_context ctx;
  sph_blake256_init(&ctx);
  sph_blake256(&ctx, this, sizeof(BlockHeaderDecred));
  sph_blake256_close(&ctx, &hash);
  return hash;
}

const NetworkParamsDecred& NetworkParamsDecred::get(NetworkDecred network)
{
  static NetworkParamsDecred mainnetParams{
    arith_uint256{"000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
    3119582664,
    100,
    101,
    6144,
    6,
    3,
    1,
    4096,
    5,
  };
  static NetworkParamsDecred testnetParams{
    arith_uint256{"0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
    2500000000,
    100,
    101,
    2048,
    6,
    3,
    1,
    768,
    5,
  };
  static NetworkParamsDecred simnetParams{
    arith_uint256{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"},
    50000000000,
    100,
    101,
    128,
    6,
    3,
    1,
    16 + (64 * 2),
    5,
  };

  switch (network) {
  case NetworkDecred::MainNet:
    return mainnetParams;
  case NetworkDecred::TestNet:
    return testnetParams;
  case NetworkDecred::SimNet:
    return simnetParams;
  }
  return testnetParams;
}
<commit_msg>Fix DCR mainnet & testnet PoW limit<commit_after>/*
 The MIT License (MIT)

 Copyright (c) [2018] [BTC.COM]

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

#include "CommonDecred.h"

extern "C" {

#include "libsph/sph_blake.h"

}

uint256 BlockHeaderDecred::getHash() const
{
  uint256 hash;
  sph_blake256_context ctx;
  sph_blake256_init(&ctx);
  sph_blake256(&ctx, this, sizeof(BlockHeaderDecred));
  sph_blake256_close(&ctx, &hash);
  return hash;
}

const NetworkParamsDecred& NetworkParamsDecred::get(NetworkDecred network)
{
  static NetworkParamsDecred mainnetParams{
    arith_uint256{}.SetCompact(0x1d00ffff),
    3119582664,
    100,
    101,
    6144,
    6,
    3,
    1,
    4096,
    5,
  };
  static NetworkParamsDecred testnetParams{
    arith_uint256{}.SetCompact(0x1e00ffff),
    2500000000,
    100,
    101,
    2048,
    6,
    3,
    1,
    768,
    5,
  };
  static NetworkParamsDecred simnetParams{
    arith_uint256{}.SetCompact(0x207fffff),
    50000000000,
    100,
    101,
    128,
    6,
    3,
    1,
    16 + (64 * 2),
    5,
  };

  switch (network) {
  case NetworkDecred::MainNet:
    return mainnetParams;
  case NetworkDecred::TestNet:
    return testnetParams;
  case NetworkDecred::SimNet:
    return simnetParams;
  }
  return testnetParams;
}
<|endoftext|>


<commit_before>//
//  MoContentDownloader.cpp
//  Chilli Source
//  Created by Scott Downie on 23/01/2012.
//
//  The MIT License (MIT)
//
//  Copyright (c) 2012 Tag Games Limited
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//

#include <ChilliSource/Networking/ContentDownload/MoContentDownloader.h>

#include <ChilliSource/Core/Base/Application.h>
#include <ChilliSource/Core/Base/Device.h>
#include <ChilliSource/Core/Delegate/MakeDelegate.h>
#include <ChilliSource/Networking/Http/HttpResponse.h>

#include <json/json.h>

namespace ChilliSource
{
    namespace Networking
    {
        const f32 k_downloadProgressUpdateIntervalDefault = 1.0f / 30.0f;

        //----------------------------------------------------------------
        //----------------------------------------------------------------
        MoContentDownloader::MoContentDownloader(HttpRequestSystem* inpRequestSystem, const std::string& instrAssetServerURL, const std::vector<std::string>& inastrTags)
        : mpHttpRequestSystem(inpRequestSystem), mstrAssetServerURL(instrAssetServerURL), mastrTags(inastrTags)
        {
            m_downloadProgressUpdateTimer = CSCore::TimerSPtr(new CSCore::Timer());
        }
        //----------------------------------------------------------------
        //----------------------------------------------------------------
        bool MoContentDownloader::DownloadContentManifest(const Delegate& inDelegate)
        {
            mOnContentManifestDownloadCompleteDelegate = inDelegate;

            //Request the content manifest
            if(mpHttpRequestSystem->CheckReachability())
            {
                Core::Device* device = Core::Application::Get()->GetSystem<Core::Device>();

                //Build the JSON request with the device info so the server can decide what
                //assets are suitable for us
                Json::Value JDeviceData(Json::objectValue);
                JDeviceData["Type"] = device->GetManufacturer() + device->GetModel() + device->GetModelType();
                JDeviceData["OS"] = device->GetOSVersion();
                JDeviceData["Locale"] = device->GetLocale();
                JDeviceData["Language"] = device->GetLanguage();

                //The server uses the tags to determine which content to serve
                Json::Value JTags(Json::arrayValue);
                for(std::vector<std::string>::const_iterator it = mastrTags.begin(); it != mastrTags.end(); ++it)
                {
                    JTags.append(*it);
                }
                JDeviceData["Tags"] = JTags;

                Json::FastWriter JWriter;
                mpHttpRequestSystem->MakePostRequest(mstrAssetServerURL, JWriter.write(JDeviceData), Core::MakeDelegate(this, &MoContentDownloader::OnContentManifestDownloadComplete));
                return true;
            }
            else
            {
                return false;
            }
        }
        //----------------------------------------------------------------
        //----------------------------------------------------------------
        void MoContentDownloader::DownloadPackage(const std::string& in_url, const Delegate& in_delegate, const DownloadProgressDelegate& in_progressDelegate)
        {
            mOnContentDownloadCompleteDelegate = in_delegate;
            mpCurrentRequest = mpHttpRequestSystem->MakeGetRequest(in_url, Core::MakeDelegate(this, &MoContentDownloader::OnContentDownloadComplete));

            //Reset the timer
            m_downloadProgressUpdateTimer->Reset();
            m_downloadProgressEventConnection = m_downloadProgressUpdateTimer->OpenConnection(k_downloadProgressUpdateIntervalDefault, [=]()
            {
                if(in_progressDelegate)
                {
                    in_progressDelegate(in_url, GetDownloadProgress());
                }
            });

            m_downloadProgressUpdateTimer->Start();
        }
        //----------------------------------------------------------------
        //----------------------------------------------------------------
        void MoContentDownloader::OnContentManifestDownloadComplete(const HttpRequest* in_request, const HttpResponse& in_response)
        {
            switch(in_response.GetResult())
            {
                case HttpResponse::Result::k_completed:
                {
                    //Check the response code for errors
                    switch(in_response.GetCode())
                    {
                        default:   //OK
                        case HttpResponseCode::k_ok:
                        {
                            mOnContentManifestDownloadCompleteDelegate(Result::k_succeeded, in_response.GetDataAsString());
                            break;
                        }
                        case HttpResponseCode::k_error:      //Error
                        case HttpResponseCode::k_unavailable://Temporary error try again later
                        case HttpResponseCode::k_notFound:   //End point doesn't exist
                        {
                            mOnContentManifestDownloadCompleteDelegate(Result::k_failed, in_response.GetDataAsString());
                            break;
                        }
                    }
                    break;
                }
                case HttpResponse::Result::k_timeout:
                case HttpResponse::Result::k_failed:
                {
                    mOnContentManifestDownloadCompleteDelegate(Result::k_failed, in_response.GetDataAsString());
                    break;
                }
                case HttpResponse::Result::k_flushed:
                {
                    //Check the response code for errors
                    switch(in_response.GetCode())
                    {
                        default:   //OK
                        case HttpResponseCode::k_ok:
                        {
                            mOnContentManifestDownloadCompleteDelegate(Result::k_flushed, in_response.GetDataAsString());
                            break;
                        }
                        case HttpResponseCode::k_error:      //Error
                        case HttpResponseCode::k_unavailable://Temporary error try again later
                        case HttpResponseCode::k_notFound:   //End point doesn't exist
                        {
                            mOnContentManifestDownloadCompleteDelegate(Result::k_failed, in_response.GetDataAsString());
                            break;
                        }
                    }
                    break;
                }
            }
        }
        //----------------------------------------------------------------
        //----------------------------------------------------------------
        void MoContentDownloader::OnContentDownloadComplete(const HttpRequest* in_request, const HttpResponse& in_response)
        {
            if(in_response.GetResult() != HttpResponse::Result::k_flushed)
            {
                if(mpCurrentRequest == in_request)
                    mpCurrentRequest = nullptr;

                if(m_downloadProgressUpdateTimer)
                {
                    m_downloadProgressEventConnection->Close();
                    m_downloadProgressUpdateTimer->Stop();
                }
            }

            switch(in_response.GetResult())
            {
                case HttpResponse::Result::k_completed:
                {
                    // Check the response code for errors
                    switch(in_response.GetCode())
                    {
                        default:   //OK
                        case HttpResponseCode::k_ok:
                            mOnContentDownloadCompleteDelegate(Result::k_succeeded, in_response.GetDataAsString());
                            break;
                    }
                    break;
                }
                case HttpResponse::Result::k_timeout:
                case HttpResponse::Result::k_failed:
                {
                    mOnContentDownloadCompleteDelegate(Result::k_failed, in_response.GetDataAsString());
                    break;
                }
                case HttpResponse::Result::k_flushed:
                {
                    mOnContentDownloadCompleteDelegate(Result::k_flushed, in_response.GetDataAsString());
                    break;
                }
            }
        }
        //----------------------------------------------------------------
        //----------------------------------------------------------------
        f32 MoContentDownloader::GetDownloadProgress()
        {
            f32 progress = 0.0f;

            // Check if there is an active request
            if(mpCurrentRequest)
            {
                if(mpCurrentRequest->GetExpectedTotalSize() > 0)
                {
                    // Calculate current scene download progress
                    progress = (f32)mpCurrentRequest->GetCurrentSize() / (f32)mpCurrentRequest->GetExpectedTotalSize();
                    CS_LOG_VERBOSE("!!!Progress = " + CSCore::ToString(progress));
                }
                else
                {
                    progress = 1.0f;
                }
            }

            return progress;
        }
    }
}<commit_msg>Fix for download progress glitch<commit_after>//
//  MoContentDownloader.cpp
//  Chilli Source
//  Created by Scott Downie on 23/01/2012.
//
//  The MIT License (MIT)
//
//  Copyright (c) 2012 Tag Games Limited
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
//

#include <ChilliSource/Networking/ContentDownload/MoContentDownloader.h>

#include <ChilliSource/Core/Base/Application.h>
#include <ChilliSource/Core/Base/Device.h>
#include <ChilliSource/Core/Delegate/MakeDelegate.h>
#include <ChilliSource/Networking/Http/HttpResponse.h>

#include <json/json.h>

namespace ChilliSource
{
    namespace Networking
    {
        const f32 k_downloadProgressUpdateIntervalDefault = 1.0f / 30.0f;

        //----------------------------------------------------------------
        //----------------------------------------------------------------
        MoContentDownloader::MoContentDownloader(HttpRequestSystem* inpRequestSystem, const std::string& instrAssetServerURL, const std::vector<std::string>& inastrTags)
        : mpHttpRequestSystem(inpRequestSystem), mstrAssetServerURL(instrAssetServerURL), mastrTags(inastrTags)
        {
            m_downloadProgressUpdateTimer = CSCore::TimerSPtr(new CSCore::Timer());
        }
        //----------------------------------------------------------------
        //----------------------------------------------------------------
        bool MoContentDownloader::DownloadContentManifest(const Delegate& inDelegate)
        {
            mOnContentManifestDownloadCompleteDelegate = inDelegate;

            //Request the content manifest
            if(mpHttpRequestSystem->CheckReachability())
            {
                Core::Device* device = Core::Application::Get()->GetSystem<Core::Device>();

                //Build the JSON request with the device info so the server can decide what
                //assets are suitable for us
                Json::Value JDeviceData(Json::objectValue);
                JDeviceData["Type"] = device->GetManufacturer() + device->GetModel() + device->GetModelType();
                JDeviceData["OS"] = device->GetOSVersion();
                JDeviceData["Locale"] = device->GetLocale();
                JDeviceData["Language"] = device->GetLanguage();

                //The server uses the tags to determine which content to serve
                Json::Value JTags(Json::arrayValue);
                for(std::vector<std::string>::const_iterator it = mastrTags.begin(); it != mastrTags.end(); ++it)
                {
                    JTags.append(*it);
                }
                JDeviceData["Tags"] = JTags;

                Json::FastWriter JWriter;
                mpHttpRequestSystem->MakePostRequest(mstrAssetServerURL, JWriter.write(JDeviceData), Core::MakeDelegate(this, &MoContentDownloader::OnContentManifestDownloadComplete));
                return true;
            }
            else
            {
                return false;
            }
        }
        //----------------------------------------------------------------
        //----------------------------------------------------------------
        void MoContentDownloader::DownloadPackage(const std::string& in_url, const Delegate& in_delegate, const DownloadProgressDelegate& in_progressDelegate)
        {
            mOnContentDownloadCompleteDelegate = in_delegate;
            mpCurrentRequest = mpHttpRequestSystem->MakeGetRequest(in_url, Core::MakeDelegate(this, &MoContentDownloader::OnContentDownloadComplete));

            //Reset the timer
            m_downloadProgressUpdateTimer->Reset();
            m_downloadProgressEventConnection = m_downloadProgressUpdateTimer->OpenConnection(k_downloadProgressUpdateIntervalDefault, [=]()
            {
                if(in_progressDelegate)
                {
                    in_progressDelegate(in_url, GetDownloadProgress());
                }
            });

            m_downloadProgressUpdateTimer->Start();
        }
        //----------------------------------------------------------------
        //----------------------------------------------------------------
        void MoContentDownloader::OnContentManifestDownloadComplete(const HttpRequest* in_request, const HttpResponse& in_response)
        {
            switch(in_response.GetResult())
            {
                case HttpResponse::Result::k_completed:
                {
                    //Check the response code for errors
                    switch(in_response.GetCode())
                    {
                        default:   //OK
                        case HttpResponseCode::k_ok:
                        {
                            mOnContentManifestDownloadCompleteDelegate(Result::k_succeeded, in_response.GetDataAsString());
                            break;
                        }
                        case HttpResponseCode::k_error:      //Error
                        case HttpResponseCode::k_unavailable://Temporary error try again later
                        case HttpResponseCode::k_notFound:   //End point doesn't exist
                        {
                            mOnContentManifestDownloadCompleteDelegate(Result::k_failed, in_response.GetDataAsString());
                            break;
                        }
                    }
                    break;
                }
                case HttpResponse::Result::k_timeout:
                case HttpResponse::Result::k_failed:
                {
                    mOnContentManifestDownloadCompleteDelegate(Result::k_failed, in_response.GetDataAsString());
                    break;
                }
                case HttpResponse::Result::k_flushed:
                {
                    //Check the response code for errors
                    switch(in_response.GetCode())
                    {
                        default:   //OK
                        case HttpResponseCode::k_ok:
                        {
                            mOnContentManifestDownloadCompleteDelegate(Result::k_flushed, in_response.GetDataAsString());
                            break;
                        }
                        case HttpResponseCode::k_error:      //Error
                        case HttpResponseCode::k_unavailable://Temporary error try again later
                        case HttpResponseCode::k_notFound:   //End point doesn't exist
                        {
                            mOnContentManifestDownloadCompleteDelegate(Result::k_failed, in_response.GetDataAsString());
                            break;
                        }
                    }
                    break;
                }
            }
        }
        //----------------------------------------------------------------
        //----------------------------------------------------------------
        void MoContentDownloader::OnContentDownloadComplete(const HttpRequest* in_request, const HttpResponse& in_response)
        {
            if(in_response.GetResult() != HttpResponse::Result::k_flushed)
            {
                if(mpCurrentRequest == in_request)
                    mpCurrentRequest = nullptr;

                if(m_downloadProgressUpdateTimer)
                {
                    m_downloadProgressEventConnection->Close();
                    m_downloadProgressUpdateTimer->Stop();
                }
            }

            switch(in_response.GetResult())
            {
                case HttpResponse::Result::k_completed:
                {
                    // Check the response code for errors
                    switch(in_response.GetCode())
                    {
                        default:   //OK
                        case HttpResponseCode::k_ok:
                            mOnContentDownloadCompleteDelegate(Result::k_succeeded, in_response.GetDataAsString());
                            break;
                    }
                    break;
                }
                case HttpResponse::Result::k_timeout:
                case HttpResponse::Result::k_failed:
                {
                    mOnContentDownloadCompleteDelegate(Result::k_failed, in_response.GetDataAsString());
                    break;
                }
                case HttpResponse::Result::k_flushed:
                {
                    mOnContentDownloadCompleteDelegate(Result::k_flushed, in_response.GetDataAsString());
                    break;
                }
            }
        }
        //----------------------------------------------------------------
        //----------------------------------------------------------------
        f32 MoContentDownloader::GetDownloadProgress()
        {
            f32 progress = 0.0f;

            // Check if there is an active request
            if(mpCurrentRequest)
            {
                if(mpCurrentRequest->GetExpectedTotalSize() > 0)
                {
                    // Calculate current scene download progress
                    progress = (f32)mpCurrentRequest->GetCurrentSize() / (f32)mpCurrentRequest->GetExpectedTotalSize();
                    CS_LOG_VERBOSE("!!!Progress = " + CSCore::ToString(progress));
                }
                else
                {
                    progress = 0.0f;
                }
            }

            return progress;
        }
    }
}<|endoftext|>