<commit_before>#include "SpellingChecker.h"

int SpellingChecker::CalculateEditDist(const string & a, const string & b)
{
	int dist;
	int **mat;
	int a_length = a.length();
	int b_length = b.length();

	mat = new int *[a_length + 1];
	for (int i = 0; i <= a_length; ++i)
	{
		mat[i] = new int[b_length + 1];
	}

	for (int i = 0; i <= b_length; ++i)
	{
		mat[0][i] = i;
	}

	for (int i = 1; i <= a_length; ++i)
	{
		mat[i][0] = i;
	}

	for (int i = 1; i <= a_length; ++i)
	{
		for (int j = 1; j <= b_length; ++j)
		{
			if (a[i - 1] == b[j - 1])
			{
				mat[i][j] = min({mat[i - 1][j] + 1, mat[i][j - 1] + 1, mat[i - 1][j - 1]});
			}
			else
			{
				mat[i][j] = min({mat[i - 1][j] + 1, mat[i][j - 1] + 1, mat[i - 1][j - 1] + 1});
			}
		}
	}

	dist = mat[a_length][b_length];

	for (int i = 0; i <= a_length; ++i)
	{
		delete [] mat[i];
	}
	delete [] mat;

	return dist;
}

string SpellingChecker::CheckWord(const string & queryword)
{
	string result;
	int resultfreq = 0;
	int minDist = 100;
	int dist;

	for (auto &word : dict)
	{
		if (word.first == queryword)
		{
			return queryword;
		}
	}

	for (auto &word : dict)
	{
		dist = CalculateEditDist(word.first, queryword);
		if (dist < minDist)
		{
			result = word.first;
			resultfreq = word.second;
			minDist = dist;
		}
		else if (dist == minDist)
		{
			if (word.second > resultfreq)
			{
				result = word.first;
				resultfreq = word.second;
			}
		}
	}

	if (minDist <= 3)
	{
		return result
	}
	else
	{
		return queryword;
	}
}

vector< pair<string, string> > SpellingChecker::CheckQuery(vector< pair<string, string> > &query)
{
	for (auto &item : query)
	{
		item.second = CheckWord(item.second);
	}

	return query;
}

int SpellingChecker::LoadDict()
{
	ifstream in;
	string line;
	int pos;

	in.open("FrequencyDict.txt", ios::in);
	if (!in.is_open())
	{
		cerr << "Can\'t open dict!" << endl;
		in.close();
		return 1;
	}

	auto word = dict.begin();
	while (getline(in, line))
    {
        pos = line.find_last_of(':');
        dict.insert(word, pair<string, int>(line.substr(0, pos), stoi(line.substr(pos + 1))));
    }

    in.close();
	return 0;
}

SpellingChecker::SpellingChecker()
{
	LoadDict();
}<commit_msg>bug fixes<commit_after>#include "SpellingChecker.h"

int SpellingChecker::CalculateEditDist(const string & a, const string & b)
{
	int dist;
	int **mat;
	int a_length = a.length();
	int b_length = b.length();

	mat = new int *[a_length + 1];
	for (int i = 0; i <= a_length; ++i)
	{
		mat[i] = new int[b_length + 1];
	}

	for (int i = 0; i <= b_length; ++i)
	{
		mat[0][i] = i;
	}

	for (int i = 1; i <= a_length; ++i)
	{
		mat[i][0] = i;
	}

	for (int i = 1; i <= a_length; ++i)
	{
		for (int j = 1; j <= b_length; ++j)
		{
			if (a[i - 1] == b[j - 1])
			{
				mat[i][j] = min({mat[i - 1][j] + 1, mat[i][j - 1] + 1, mat[i - 1][j - 1]});
			}
			else
			{
				mat[i][j] = min({mat[i - 1][j] + 1, mat[i][j - 1] + 1, mat[i - 1][j - 1] + 1});
			}
		}
	}

	dist = mat[a_length][b_length];

	for (int i = 0; i <= a_length; ++i)
	{
		delete [] mat[i];
	}
	delete [] mat;

	return dist;
}

string SpellingChecker::CheckWord(const string & queryword)
{
	string result;
	int resultfreq = 0;
	int minDist = 100;
	int dist;

	for (auto &word : dict)
	{
		if (word.first == queryword)
		{
			return queryword;
		}
	}

	for (auto &word : dict)
	{
		dist = CalculateEditDist(word.first, queryword);
		if (dist < minDist)
		{
			result = word.first;
			resultfreq = word.second;
			minDist = dist;
		}
		else if (dist == minDist)
		{
			if (word.second > resultfreq)
			{
				result = word.first;
				resultfreq = word.second;
			}
		}
	}

	if (minDist <= 3)
	{
		return result;
	}
	else
	{
		return queryword;
	}
}

vector< pair<string, string> > SpellingChecker::CheckQuery(vector< pair<string, string> > &query)
{
	for (auto &item : query)
	{
		item.second = CheckWord(item.second);
	}

	return query;
}

int SpellingChecker::LoadDict()
{
	ifstream in;
	string line;
	int pos;

	in.open("FrequencyDict.txt", ios::in);
	if (!in.is_open())
	{
		cerr << "Can\'t open dict!" << endl;
		in.close();
		return 1;
	}

	auto word = dict.begin();
	while (getline(in, line))
    {
        pos = line.find_last_of(':');
        dict.insert(word, pair<string, int>(line.substr(0, pos), stoi(line.substr(pos + 1))));
    }

    in.close();
	return 0;
}

SpellingChecker::SpellingChecker()
{
	LoadDict();
}<|endoftext|>


<commit_before><commit_msg>remove stan::math::test namespace for now<commit_after><|endoftext|>


<commit_before>//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <stdio.h>
#include <string.h>
#include "harness/testHarness.h"
#include "harness/typeWrappers.h"

#include <vector>

#include "procs.h"
#include "utils.h"
#include <time.h>

extern int gWimpyMode;

#ifdef CL_VERSION_2_0

static const char* enqueue_block_first_kernel[] =
{
    NL, "void block_fn(uint num, __global int* res)"
    NL, "{"
    NL, "    size_t tid = get_global_id(0);"
    NL, ""
    NL, "    for(int i = 1 ; i < tid ; i++)"
    NL, "    {"
    NL, "      for(int j = 0 ; j < num ; j++)"
    NL, "        atomic_add(res+tid, 1);"
    NL, "    }"
    NL, "}"
    NL, ""
    NL, "kernel void enqueue_block_first_kernel(uint num, __global int* res)"
    NL, "{"
    NL, "  void (^kernelBlock)(void) = ^{ block_fn(num, res); };"
    NL, ""
    NL, "  ndrange_t ndrange = ndrange_1D(num, 1);"
    NL, ""
    NL, "  int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, kernelBlock);"
    NL, "  if(enq_res != CLK_SUCCESS) { res[0] = -1; return; }"
    NL, ""
    NL, "}"
    NL
};

static const char* enqueue_block_second_kernel[] =
{
    NL, "void block_fn(uint num, __global int* res)"
    NL, "{"
    NL, "    for(int i = 2 ; i < num ; i++)"
    NL, "    {"
    NL, "      res[i] = res[i]/num - (i-1);"
    NL, "    }"
    NL, "}"
    NL, ""
    NL, "kernel void enqueue_block_second_kernel(uint num, __global int* res)"
    NL, "{"
    NL, "  void (^kernelBlock)(void) = ^{ block_fn(num, res); };"
    NL, ""
    NL, "  ndrange_t ndrange = ndrange_1D(1);"
    NL, ""
    NL, "  int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);"
    NL, "  if(enq_res != CLK_SUCCESS) { res[0] = -1; return; }"
    NL, ""
    NL, "}"
    NL
};

static int check_kernel_results(cl_int* results, cl_int len)
{
    for(cl_int i = 0; i < len; ++i)
    {
        if(results[i] != 0) return i;
    }
    return -1;
}

/*
    Test checks kernel block execution order in case of two different kernels with enqueue block submitted to one ordered host queue.
*/
int test_host_queue_order(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
{
    cl_int k, err_ret, res = 0;
    clCommandQueueWrapper dev_queue;
    cl_int kernel_results[MAX_GWS] = {0};

    size_t ret_len;
    cl_uint max_queues = 1;
    cl_uint maxQueueSize = 0;
    err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, sizeof(maxQueueSize), &maxQueueSize, 0);
    test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE) failed");

    err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_QUEUES, sizeof(max_queues), &max_queues, &ret_len);
    test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_ON_DEVICE_QUEUES) failed");

    size_t max_local_size = 1;
    err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(max_local_size), &max_local_size, &ret_len);
    test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_WORK_GROUP_SIZE) failed");

    cl_queue_properties queue_prop_def[] =
    {
        CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE|CL_QUEUE_ON_DEVICE_DEFAULT,
        CL_QUEUE_SIZE, maxQueueSize,
        0
    };

    dev_queue = clCreateCommandQueueWithProperties(context, device, queue_prop_def, &err_ret);
    test_error(err_ret, "clCreateCommandQueueWithProperties(CL_QUEUE_DEVICE|CL_QUEUE_DEFAULT) failed");

    cl_int status;
    size_t size = 1;
    cl_int result[MAX_GWS] = { 0 };
    cl_uint num = arr_size(result);
    if( gWimpyMode )
    {
        num = MAX(num / 16, 4);
    }

    clMemWrapper res_mem;
    clProgramWrapper program1, program2;
    clKernelWrapper kernel1, kernel2;

    cl_event kernel_event;

    err_ret = create_single_kernel_helper_with_build_options(context, &program1, &kernel1,  arr_size(enqueue_block_first_kernel), enqueue_block_first_kernel, "enqueue_block_first_kernel", "-cl-std=CL2.0");
    if(check_error(err_ret, "Create single kernel failed")) return -1;

    err_ret = create_single_kernel_helper_with_build_options(context, &program2, &kernel2, arr_size(enqueue_block_second_kernel), enqueue_block_second_kernel, "enqueue_block_second_kernel", "-cl-std=CL2.0");
    if(check_error(err_ret, "Create single kernel failed")) return -1;

    res_mem = clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, sizeof(kernel_results), kernel_results, &err_ret);
    test_error(err_ret, "clCreateBuffer() failed");

    // Enqueue first kernel
    err_ret = clSetKernelArg(kernel1, 0, sizeof(num), &num);
    test_error(err_ret, "clSetKernelArg(0) failed");
    err_ret = clSetKernelArg(kernel1, 1, sizeof(cl_mem), &res_mem);
    test_error(err_ret, "clSetKernelArg(1) failed");

    cl_event event1 = clCreateUserEvent(context, &err_ret);
    if(check_error(err_ret, "Create user event failed")) return -1;

    err_ret = clEnqueueNDRangeKernel(queue, kernel1, 1, NULL, &size, &size, 1, &event1, NULL);
    test_error(err_ret, "clEnqueueNDRangeKernel('enqueue_block_first_kernel') failed");

    // Enqueue second kernel
    err_ret = clSetKernelArg(kernel2, 0, sizeof(num), &num);
    test_error(err_ret, "clSetKernelArg(0) failed");
    err_ret = clSetKernelArg(kernel2, 1, sizeof(cl_mem), &res_mem);
    test_error(err_ret, "clSetKernelArg(1) failed");

    err_ret = clEnqueueNDRangeKernel(queue, kernel2, 1, NULL, &size, &size, 0, NULL, &kernel_event);
    test_error(err_ret, "clEnqueueNDRangeKernel('enqueue_block_second_kernel') failed");

    //Triger execution of first kernel
    err_ret = clSetUserEventStatus(event1, CL_COMPLETE);
    test_error(err_ret, "clSetUserEventStatus() failed");

    // Collect resulsts
    err_ret = clEnqueueReadBuffer(queue, res_mem, CL_TRUE, 0, sizeof(result), result, 0, NULL, NULL);
    test_error(err_ret, "clEnqueueReadBuffer() failed");

    err_ret = clGetEventInfo(kernel_event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(status), &status, &ret_len);
    test_error(err_ret, "clGetEventInfo() failed");

    if(check_error(status, "Kernel execution status %d", status)) return status;

    if((k = check_kernel_results(result, num)) >= 0 && check_error(-1, "'%s' results validation failed: [%d] returned %d expected 0", "test_host_queue_order", k, result[k])) res = -1;

    return res;
}

#endif

<commit_msg>Release event in host_enqueue_order test.<commit_after>//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <stdio.h>
#include <string.h>
#include "harness/testHarness.h"
#include "harness/typeWrappers.h"

#include <vector>

#include "procs.h"
#include "utils.h"
#include <time.h>

extern int gWimpyMode;

#ifdef CL_VERSION_2_0

static const char* enqueue_block_first_kernel[] =
{
    NL, "void block_fn(uint num, __global int* res)"
    NL, "{"
    NL, "    size_t tid = get_global_id(0);"
    NL, ""
    NL, "    for(int i = 1 ; i < tid ; i++)"
    NL, "    {"
    NL, "      for(int j = 0 ; j < num ; j++)"
    NL, "        atomic_add(res+tid, 1);"
    NL, "    }"
    NL, "}"
    NL, ""
    NL, "kernel void enqueue_block_first_kernel(uint num, __global int* res)"
    NL, "{"
    NL, "  void (^kernelBlock)(void) = ^{ block_fn(num, res); };"
    NL, ""
    NL, "  ndrange_t ndrange = ndrange_1D(num, 1);"
    NL, ""
    NL, "  int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_NO_WAIT, ndrange, kernelBlock);"
    NL, "  if(enq_res != CLK_SUCCESS) { res[0] = -1; return; }"
    NL, ""
    NL, "}"
    NL
};

static const char* enqueue_block_second_kernel[] =
{
    NL, "void block_fn(uint num, __global int* res)"
    NL, "{"
    NL, "    for(int i = 2 ; i < num ; i++)"
    NL, "    {"
    NL, "      res[i] = res[i]/num - (i-1);"
    NL, "    }"
    NL, "}"
    NL, ""
    NL, "kernel void enqueue_block_second_kernel(uint num, __global int* res)"
    NL, "{"
    NL, "  void (^kernelBlock)(void) = ^{ block_fn(num, res); };"
    NL, ""
    NL, "  ndrange_t ndrange = ndrange_1D(1);"
    NL, ""
    NL, "  int enq_res = enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_WAIT_KERNEL, ndrange, kernelBlock);"
    NL, "  if(enq_res != CLK_SUCCESS) { res[0] = -1; return; }"
    NL, ""
    NL, "}"
    NL
};

static int check_kernel_results(cl_int* results, cl_int len)
{
    for(cl_int i = 0; i < len; ++i)
    {
        if(results[i] != 0) return i;
    }
    return -1;
}

/*
    Test checks kernel block execution order in case of two different kernels with enqueue block submitted to one ordered host queue.
*/
int test_host_queue_order(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
{
    cl_int k, err_ret, res = 0;
    clCommandQueueWrapper dev_queue;
    cl_int kernel_results[MAX_GWS] = {0};

    size_t ret_len;
    cl_uint max_queues = 1;
    cl_uint maxQueueSize = 0;
    err_ret = clGetDeviceInfo(device, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, sizeof(maxQueueSize), &maxQueueSize, 0);
    test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE) failed");

    err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_ON_DEVICE_QUEUES, sizeof(max_queues), &max_queues, &ret_len);
    test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_ON_DEVICE_QUEUES) failed");

    size_t max_local_size = 1;
    err_ret = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(max_local_size), &max_local_size, &ret_len);
    test_error(err_ret, "clGetDeviceInfo(CL_DEVICE_MAX_WORK_GROUP_SIZE) failed");

    cl_queue_properties queue_prop_def[] =
    {
        CL_QUEUE_PROPERTIES, CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE|CL_QUEUE_ON_DEVICE|CL_QUEUE_ON_DEVICE_DEFAULT,
        CL_QUEUE_SIZE, maxQueueSize,
        0
    };

    dev_queue = clCreateCommandQueueWithProperties(context, device, queue_prop_def, &err_ret);
    test_error(err_ret, "clCreateCommandQueueWithProperties(CL_QUEUE_DEVICE|CL_QUEUE_DEFAULT) failed");

    cl_int status;
    size_t size = 1;
    cl_int result[MAX_GWS] = { 0 };
    cl_uint num = arr_size(result);
    if( gWimpyMode )
    {
        num = MAX(num / 16, 4);
    }

    clMemWrapper res_mem;
    clProgramWrapper program1, program2;
    clKernelWrapper kernel1, kernel2;

    cl_event kernel_event;

    err_ret = create_single_kernel_helper_with_build_options(context, &program1, &kernel1,  arr_size(enqueue_block_first_kernel), enqueue_block_first_kernel, "enqueue_block_first_kernel", "-cl-std=CL2.0");
    if(check_error(err_ret, "Create single kernel failed")) return -1;

    err_ret = create_single_kernel_helper_with_build_options(context, &program2, &kernel2, arr_size(enqueue_block_second_kernel), enqueue_block_second_kernel, "enqueue_block_second_kernel", "-cl-std=CL2.0");
    if(check_error(err_ret, "Create single kernel failed")) return -1;

    res_mem = clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, sizeof(kernel_results), kernel_results, &err_ret);
    test_error(err_ret, "clCreateBuffer() failed");

    // Enqueue first kernel
    err_ret = clSetKernelArg(kernel1, 0, sizeof(num), &num);
    test_error(err_ret, "clSetKernelArg(0) failed");
    err_ret = clSetKernelArg(kernel1, 1, sizeof(cl_mem), &res_mem);
    test_error(err_ret, "clSetKernelArg(1) failed");

    cl_event event1 = clCreateUserEvent(context, &err_ret);
    if(check_error(err_ret, "Create user event failed")) return -1;

    err_ret = clEnqueueNDRangeKernel(queue, kernel1, 1, NULL, &size, &size, 1, &event1, NULL);
    test_error(err_ret, "clEnqueueNDRangeKernel('enqueue_block_first_kernel') failed");

    // Enqueue second kernel
    err_ret = clSetKernelArg(kernel2, 0, sizeof(num), &num);
    test_error(err_ret, "clSetKernelArg(0) failed");
    err_ret = clSetKernelArg(kernel2, 1, sizeof(cl_mem), &res_mem);
    test_error(err_ret, "clSetKernelArg(1) failed");

    err_ret = clEnqueueNDRangeKernel(queue, kernel2, 1, NULL, &size, &size, 0, NULL, &kernel_event);
    test_error(err_ret, "clEnqueueNDRangeKernel('enqueue_block_second_kernel') failed");

    //Triger execution of first kernel
    err_ret = clSetUserEventStatus(event1, CL_COMPLETE);
    test_error(err_ret, "clSetUserEventStatus() failed");

    // Collect resulsts
    err_ret = clEnqueueReadBuffer(queue, res_mem, CL_TRUE, 0, sizeof(result), result, 0, NULL, NULL);
    test_error(err_ret, "clEnqueueReadBuffer() failed");

    err_ret = clGetEventInfo(kernel_event, CL_EVENT_COMMAND_EXECUTION_STATUS, sizeof(status), &status, &ret_len);
    test_error(err_ret, "clGetEventInfo() failed");

    if(check_error(status, "Kernel execution status %d", status)) return status;

    if((k = check_kernel_results(result, num)) >= 0 && check_error(-1, "'%s' results validation failed: [%d] returned %d expected 0", "test_host_queue_order", k, result[k])) res = -1;

    clReleaseEvent(kernel_event);
    clReleaseEvent(event1);

    return res;
}

#endif

<|endoftext|>


<commit_before>#include "ShardServer.h"
#include "System/Config.h"
#include "Framework/Replication/ReplicationConfig.h"
#include "Application/Common/ContextTransport.h"
#include "Application/Common/DatabaseConsts.h"
#include "Application/Common/CatchupMessage.h"
#include "Application/Common/ClientRequestCache.h"

void ShardServer::Init()
{
    unsigned        numControllers;
    uint64_t        nodeID;
    uint64_t        runID;
    const char*     str;
    Endpoint        endpoint;

    databaseManager.Init(this);
    heartbeatManager.Init(this);
    REQUEST_CACHE->Init(configFile.GetIntValue("requestCache.size", 100));

    runID = REPLICATION_CONFIG->GetRunID();
    runID += 1;
    REPLICATION_CONFIG->SetRunID(runID);
    REPLICATION_CONFIG->Commit();
    Log_Trace("rundID: %U", runID);

    if (MY_NODEID > 0)
        CONTEXT_TRANSPORT->SetSelfNodeID(MY_NODEID);

    CONTEXT_TRANSPORT->SetClusterID(REPLICATION_CONFIG->GetClusterID());

    // connect to the controller nodes
    numControllers = (unsigned) configFile.GetListNum("controllers");
    for (nodeID = 0; nodeID < numControllers; nodeID++)
    {
        str = configFile.GetListValue("controllers", (int) nodeID, "");
        endpoint.Set(str);
        CONTEXT_TRANSPORT->AddNode(nodeID, endpoint);
        configServers.Append(nodeID);
        // this will cause the node to connect to the controllers
        // and if my nodeID is not set the MASTER will automatically send
        // me a SetNodeID cluster message
    }

    CONTEXT_TRANSPORT->SetClusterContext(this);
}

void ShardServer::Shutdown()
{
    quorumProcessors.DeleteList();
    databaseManager.Shutdown();
    CONTEXT_TRANSPORT->Shutdown();
    REPLICATION_CONFIG->Shutdown();
    REQUEST_CACHE->Shutdown();
}

ShardQuorumProcessor* ShardServer::GetQuorumProcessor(uint64_t quorumID)
{
    ShardQuorumProcessor* it;

    FOREACH(it, quorumProcessors)
    {
        if (it->GetQuorumID() == quorumID)
            return it;
    }

    return NULL;
}

ShardServer::QuorumProcessorList* ShardServer::GetQuorumProcessors()
{
    return &quorumProcessors;
}

ShardDatabaseManager* ShardServer::GetDatabaseManager()
{
    return &databaseManager;
}

ConfigState* ShardServer::GetConfigState()
{
    return &configState;
}

void ShardServer::BroadcastToControllers(Message& message)
{
    uint64_t* itNodeID;

    FOREACH(itNodeID, configServers)
        CONTEXT_TRANSPORT->SendClusterMessage(*itNodeID, message);
}

bool ShardServer::IsValidClientRequest(ClientRequest* request)
{
     return request->IsShardServerRequest();
}

void ShardServer::OnClientRequest(ClientRequest* request)
{
    ConfigShard*            shard;
    ShardQuorumProcessor*   quorumProcessor;

    if (request->type == CLIENTREQUEST_SUBMIT)
    {
        quorumProcessor = GetQuorumProcessor(request->quorumID);
        if (!quorumProcessor)
        {
            request->response.NoResponse();
            request->OnComplete();
            return;
        }

        quorumProcessor->OnClientRequest(request);
        return;
    }

    shard = configState.GetShard(request->tableID, ReadBuffer(request->key));
    if (!shard)
    {
        Log_Trace();
        request->response.Failed();
        request->OnComplete();
        return;
    }

    quorumProcessor = GetQuorumProcessor(shard->quorumID);
    if (!quorumProcessor)
    {
        request->response.NoService();
        request->OnComplete();
        return;
    }

    quorumProcessor->OnClientRequest(request);
}

void ShardServer::OnClientClose(ClientSession* /*session*/)
{
    // nothing
}

void ShardServer::OnClusterMessage(uint64_t /*nodeID*/, ClusterMessage& message)
{
    ShardQuorumProcessor* quorumProcessor;

    Log_Trace();

    switch (message.type)
    {
        case CLUSTERMESSAGE_SET_NODEID:
            if (!CONTEXT_TRANSPORT->IsAwaitingNodeID())
                return;
            CONTEXT_TRANSPORT->SetSelfNodeID(message.nodeID);
            REPLICATION_CONFIG->SetNodeID(message.nodeID);
            assert(REPLICATION_CONFIG->GetClusterID() == 0);
            CONTEXT_TRANSPORT->SetClusterID(message.clusterID);
            REPLICATION_CONFIG->SetClusterID(message.clusterID);
            REPLICATION_CONFIG->Commit();
            Log_Trace("My nodeID is %U", message.nodeID);
            Log_Message("NodeID set to %U", message.nodeID);
            break;
        case CLUSTERMESSAGE_SET_CONFIG_STATE:
            OnSetConfigState(message);
            Log_Trace("Got new configState, master is %d",
             configState.hasMaster ? (int) configState.masterID : -1);
            break;
        case CLUSTERMESSAGE_RECEIVE_LEASE:
            quorumProcessor = GetQuorumProcessor(message.quorumID);
            if (quorumProcessor)
                quorumProcessor->OnReceiveLease(message);
            Log_Trace("Recieved lease, quorumID = %U, proposalID =  %U",
             message.quorumID, message.proposalID);
            break;
        default:
            ASSERT_FAIL();
    }
}

void ShardServer::OnIncomingConnectionReady(uint64_t /*nodeID*/, Endpoint /*endpoint*/)
{
    // nothing
}

bool ShardServer::OnAwaitingNodeID(Endpoint /*endpoint*/)
{
    // always drop
    return true;
}

bool ShardServer::IsLeaseKnown(uint64_t quorumID)
{
    ShardQuorumProcessor*   quorumProcessor;
    ConfigQuorum*           configQuorum;

    quorumProcessor = GetQuorumProcessor(quorumID);
    if (quorumProcessor == NULL)
        return false;

    if (quorumProcessor->IsPrimary())
        return true;

    configQuorum = configState.GetQuorum(quorumID);
    if (configQuorum == NULL)
        return false;

    if (!configQuorum->hasPrimary)
        return false;

    // we already checked this case
    if (configQuorum->primaryID == MY_NODEID)
        return false;

    return true;
}

bool ShardServer::IsLeaseOwner(uint64_t quorumID)
{
    ShardQuorumProcessor*   quorumProcessor;

    quorumProcessor = GetQuorumProcessor(quorumID);
    if (quorumProcessor == NULL)
        return false;

    return quorumProcessor->IsPrimary();
}

uint64_t ShardServer::GetLeaseOwner(uint64_t quorumID)
{
    ShardQuorumProcessor*   quorumProcessor;
    ConfigQuorum*           configQuorum;

    quorumProcessor = GetQuorumProcessor(quorumID);
    if (quorumProcessor == NULL)
        return false;

    if (quorumProcessor->IsPrimary())
        return MY_NODEID;

    configQuorum = configState.GetQuorum(quorumID);
    if (configQuorum == NULL)
        return 0;

    if (!configQuorum->hasPrimary)
        return 0;

    // we already checked this case
    if (configQuorum->primaryID == MY_NODEID)
        return 0;

    return configQuorum->primaryID;
}

void ShardServer::OnSetConfigState(ClusterMessage& message)
{
    bool                    found;
    uint64_t*               itNodeID;
    uint64_t*               itConfigShard;
    ReadBuffer              splitKey;
    ConfigShard*            configShard;
    ConfigQuorum*           configQuorum;
    ConfigShardServer*      configShardServer;
    ShardQuorumProcessor*   quorumProcessor;
    ShardQuorumProcessor*   next;

    Log_Trace();

    configState = message.configState;
    configShardServer = configState.GetShardServer(MY_NODEID);

    // look for removal
    for (quorumProcessor = quorumProcessors.First(); quorumProcessor != NULL; quorumProcessor = next)
    {
        configQuorum = configState.GetQuorum(quorumProcessor->GetQuorumID());
        if (configQuorum == NULL)
        {
            // TODO: quorum has disappeared
            ASSERT_FAIL();
        }

        found = false;
        next = quorumProcessors.Next(quorumProcessor);

        FOREACH(itNodeID, configQuorum->activeNodes)
        {
            if (*itNodeID == MY_NODEID)
            {
                found = true;
                break;
            }
        }
        if (found)
        {
            quorumProcessor->RegisterPaxosID(configQuorum->paxosID);

            if (quorumProcessor->IsPrimary())
            {
                // look for shard splits
                FOREACH(itConfigShard, configQuorum->shards)
                {
                    configShard = configState.GetShard(*itConfigShard);
                    if (configShard->isSplitCreating)
                    {
                        splitKey.Wrap(configShard->firstKey);
                        quorumProcessor->TrySplitShard(configShard->parentShardID,
                         configShard->shardID, splitKey);
                    }
                }
            }
            continue;
        }
        FOREACH(itNodeID, configQuorum->inactiveNodes)
        {
            if (*itNodeID == MY_NODEID)
            {
                found = true;
                break;
            }
        }
        if (found)
        {
            quorumProcessor->RegisterPaxosID(configQuorum->paxosID);
            continue;
        }

        next = quorumProcessors.Remove(quorumProcessor);
        delete quorumProcessor;
    }

    // check changes in active or inactive node list
    FOREACH(configQuorum, configState.quorums)
    {
        FOREACH(itNodeID, configQuorum->activeNodes)
        {
            if (*itNodeID == MY_NODEID)
            {
                ConfigureQuorum(configQuorum); // also creates quorum
                break;
            }
        }

        FOREACH(itNodeID, configQuorum->inactiveNodes)
        {
            if (*itNodeID == MY_NODEID)
            {
                ConfigureQuorum(configQuorum); // also creates quorum
                quorumProcessor = GetQuorumProcessor(configQuorum->quorumID);
                assert(quorumProcessor != NULL);
                quorumProcessor->TryReplicationCatchup();
                break;
            }
        }
    }

    databaseManager.RemoveDeletedTables();
    databaseManager.RemoveDeletedDatabases();
}

void ShardServer::ConfigureQuorum(ConfigQuorum* configQuorum)
{
    uint64_t                quorumID;
    uint64_t*               itNodeID;
    ConfigShardServer*      shardServer;
    ShardQuorumProcessor*   quorumProcessor;

    Log_Trace();

    quorumID = configQuorum->quorumID;
    quorumProcessor = GetQuorumProcessor(quorumID);
    if (quorumProcessor == NULL)
    {
        databaseManager.SetQuorumShards(quorumID);

        quorumProcessor = new ShardQuorumProcessor;
        quorumProcessor->Init(configQuorum, this);

        quorumProcessors.Append(quorumProcessor);
        FOREACH(itNodeID, configQuorum->activeNodes)
        {
            shardServer = configState.GetShardServer(*itNodeID);
            assert(shardServer != NULL);
            CONTEXT_TRANSPORT->AddNode(*itNodeID, shardServer->endpoint);
        }
    }
    else
    {
        quorumProcessor->SetActiveNodes(configQuorum->activeNodes);

        // add nodes to CONTEXT_TRANSPORT
        FOREACH(itNodeID, configQuorum->activeNodes)
        {
            shardServer = configState.GetShardServer(*itNodeID);
            assert(shardServer != NULL);
            CONTEXT_TRANSPORT->AddNode(*itNodeID, shardServer->endpoint);
        }
    }

    databaseManager.SetShards(configQuorum->shards);
}

unsigned ShardServer::GetHTTPPort()
{
    return configFile.GetIntValue("http.port", 8080);
}

unsigned  ShardServer::GetSDBPPort()
{
    return configFile.GetIntValue("sdbp.port", 7080);
}
<commit_msg>Added Log_Debug.<commit_after>#include "ShardServer.h"
#include "System/Config.h"
#include "Framework/Replication/ReplicationConfig.h"
#include "Application/Common/ContextTransport.h"
#include "Application/Common/DatabaseConsts.h"
#include "Application/Common/CatchupMessage.h"
#include "Application/Common/ClientRequestCache.h"

void ShardServer::Init()
{
    unsigned        numControllers;
    uint64_t        nodeID;
    uint64_t        runID;
    const char*     str;
    Endpoint        endpoint;

    databaseManager.Init(this);
    heartbeatManager.Init(this);
    REQUEST_CACHE->Init(configFile.GetIntValue("requestCache.size", 100));

    runID = REPLICATION_CONFIG->GetRunID();
    runID += 1;
    REPLICATION_CONFIG->SetRunID(runID);
    REPLICATION_CONFIG->Commit();
    Log_Trace("rundID: %U", runID);

    if (MY_NODEID > 0)
        CONTEXT_TRANSPORT->SetSelfNodeID(MY_NODEID);

    CONTEXT_TRANSPORT->SetClusterID(REPLICATION_CONFIG->GetClusterID());

    // connect to the controller nodes
    numControllers = (unsigned) configFile.GetListNum("controllers");
    for (nodeID = 0; nodeID < numControllers; nodeID++)
    {
        str = configFile.GetListValue("controllers", (int) nodeID, "");
        endpoint.Set(str);
        CONTEXT_TRANSPORT->AddNode(nodeID, endpoint);
        configServers.Append(nodeID);
        // this will cause the node to connect to the controllers
        // and if my nodeID is not set the MASTER will automatically send
        // me a SetNodeID cluster message
    }

    CONTEXT_TRANSPORT->SetClusterContext(this);
}

void ShardServer::Shutdown()
{
    quorumProcessors.DeleteList();
    databaseManager.Shutdown();
    CONTEXT_TRANSPORT->Shutdown();
    REPLICATION_CONFIG->Shutdown();
    REQUEST_CACHE->Shutdown();
}

ShardQuorumProcessor* ShardServer::GetQuorumProcessor(uint64_t quorumID)
{
    ShardQuorumProcessor* it;

    FOREACH(it, quorumProcessors)
    {
        if (it->GetQuorumID() == quorumID)
            return it;
    }

    return NULL;
}

ShardServer::QuorumProcessorList* ShardServer::GetQuorumProcessors()
{
    return &quorumProcessors;
}

ShardDatabaseManager* ShardServer::GetDatabaseManager()
{
    return &databaseManager;
}

ConfigState* ShardServer::GetConfigState()
{
    return &configState;
}

void ShardServer::BroadcastToControllers(Message& message)
{
    uint64_t* itNodeID;

    FOREACH(itNodeID, configServers)
        CONTEXT_TRANSPORT->SendClusterMessage(*itNodeID, message);
}

bool ShardServer::IsValidClientRequest(ClientRequest* request)
{
     return request->IsShardServerRequest();
}

void ShardServer::OnClientRequest(ClientRequest* request)
{
    ConfigShard*            shard;
    ShardQuorumProcessor*   quorumProcessor;

    if (request->type == CLIENTREQUEST_SUBMIT)
    {
        quorumProcessor = GetQuorumProcessor(request->quorumID);
        if (!quorumProcessor)
        {
            request->response.NoResponse();
            request->OnComplete();
            return;
        }

        quorumProcessor->OnClientRequest(request);
        return;
    }

    shard = configState.GetShard(request->tableID, ReadBuffer(request->key));
    if (!shard)
    {
        Log_Trace();
        request->response.Failed();
        request->OnComplete();
        return;
    }

    quorumProcessor = GetQuorumProcessor(shard->quorumID);
    if (!quorumProcessor)
    {
        request->response.NoService();
        request->OnComplete();
        return;
    }

    quorumProcessor->OnClientRequest(request);
}

void ShardServer::OnClientClose(ClientSession* /*session*/)
{
    // nothing
}

void ShardServer::OnClusterMessage(uint64_t /*nodeID*/, ClusterMessage& message)
{
    ShardQuorumProcessor* quorumProcessor;

    Log_Trace();

    switch (message.type)
    {
        case CLUSTERMESSAGE_SET_NODEID:
            if (!CONTEXT_TRANSPORT->IsAwaitingNodeID())
                return;
            CONTEXT_TRANSPORT->SetSelfNodeID(message.nodeID);
            REPLICATION_CONFIG->SetNodeID(message.nodeID);
            assert(REPLICATION_CONFIG->GetClusterID() == 0);
            CONTEXT_TRANSPORT->SetClusterID(message.clusterID);
            REPLICATION_CONFIG->SetClusterID(message.clusterID);
            REPLICATION_CONFIG->Commit();
            Log_Trace("My nodeID is %U", message.nodeID);
            Log_Message("NodeID set to %U", message.nodeID);
            break;
        case CLUSTERMESSAGE_SET_CONFIG_STATE:
            OnSetConfigState(message);
            Log_Trace("Got new configState, master is %d",
             configState.hasMaster ? (int) configState.masterID : -1);
            break;
        case CLUSTERMESSAGE_RECEIVE_LEASE:
            quorumProcessor = GetQuorumProcessor(message.quorumID);
            if (quorumProcessor)
                quorumProcessor->OnReceiveLease(message);
            Log_Trace("Recieved lease, quorumID = %U, proposalID =  %U",
             message.quorumID, message.proposalID);
            break;
        default:
            ASSERT_FAIL();
    }
}

void ShardServer::OnIncomingConnectionReady(uint64_t /*nodeID*/, Endpoint /*endpoint*/)
{
    // nothing
}

bool ShardServer::OnAwaitingNodeID(Endpoint /*endpoint*/)
{
    // always drop
    return true;
}

bool ShardServer::IsLeaseKnown(uint64_t quorumID)
{
    ShardQuorumProcessor*   quorumProcessor;
    ConfigQuorum*           configQuorum;

    quorumProcessor = GetQuorumProcessor(quorumID);
    if (quorumProcessor == NULL)
        return false;

    if (quorumProcessor->IsPrimary())
        return true;

    configQuorum = configState.GetQuorum(quorumID);
    if (configQuorum == NULL)
        return false;

    if (!configQuorum->hasPrimary)
        return false;

    // we already checked this case
    if (configQuorum->primaryID == MY_NODEID)
        return false;

    return true;
}

bool ShardServer::IsLeaseOwner(uint64_t quorumID)
{
    ShardQuorumProcessor*   quorumProcessor;

    quorumProcessor = GetQuorumProcessor(quorumID);
    if (quorumProcessor == NULL)
        return false;

    return quorumProcessor->IsPrimary();
}

uint64_t ShardServer::GetLeaseOwner(uint64_t quorumID)
{
    ShardQuorumProcessor*   quorumProcessor;
    ConfigQuorum*           configQuorum;

    quorumProcessor = GetQuorumProcessor(quorumID);
    if (quorumProcessor == NULL)
        return false;

    if (quorumProcessor->IsPrimary())
        return MY_NODEID;

    configQuorum = configState.GetQuorum(quorumID);
    if (configQuorum == NULL)
        return 0;

    if (!configQuorum->hasPrimary)
        return 0;

    // we already checked this case
    if (configQuorum->primaryID == MY_NODEID)
        return 0;

    return configQuorum->primaryID;
}

void ShardServer::OnSetConfigState(ClusterMessage& message)
{
    bool                    found;
    uint64_t*               itNodeID;
    uint64_t*               itConfigShard;
    ReadBuffer              splitKey;
    ConfigShard*            configShard;
    ConfigQuorum*           configQuorum;
    ConfigShardServer*      configShardServer;
    ShardQuorumProcessor*   quorumProcessor;
    ShardQuorumProcessor*   next;

    Log_Trace();

    configState = message.configState;
    configShardServer = configState.GetShardServer(MY_NODEID);

    // look for removal
    for (quorumProcessor = quorumProcessors.First(); quorumProcessor != NULL; quorumProcessor = next)
    {
        configQuorum = configState.GetQuorum(quorumProcessor->GetQuorumID());
        if (configQuorum == NULL)
        {
            // TODO: quorum has disappeared
            ASSERT_FAIL();
        }

        found = false;
        next = quorumProcessors.Next(quorumProcessor);

        FOREACH(itNodeID, configQuorum->activeNodes)
        {
            if (*itNodeID == MY_NODEID)
            {
                found = true;
                break;
            }
        }
        if (found)
        {
            quorumProcessor->RegisterPaxosID(configQuorum->paxosID);

            if (quorumProcessor->IsPrimary())
            {
                // look for shard splits
                FOREACH(itConfigShard, configQuorum->shards)
                {
                    configShard = configState.GetShard(*itConfigShard);
                    if (configShard->isSplitCreating)
                    {
                        Log_Debug("Splitting shard (parent shardID = %U, new shardID = %U)...",
                         configShard->parentShardID, configShard->shardID);
                        splitKey.Wrap(configShard->firstKey);
                        quorumProcessor->TrySplitShard(configShard->parentShardID,
                         configShard->shardID, splitKey);
                    }
                }
            }
            continue;
        }
        FOREACH(itNodeID, configQuorum->inactiveNodes)
        {
            if (*itNodeID == MY_NODEID)
            {
                found = true;
                break;
            }
        }
        if (found)
        {
            quorumProcessor->RegisterPaxosID(configQuorum->paxosID);
            continue;
        }

        next = quorumProcessors.Remove(quorumProcessor);
        delete quorumProcessor;
    }

    // check changes in active or inactive node list
    FOREACH(configQuorum, configState.quorums)
    {
        FOREACH(itNodeID, configQuorum->activeNodes)
        {
            if (*itNodeID == MY_NODEID)
            {
                ConfigureQuorum(configQuorum); // also creates quorum
                break;
            }
        }

        FOREACH(itNodeID, configQuorum->inactiveNodes)
        {
            if (*itNodeID == MY_NODEID)
            {
                ConfigureQuorum(configQuorum); // also creates quorum
                quorumProcessor = GetQuorumProcessor(configQuorum->quorumID);
                assert(quorumProcessor != NULL);
                quorumProcessor->TryReplicationCatchup();
                break;
            }
        }
    }

    databaseManager.RemoveDeletedTables();
    databaseManager.RemoveDeletedDatabases();
}

void ShardServer::ConfigureQuorum(ConfigQuorum* configQuorum)
{
    uint64_t                quorumID;
    uint64_t*               itNodeID;
    ConfigShardServer*      shardServer;
    ShardQuorumProcessor*   quorumProcessor;

    Log_Trace();

    quorumID = configQuorum->quorumID;
    quorumProcessor = GetQuorumProcessor(quorumID);
    if (quorumProcessor == NULL)
    {
        databaseManager.SetQuorumShards(quorumID);

        quorumProcessor = new ShardQuorumProcessor;
        quorumProcessor->Init(configQuorum, this);

        quorumProcessors.Append(quorumProcessor);
        FOREACH(itNodeID, configQuorum->activeNodes)
        {
            shardServer = configState.GetShardServer(*itNodeID);
            assert(shardServer != NULL);
            CONTEXT_TRANSPORT->AddNode(*itNodeID, shardServer->endpoint);
        }
    }
    else
    {
        quorumProcessor->SetActiveNodes(configQuorum->activeNodes);

        // add nodes to CONTEXT_TRANSPORT
        FOREACH(itNodeID, configQuorum->activeNodes)
        {
            shardServer = configState.GetShardServer(*itNodeID);
            assert(shardServer != NULL);
            CONTEXT_TRANSPORT->AddNode(*itNodeID, shardServer->endpoint);
        }
    }

    databaseManager.SetShards(configQuorum->shards);
}

unsigned ShardServer::GetHTTPPort()
{
    return configFile.GetIntValue("http.port", 8080);
}

unsigned  ShardServer::GetSDBPPort()
{
    return configFile.GetIntValue("sdbp.port", 7080);
}
<|endoftext|>


<commit_before>#ifndef TESTERDRIVER_H
#define TESTERDRIVER_H

#include <iostream>
#include <string.h>
using namespace std;
#include "wrapperregdriver.h"
#include "TesterWrapper.h"

// enable verbose reg read/writes and Chisel HW printfs
// remember to compile with -std=c++11 for Chisel HW printfs to work
#ifdef DEBUG
#warning "Compiling emulation with full debug support"
#define __TESTERDRIVER_DEBUG_PRINT(x) (cout << x << endl)
#define __TESTERDRIVER_DEBUG(x) (x)
#elif DEBUG_HW
#warning "Compiling emulation with Chisel printf support"
#define __TESTERDRIVER_DEBUG_PRINT(x) (0)
#define __TESTERDRIVER_DEBUG(x) (x)
#else
#define __TESTERDRIVER_DEBUG_PRINT(x) (0)
#define __TESTERDRIVER_DEBUG(x) (0)
#endif

// register driver for the Tester platform, using the Chisel-generated C++ model to
// interface with the accelerator model
// note that TesterWrapper.h must be generated for each new accelerator, it is the
// model header not just for the wrapper, but the entire system (wrapper+accel)

class TesterRegDriver : public WrapperRegDriver {
public:
  TesterRegDriver() {m_freePtr = 0;}

  virtual void attach(const char * name) {
    m_inst = new TesterWrapper_t();
    // get # words in the memory
    m_memWords = m_inst->TesterWrapper__mem.length();
    // initialize and reset the model
    m_inst->init();
    reset();
    m_regCount = m_inst->TesterWrapper__io_regFileIF_regCount.to_ulong();
  }

  virtual void detach() { delete m_inst; }

  virtual void copyBufferHostToAccel(void * hostBuffer, void * accelBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    __TESTERDRIVER_DEBUG_PRINT("host2accel(" << (uint64_t) hostBuffer << " -> " << accelBufBase << " : " << numBytes << " bytes)");

    if((numBytes % 8 == 0) && (accelBufBase % 8 == 0))
      alignedCopyBufferHostToAccel(hostBuffer, accelBuffer, numBytes);
    else {
      // align base and size
      uint64_t alignedBase = accelBufBase - (accelBufBase % 8);
      uint64_t startDiff = accelBufBase - alignedBase;
      unsigned int alignedSize = (startDiff + numBytes + 7) / 8 * 8;
      // copy containing block into host memory
      char * tmp = new char[alignedSize];
      alignedCopyBufferAccelToHost((void *)alignedBase, (void *) tmp, alignedSize);
      // do host-to-host unaligned copy
      memcpy((void *)&tmp[startDiff], hostBuffer, numBytes);
      // write containing block back to accel memory
      alignedCopyBufferHostToAccel((void *)tmp, (void *)alignedBase, alignedSize);
      delete [] tmp;
    }
  }

  virtual void copyBufferAccelToHost(void * accelBuffer, void * hostBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    __TESTERDRIVER_DEBUG_PRINT("accel2host(" << accelBufBase << " -> " << (uint64_t) hostBuffer << " : " << numBytes << " bytes)");

    if((numBytes % 8 == 0) && (accelBufBase % 8 == 0))
      alignedCopyBufferAccelToHost(accelBuffer, hostBuffer, numBytes);
    else {
      // implement unaligned accel-to-host
      // align base and size
      uint64_t alignedBase = accelBufBase - (accelBufBase % 8);
      uint64_t startDiff = accelBufBase - alignedBase;
      unsigned int alignedSize = (startDiff + numBytes + 7) / 8 * 8;
      // copy containing block into host memory
      char * tmp = new char[alignedSize];
      alignedCopyBufferAccelToHost((void *)alignedBase, (void *) tmp, alignedSize);
      // do host-to-host unaligned copy
      memcpy(hostBuffer, (void *)&tmp[startDiff],numBytes);
      delete [] tmp;
    }
  }

  virtual void * allocAccelBuffer(unsigned int numBytes) {
    // all this assumes allocation and mem word size of 8 bytes
    // round requested size to nearest multiple of 8
    unsigned int actualAllocSize = (numBytes + 7) / 8 * 8;
    void * accelBuf = (void *) m_freePtr;
    // update free pointer and sanity check
    m_freePtr += actualAllocSize;
    if(m_freePtr > m_memWords * 8)
      throw "Not enough memory in allocAccelBuffer";
    __TESTERDRIVER_DEBUG_PRINT("allocAccelBuffer(" << numBytes << ", alloc " << actualAllocSize <<") = " << (uint64_t) accelBuf);

    return accelBuf;
  }

  // register access methods for the platform wrapper
  virtual void writeReg(unsigned int regInd, AccelReg regValue) {
    __TESTERDRIVER_DEBUG_PRINT("writeReg(" << regInd << ", " << regValue  << ") ");

    m_inst->TesterWrapper__io_regFileIF_cmd_bits_writeData = regValue;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_write  = 1;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_regID = regInd;
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 1;
    step();
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 0;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_write = 0;
    step(5);  // extra delay on write completion to be realistic
  }

  virtual AccelReg readReg(unsigned int regInd) {
    AccelReg ret;

    m_inst->TesterWrapper__io_regFileIF_cmd_bits_regID = regInd;
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 1;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_read = 1;
    step(); // don't actually need 1 cycle, regfile reads are combinational

    if(!m_inst->TesterWrapper__io_regFileIF_readData_valid.to_bool())
      throw "Could not read register";

    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 0;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_read = 0;

    ret = m_inst->TesterWrapper__io_regFileIF_readData_bits.to_ulong();

    __TESTERDRIVER_DEBUG_PRINT("readReg(" << regInd << ") = " << ret);

    step(5);  // extra delay on read completion to be realistic

    return ret;
  }

  void printAllRegs() {
    for(unsigned int i = 0; i < m_regCount; i++)  {
        AccelReg val = readReg(i);
        cout << "Reg " << i << " = " << val << " (0x" << hex << val << dec << ")" << endl;
      }

  }

protected:
  TesterWrapper_t * m_inst;
  unsigned int m_memWords;
  unsigned int m_regCount;
  uint64_t m_freePtr;

  void reset() {
    m_inst->clock(1);
    m_inst->clock(0);
    // Chisel c++ backend requires this workaround to get out the correct values
    m_inst->clock_lo(0);
  }

  void step(int n = 1) {
    for(int i = 0; i < n; i++) {
      m_inst->clock(0);
      // Chisel c++ backend requires this workaround to get out the correct values
      m_inst->clock_lo(0);
      __TESTERDRIVER_DEBUG(m_inst->print(cout));
    }
  }

  void memWrite(uint64_t addr, uint64_t value) {
    m_inst->TesterWrapper__io_memAddr = addr;
    m_inst->TesterWrapper__io_memWriteData = value;
    m_inst->TesterWrapper__io_memWriteEn = 1;
    step();
    m_inst->TesterWrapper__io_memWriteEn = 0;
  }

  uint64_t memRead(uint64_t addr) {
    m_inst->TesterWrapper__io_memAddr = addr;
    step();
    uint64_t ret = m_inst->TesterWrapper__io_memReadData[0];
    return ret;
  }

  // "aligned" copy functions, where accel ptr start and size are guaranteed to be 8-aligned
  void alignedCopyBufferHostToAccel(void * hostBuffer, void * accelBuffer, unsigned int numBytes) {
    uint64_t * host_buf = (uint64_t *) hostBuffer;
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    for(unsigned int i = 0; i < numBytes/8; i++)
        memWrite(accelBufBase + i*8, host_buf[i]);
  }

  void alignedCopyBufferAccelToHost(void * accelBuffer, void * hostBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    uint64_t * readBuf = (uint64_t *) hostBuffer;
    for(unsigned int i = 0; i < numBytes/8; i++)
      readBuf[i] = memRead(accelBufBase + i*8);
  }
};

#endif
<commit_msg>prevent double free in TesterDriver<commit_after>#ifndef TESTERDRIVER_H
#define TESTERDRIVER_H

#include <iostream>
#include <string.h>
using namespace std;
#include "wrapperregdriver.h"
#include "TesterWrapper.h"

// enable verbose reg read/writes and Chisel HW printfs
// remember to compile with -std=c++11 for Chisel HW printfs to work
#ifdef DEBUG
#warning "Compiling emulation with full debug support"
#define __TESTERDRIVER_DEBUG_PRINT(x) (cout << x << endl)
#define __TESTERDRIVER_DEBUG(x) (x)
#elif DEBUG_HW
#warning "Compiling emulation with Chisel printf support"
#define __TESTERDRIVER_DEBUG_PRINT(x) (0)
#define __TESTERDRIVER_DEBUG(x) (x)
#else
#define __TESTERDRIVER_DEBUG_PRINT(x) (0)
#define __TESTERDRIVER_DEBUG(x) (0)
#endif

// register driver for the Tester platform, using the Chisel-generated C++ model to
// interface with the accelerator model
// note that TesterWrapper.h must be generated for each new accelerator, it is the
// model header not just for the wrapper, but the entire system (wrapper+accel)

class TesterRegDriver : public WrapperRegDriver {
public:
  TesterRegDriver() {m_inst = 0; m_freePtr = 0;}

  virtual void attach(const char * name) {
    m_inst = new TesterWrapper_t();
    // get # words in the memory
    m_memWords = m_inst->TesterWrapper__mem.length();
    // initialize and reset the model
    m_inst->init();
    reset();
    m_regCount = m_inst->TesterWrapper__io_regFileIF_regCount.to_ulong();
  }

  virtual void detach() {
    if(m_inst) {
      delete m_inst;
      m_inst = 0;
    }
  }

  virtual void copyBufferHostToAccel(void * hostBuffer, void * accelBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    __TESTERDRIVER_DEBUG_PRINT("host2accel(" << (uint64_t) hostBuffer << " -> " << accelBufBase << " : " << numBytes << " bytes)");

    if((numBytes % 8 == 0) && (accelBufBase % 8 == 0))
      alignedCopyBufferHostToAccel(hostBuffer, accelBuffer, numBytes);
    else {
      // align base and size
      uint64_t alignedBase = accelBufBase - (accelBufBase % 8);
      uint64_t startDiff = accelBufBase - alignedBase;
      unsigned int alignedSize = (startDiff + numBytes + 7) / 8 * 8;
      // copy containing block into host memory
      char * tmp = new char[alignedSize];
      alignedCopyBufferAccelToHost((void *)alignedBase, (void *) tmp, alignedSize);
      // do host-to-host unaligned copy
      memcpy((void *)&tmp[startDiff], hostBuffer, numBytes);
      // write containing block back to accel memory
      alignedCopyBufferHostToAccel((void *)tmp, (void *)alignedBase, alignedSize);
      delete [] tmp;
    }
  }

  virtual void copyBufferAccelToHost(void * accelBuffer, void * hostBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    __TESTERDRIVER_DEBUG_PRINT("accel2host(" << accelBufBase << " -> " << (uint64_t) hostBuffer << " : " << numBytes << " bytes)");

    if((numBytes % 8 == 0) && (accelBufBase % 8 == 0))
      alignedCopyBufferAccelToHost(accelBuffer, hostBuffer, numBytes);
    else {
      // implement unaligned accel-to-host
      // align base and size
      uint64_t alignedBase = accelBufBase - (accelBufBase % 8);
      uint64_t startDiff = accelBufBase - alignedBase;
      unsigned int alignedSize = (startDiff + numBytes + 7) / 8 * 8;
      // copy containing block into host memory
      char * tmp = new char[alignedSize];
      alignedCopyBufferAccelToHost((void *)alignedBase, (void *) tmp, alignedSize);
      // do host-to-host unaligned copy
      memcpy(hostBuffer, (void *)&tmp[startDiff],numBytes);
      delete [] tmp;
    }
  }

  virtual void * allocAccelBuffer(unsigned int numBytes) {
    // all this assumes allocation and mem word size of 8 bytes
    // round requested size to nearest multiple of 8
    unsigned int actualAllocSize = (numBytes + 7) / 8 * 8;
    void * accelBuf = (void *) m_freePtr;
    // update free pointer and sanity check
    m_freePtr += actualAllocSize;
    if(m_freePtr > m_memWords * 8)
      throw "Not enough memory in allocAccelBuffer";
    __TESTERDRIVER_DEBUG_PRINT("allocAccelBuffer(" << numBytes << ", alloc " << actualAllocSize <<") = " << (uint64_t) accelBuf);

    return accelBuf;
  }

  // register access methods for the platform wrapper
  virtual void writeReg(unsigned int regInd, AccelReg regValue) {
    __TESTERDRIVER_DEBUG_PRINT("writeReg(" << regInd << ", " << regValue  << ") ");

    m_inst->TesterWrapper__io_regFileIF_cmd_bits_writeData = regValue;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_write  = 1;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_regID = regInd;
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 1;
    step();
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 0;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_write = 0;
    step(5);  // extra delay on write completion to be realistic
  }

  virtual AccelReg readReg(unsigned int regInd) {
    AccelReg ret;

    m_inst->TesterWrapper__io_regFileIF_cmd_bits_regID = regInd;
    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 1;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_read = 1;
    step(); // don't actually need 1 cycle, regfile reads are combinational

    if(!m_inst->TesterWrapper__io_regFileIF_readData_valid.to_bool())
      throw "Could not read register";

    m_inst->TesterWrapper__io_regFileIF_cmd_valid = 0;
    m_inst->TesterWrapper__io_regFileIF_cmd_bits_read = 0;

    ret = m_inst->TesterWrapper__io_regFileIF_readData_bits.to_ulong();

    __TESTERDRIVER_DEBUG_PRINT("readReg(" << regInd << ") = " << ret);

    step(5);  // extra delay on read completion to be realistic

    return ret;
  }

  void printAllRegs() {
    for(unsigned int i = 0; i < m_regCount; i++)  {
        AccelReg val = readReg(i);
        cout << "Reg " << i << " = " << val << " (0x" << hex << val << dec << ")" << endl;
      }

  }

protected:
  TesterWrapper_t * m_inst;
  unsigned int m_memWords;
  unsigned int m_regCount;
  uint64_t m_freePtr;

  void reset() {
    m_inst->clock(1);
    m_inst->clock(0);
    // Chisel c++ backend requires this workaround to get out the correct values
    m_inst->clock_lo(0);
  }

  void step(int n = 1) {
    for(int i = 0; i < n; i++) {
      m_inst->clock(0);
      // Chisel c++ backend requires this workaround to get out the correct values
      m_inst->clock_lo(0);
      __TESTERDRIVER_DEBUG(m_inst->print(cout));
    }
  }

  void memWrite(uint64_t addr, uint64_t value) {
    m_inst->TesterWrapper__io_memAddr = addr;
    m_inst->TesterWrapper__io_memWriteData = value;
    m_inst->TesterWrapper__io_memWriteEn = 1;
    step();
    m_inst->TesterWrapper__io_memWriteEn = 0;
  }

  uint64_t memRead(uint64_t addr) {
    m_inst->TesterWrapper__io_memAddr = addr;
    step();
    uint64_t ret = m_inst->TesterWrapper__io_memReadData[0];
    return ret;
  }

  // "aligned" copy functions, where accel ptr start and size are guaranteed to be 8-aligned
  void alignedCopyBufferHostToAccel(void * hostBuffer, void * accelBuffer, unsigned int numBytes) {
    uint64_t * host_buf = (uint64_t *) hostBuffer;
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    for(unsigned int i = 0; i < numBytes/8; i++)
        memWrite(accelBufBase + i*8, host_buf[i]);
  }

  void alignedCopyBufferAccelToHost(void * accelBuffer, void * hostBuffer, unsigned int numBytes) {
    uint64_t accelBufBase = (uint64_t) accelBuffer;
    uint64_t * readBuf = (uint64_t *) hostBuffer;
    for(unsigned int i = 0; i < numBytes/8; i++)
      readBuf[i] = memRead(accelBufBase + i*8);
  }
};

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) The Shogun Machine Learning Toolbox
 * Written (w) 2014 Khaled Nasr
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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.
 *
 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the Shogun Development Team.
 */

#include <shogun/lib/config.h>

#ifdef HAVE_LINALG_LIB
#include <shogun/mathematics/linalg/linalg.h>
#include <shogun/lib/SGMatrix.h>
#include <shogun/lib/SGVector.h>
#include <gtest/gtest.h>

#ifdef HAVE_EIGEN3
#include <shogun/mathematics/eigen3.h>
#endif // HAVE_EIGEN3

#ifdef HAVE_VIENNACL
#include <shogun/lib/GPUMatrix.h>
#include <shogun/lib/GPUVector.h>
#endif

using namespace shogun;

#ifdef HAVE_EIGEN3
TEST(SetRowsConst, eigen3_backend)
{
	SGMatrix<float64_t> A(3,4);
	SGVector<float64_t> v(A.num_rows);

	for (int32_t i=v.vlen; i<3; i++)
		v[i] = i;

	linalg::set_rows_const<linalg::Backend::EIGEN3>(A, v);

	for (int32_t i=0; i<A.num_rows; i++)
		for (int32_t j=0; j<A.num_cols; j++)
			EXPECT_EQ(A(i,j), v[i]);
}
#endif // HAVE_EIGEN3

#ifdef HAVE_VIENNACL
TEST(SetRowsConst, viennacl_backend)
{
	CGPUMatrix<float64_t> A(3,4);
	CGPUVector<float64_t> v(A.num_rows);

	for (int32_t i=v.vlen; i<3; i++)
		v[i] = i;

	linalg::set_rows_const<linalg::Backend::VIENNACL>(A, v);

	for (int32_t i=0; i<A.num_rows; i++)
		for (int32_t j=0; j<A.num_cols; j++)
			EXPECT_EQ(A(i,j), v[i]);
}
#endif // HAVE_VIENNACL

#endif // HAVE_LINALG_LIB
<commit_msg>fixed issue  #2464<commit_after>/*
 * Copyright (c) The Shogun Machine Learning Toolbox
 * Written (w) 2014 Khaled Nasr
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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.
 *
 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the Shogun Development Team.
 */

#include <shogun/lib/config.h>

#ifdef HAVE_LINALG_LIB
#include <shogun/mathematics/linalg/linalg.h>
#include <shogun/lib/SGMatrix.h>
#include <shogun/lib/SGVector.h>
#include <gtest/gtest.h>

#ifdef HAVE_EIGEN3
#include <shogun/mathematics/eigen3.h>
#endif // HAVE_EIGEN3

#ifdef HAVE_VIENNACL
#include <shogun/lib/GPUMatrix.h>
#include <shogun/lib/GPUVector.h>
#endif

using namespace shogun;

#ifdef HAVE_EIGEN3
TEST(SetRowsConst, eigen3_backend)
{
	SGMatrix<float64_t> A(3,4);
	SGVector<float64_t> v(A.num_rows);

	for (int32_t i=0; i<v.vlen; i++)
		v[i] = i;

	linalg::set_rows_const<linalg::Backend::EIGEN3>(A, v);

	for (int32_t i=0; i<A.num_rows; i++)
		for (int32_t j=0; j<A.num_cols; j++)
			EXPECT_EQ(A(i,j), v[i]);
}
#endif // HAVE_EIGEN3

#ifdef HAVE_VIENNACL
TEST(SetRowsConst, viennacl_backend)
{
	CGPUMatrix<float64_t> A(3,4);
	CGPUVector<float64_t> v(A.num_rows);

	for (int32_t i=0; i<v.vlen; i++)
		v[i] = i;

	linalg::set_rows_const<linalg::Backend::VIENNACL>(A, v);

	for (int32_t i=0; i<A.num_rows; i++)
		for (int32_t j=0; j<A.num_cols; j++)
			EXPECT_EQ(A(i,j), v[i]);
}
#endif // HAVE_VIENNACL

#endif // HAVE_LINALG_LIB
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in LICENSE

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "EC_VolumeTrigger.h"
#include "EC_RigidBody.h"
#include "EC_Placeable.h"
#include "Entity.h"
#include "Scene/Scene.h"
#include "PhysicsModule.h"
#include "PhysicsWorld.h"
#include "PhysicsUtils.h"
#include "LoggingFunctions.h"
#include "Profiler.h"

#include <OgreAxisAlignedBox.h>
#include <QMap>
#include <btBulletDynamicsCommon.h>

#include "MemoryLeakCheck.h"

using namespace Physics;

EC_VolumeTrigger::EC_VolumeTrigger(Scene* scene) :
    IComponent(scene),
    byPivot(this, "By Pivot", false),
    entities(this, "Entities")
{
    connect(this, SIGNAL(ParentEntitySet()), this, SLOT(UpdateSignals()), Qt::UniqueConnection);
}

EC_VolumeTrigger::~EC_VolumeTrigger()
{
}

QList<EntityWeakPtr> EC_VolumeTrigger::GetEntitiesInside() const
{
    QList<EntityWeakPtr> ret;
    for(EntitiesWithinVolumeMap::const_iterator it = entities_.begin(); it != entities_.end(); ++it)
        ret.push_back(it->first);
    return ret;
}

int EC_VolumeTrigger::GetNumEntitiesInside() const
{
    return entities_.size();
}

Entity* EC_VolumeTrigger::GetEntityInside(int idx) const
{
    if (idx >=0 && (size_t)idx < entities_.size())
    {
        int currentIndex = 0;
        for(EntitiesWithinVolumeMap::const_iterator it = entities_.begin(); it != entities_.end(); ++it)
        {
            if (currentIndex == idx)
                return it->first.lock().get();
            ++currentIndex;
        }
    }
    return 0;
}

QStringList EC_VolumeTrigger::GetEntityNamesInside() const
{
    QStringList entitynames;
    for(EntitiesWithinVolumeMap::const_iterator it = entities_.begin(); it != entities_.end(); ++it)
        if (it->first.expired())
            entitynames.append(it->first.lock()->Name());
    return entitynames;
}

float EC_VolumeTrigger::GetEntityInsidePercent(const Entity *entity) const
{
    if (entity)
    {
        shared_ptr<EC_RigidBody> otherRigidbody = entity->GetComponent<EC_RigidBody>();

        shared_ptr<EC_RigidBody> rigidbody = rigidbody_.lock();
        if (rigidbody && otherRigidbody)
        {
            float3 thisBoxMin, thisBoxMax;
            rigidbody->GetAabbox(thisBoxMin, thisBoxMax);

            float3 otherBoxMin, otherBoxMax;
            otherRigidbody->GetAabbox(otherBoxMin, otherBoxMax);

            Ogre::AxisAlignedBox thisBox(thisBoxMin.x, thisBoxMin.y, thisBoxMin.z, thisBoxMax.x, thisBoxMax.y, thisBoxMax.z);
            Ogre::AxisAlignedBox otherBox(otherBoxMin.x, otherBoxMin.y, otherBoxMin.z, otherBoxMax.x, otherBoxMax.y, otherBoxMax.z);

            return (thisBox.intersection(otherBox).volume() / otherBox.volume());
        } else
            LogWarning("EC_VolumeTrigger: no EC_RigidBody for entity or volume.");
    }
    return 0.0f;
}

float EC_VolumeTrigger::GetEntityInsidePercentByName(const QString &name) const
{
    for(EntitiesWithinVolumeMap::const_iterator it = entities_.begin(); it != entities_.end(); ++it)
        if (!it->first.expired() && it->first.lock()->Name().compare(name) == 0)
            return GetEntityInsidePercent(it->first.lock().get());
    return 0.f;
}

bool EC_VolumeTrigger::IsInterestingEntity(const QString &name) const
{
    PROFILE(EC_VolumeTrigger_IsInterestingEntity); ///\todo The performance of this function feels really fishy - on each physics collision, we iterate through a list performing string comparisons.

    QVariantList interestingEntities = entities.Get();
    if (interestingEntities.isEmpty())
        return true;

    foreach (QVariant intname, interestingEntities)
    {
        if (intname.toString().compare(name) == 0)
        {
            return true;
        }
    }
    return false;
}

bool EC_VolumeTrigger::IsPivotInside(Entity *entity) const
{
    shared_ptr<EC_Placeable> placeable = entity->GetComponent<EC_Placeable>();
    shared_ptr<EC_RigidBody> rigidbody = rigidbody_.lock();
    if (placeable && rigidbody)
    {
        const Transform& trans = placeable->transform.Get();
        const float3& pivot = trans.pos;

        return ( RayTestSingle(float3(pivot.x, pivot.y - 1e7f, pivot.z), pivot, rigidbody->GetRigidBody()) &&
                 RayTestSingle(float3(pivot.x, pivot.y + 1e7f, pivot.z), pivot, rigidbody->GetRigidBody()) );
    }
    LogWarning("EC_VolumeTrigger::IsPivotInside(): entity has no EC_Placeable or volume has no EC_RigidBody.");
    return false;
}

bool EC_VolumeTrigger::IsInsideVolume(const float3& point) const
{
    shared_ptr<EC_RigidBody> rigidbody = rigidbody_.lock();
    if (!rigidbody)
    {
        LogWarning("Volume has no EC_RigidBody.");
        return false;
    }

    return RayTestSingle(float3(point.x, point.y - 1e7f, point.z), point, rigidbody->GetRigidBody()) &&
           RayTestSingle(float3(point.x, point.y + 1e7f, point.z), point, rigidbody->GetRigidBody());
}

void EC_VolumeTrigger::AttributesChanged()
{
    /// \todo Attribute updates not handled yet, there are a bit too many problems of what signals to send after the update -cm

    //if (mass.ValueChanged())
    //    ReadBody();
}

void EC_VolumeTrigger::UpdateSignals()
{
    Entity* parent = ParentEntity();
    if (!parent)
        return;

    connect(parent, SIGNAL(ComponentAdded(IComponent*, AttributeChange::Type)), this, SLOT(CheckForRigidBody()), Qt::UniqueConnection);

    Scene* scene = parent->ParentScene();
    PhysicsWorld* world = scene->GetWorld<PhysicsWorld>().get();
    if (world)
        connect(world, SIGNAL(Updated(float)), this, SLOT(OnPhysicsUpdate()), Qt::UniqueConnection);
}

void EC_VolumeTrigger::CheckForRigidBody()
{
    Entity* parent = ParentEntity();
    if (!parent)
        return;

    if (!rigidbody_.lock())
    {
        shared_ptr<EC_RigidBody> rigidbody = parent->GetComponent<EC_RigidBody>();
        if (rigidbody)
        {
            rigidbody_ = rigidbody;
            connect(rigidbody.get(), SIGNAL(PhysicsCollision(Entity*, const float3&, const float3&, float, float, bool)),
                this, SLOT(OnPhysicsCollision(Entity*, const float3&, const float3&, float, float, bool)), Qt::UniqueConnection);
        }
    }
}

void EC_VolumeTrigger::OnPhysicsUpdate()
{
    PROFILE(EC_VolumeTrigger_OnPhysicsUpdate);
    for(EntitiesWithinVolumeMap::iterator it = entities_.begin(); it != entities_.end(); ++it)
    {
        if (!it->first.expired())
        {
            EntityPtr entity = it->first.lock();
            bool active = true;
            // inactive rigid bodies don't generate collisions, so before emitting EntityLeave -event, make sure the body is active.
            if (entity)
            {
                shared_ptr<EC_RigidBody> rigidbody = entity->GetComponent<EC_RigidBody>();
                if (rigidbody)
                    active = rigidbody->IsActive();
            }
            if (active)
            {
                entities_.erase(it);

                if (entity)
                {
                    emit entityLeave(entity.get());
                    disconnect(entity.get(), SIGNAL(EntityRemoved(Entity*, AttributeChange::Type)), this, SLOT(OnEntityRemoved(Entity*)));
                }
                continue;
            }
        } else
        {
            // Age the internal bool from true to false to signal that this collision is now an old one.
            entities_[it->first] = false;
        }
    }
}

void EC_VolumeTrigger::OnPhysicsCollision(Entity* otherEntity, const float3& position, const float3& normal, float distance, float impulse, bool newCollision)
{
    PROFILE(EC_VolumeTrigger_OnPhysicsCollision);

    assert(otherEntity && "Physics collision with no entity.");

    if (!entities.Get().isEmpty() && !IsInterestingEntity(otherEntity->Name()))
        return;

    EntityPtr entity = otherEntity->shared_from_this();

    // If byPivot attribute is enabled, we require the object pivot to enter the volume trigger area.
    // Otherwise, we react on each physics collision message (i.e. we accept if the volumetrigger and other entity just touch).
    if (byPivot.Get() && !IsPivotInside(entity.get()))
        return;

    if (newCollision)
    {
        // make sure the entity isn't already inside the volume
        if (entities_.find(entity) == entities_.end())
        {
            emit entityEnter(otherEntity);
            connect(otherEntity, SIGNAL(EntityRemoved(Entity*, AttributeChange::Type)), this, SLOT(OnEntityRemoved(Entity*)), Qt::UniqueConnection);
        }
    }
    entities_[entity] = true;
}

/** Called when the given entity is deleted from the scene. In that case, remove the Entity immediately from our tracking data structure (and signal listeners). */
void EC_VolumeTrigger::OnEntityRemoved(Entity *entity)
{
    assert(entity);
    EntitiesWithinVolumeMap::iterator i = entities_.find(entity->shared_from_this());
    if (i != entities_.end())
    {
        entities_.erase(i);
        emit entityLeave(entity);
    }
}
<commit_msg>Fixed EC_VolumeTrigger iteration crash. Fixed EC_VolumeTrigger sending the leave signal multiple times.<commit_after>// For conditions of distribution and use, see copyright notice in LICENSE

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "EC_VolumeTrigger.h"
#include "EC_RigidBody.h"
#include "EC_Placeable.h"
#include "Entity.h"
#include "Scene/Scene.h"
#include "PhysicsModule.h"
#include "PhysicsWorld.h"
#include "PhysicsUtils.h"
#include "LoggingFunctions.h"
#include "Profiler.h"

#include <OgreAxisAlignedBox.h>
#include <QMap>
#include <btBulletDynamicsCommon.h>

#include "MemoryLeakCheck.h"

using namespace Physics;

EC_VolumeTrigger::EC_VolumeTrigger(Scene* scene) :
    IComponent(scene),
    byPivot(this, "By Pivot", false),
    entities(this, "Entities")
{
    connect(this, SIGNAL(ParentEntitySet()), this, SLOT(UpdateSignals()), Qt::UniqueConnection);
}

EC_VolumeTrigger::~EC_VolumeTrigger()
{
}

QList<EntityWeakPtr> EC_VolumeTrigger::GetEntitiesInside() const
{
    QList<EntityWeakPtr> ret;
    for(EntitiesWithinVolumeMap::const_iterator it = entities_.begin(); it != entities_.end(); ++it)
        ret.push_back(it->first);
    return ret;
}

int EC_VolumeTrigger::GetNumEntitiesInside() const
{
    return entities_.size();
}

Entity* EC_VolumeTrigger::GetEntityInside(int idx) const
{
    if (idx >=0 && (size_t)idx < entities_.size())
    {
        int currentIndex = 0;
        for(EntitiesWithinVolumeMap::const_iterator it = entities_.begin(); it != entities_.end(); ++it)
        {
            if (currentIndex == idx)
                return it->first.lock().get();
            ++currentIndex;
        }
    }
    return 0;
}

QStringList EC_VolumeTrigger::GetEntityNamesInside() const
{
    QStringList entitynames;
    for(EntitiesWithinVolumeMap::const_iterator it = entities_.begin(); it != entities_.end(); ++it)
        if (!it->first.expired())
            entitynames.append(it->first.lock()->Name());
    return entitynames;
}

float EC_VolumeTrigger::GetEntityInsidePercent(const Entity *entity) const
{
    if (entity)
    {
        shared_ptr<EC_RigidBody> otherRigidbody = entity->GetComponent<EC_RigidBody>();

        shared_ptr<EC_RigidBody> rigidbody = rigidbody_.lock();
        if (rigidbody && otherRigidbody)
        {
            float3 thisBoxMin, thisBoxMax;
            rigidbody->GetAabbox(thisBoxMin, thisBoxMax);

            float3 otherBoxMin, otherBoxMax;
            otherRigidbody->GetAabbox(otherBoxMin, otherBoxMax);

            Ogre::AxisAlignedBox thisBox(thisBoxMin.x, thisBoxMin.y, thisBoxMin.z, thisBoxMax.x, thisBoxMax.y, thisBoxMax.z);
            Ogre::AxisAlignedBox otherBox(otherBoxMin.x, otherBoxMin.y, otherBoxMin.z, otherBoxMax.x, otherBoxMax.y, otherBoxMax.z);

            return (thisBox.intersection(otherBox).volume() / otherBox.volume());
        } else
            LogWarning("EC_VolumeTrigger: no EC_RigidBody for entity or volume.");
    }
    return 0.0f;
}

float EC_VolumeTrigger::GetEntityInsidePercentByName(const QString &name) const
{
    for(EntitiesWithinVolumeMap::const_iterator it = entities_.begin(); it != entities_.end(); ++it)
        if (!it->first.expired() && it->first.lock()->Name().compare(name) == 0)
            return GetEntityInsidePercent(it->first.lock().get());
    return 0.f;
}

bool EC_VolumeTrigger::IsInterestingEntity(const QString &name) const
{
    PROFILE(EC_VolumeTrigger_IsInterestingEntity); ///\todo The performance of this function feels really fishy - on each physics collision, we iterate through a list performing string comparisons.

    QVariantList interestingEntities = entities.Get();
    if (interestingEntities.isEmpty())
        return true;

    foreach (QVariant intname, interestingEntities)
    {
        if (intname.toString().compare(name) == 0)
        {
            return true;
        }
    }
    return false;
}

bool EC_VolumeTrigger::IsPivotInside(Entity *entity) const
{
    shared_ptr<EC_Placeable> placeable = entity->GetComponent<EC_Placeable>();
    shared_ptr<EC_RigidBody> rigidbody = rigidbody_.lock();
    if (placeable && rigidbody)
    {
        const Transform& trans = placeable->transform.Get();
        const float3& pivot = trans.pos;

        return ( RayTestSingle(float3(pivot.x, pivot.y - 1e7f, pivot.z), pivot, rigidbody->GetRigidBody()) &&
                 RayTestSingle(float3(pivot.x, pivot.y + 1e7f, pivot.z), pivot, rigidbody->GetRigidBody()) );
    }
    LogWarning("EC_VolumeTrigger::IsPivotInside(): entity has no EC_Placeable or volume has no EC_RigidBody.");
    return false;
}

bool EC_VolumeTrigger::IsInsideVolume(const float3& point) const
{
    shared_ptr<EC_RigidBody> rigidbody = rigidbody_.lock();
    if (!rigidbody)
    {
        LogWarning("Volume has no EC_RigidBody.");
        return false;
    }

    return RayTestSingle(float3(point.x, point.y - 1e7f, point.z), point, rigidbody->GetRigidBody()) &&
           RayTestSingle(float3(point.x, point.y + 1e7f, point.z), point, rigidbody->GetRigidBody());
}

void EC_VolumeTrigger::AttributesChanged()
{
    /// \todo Attribute updates not handled yet, there are a bit too many problems of what signals to send after the update -cm

    //if (mass.ValueChanged())
    //    ReadBody();
}

void EC_VolumeTrigger::UpdateSignals()
{
    Entity* parent = ParentEntity();
    if (!parent)
        return;

    connect(parent, SIGNAL(ComponentAdded(IComponent*, AttributeChange::Type)), this, SLOT(CheckForRigidBody()), Qt::UniqueConnection);

    Scene* scene = parent->ParentScene();
    PhysicsWorld* world = scene->GetWorld<PhysicsWorld>().get();
    if (world)
        connect(world, SIGNAL(Updated(float)), this, SLOT(OnPhysicsUpdate()), Qt::UniqueConnection);
}

void EC_VolumeTrigger::CheckForRigidBody()
{
    Entity* parent = ParentEntity();
    if (!parent)
        return;

    if (!rigidbody_.lock())
    {
        shared_ptr<EC_RigidBody> rigidbody = parent->GetComponent<EC_RigidBody>();
        if (rigidbody)
        {
            rigidbody_ = rigidbody;
            connect(rigidbody.get(), SIGNAL(PhysicsCollision(Entity*, const float3&, const float3&, float, float, bool)),
                this, SLOT(OnPhysicsCollision(Entity*, const float3&, const float3&, float, float, bool)), Qt::UniqueConnection);
        }
    }
}

void EC_VolumeTrigger::OnPhysicsUpdate()
{
    PROFILE(EC_VolumeTrigger_OnPhysicsUpdate);

    for(EntitiesWithinVolumeMap::iterator it = entities_.begin(); it != entities_.end();)
    {
        bool remove = false;

        // Entity was destroyed without us knowing? Remove from map in that case
        if (it->first.expired())
            remove = true;
        else
        {
            // If collision is old, remove the entity if its rigidbody is active
            // (inactive rigidbodies do not refresh the collision, so we would remove the entity mistakenly)
            if (!it->second)
            {
                EntityPtr entity = it->first.lock();
                bool active = true;
                shared_ptr<EC_RigidBody> rigidbody = entity->GetComponent<EC_RigidBody>();
                if (rigidbody)
                    active = rigidbody->IsActive();
                if (active)
                {
                    remove = true;
                    emit entityLeave(entity.get());
                    disconnect(entity.get(), SIGNAL(EntityRemoved(Entity*, AttributeChange::Type)), this, SLOT(OnEntityRemoved(Entity*)));
                }
            }
            else
            {
                // Age the collision from new to old
                it->second = false;
            }
        }

        if (!remove)
            ++it;
        else
        {
            EntitiesWithinVolumeMap::iterator current = it;
            ++it;
            entities_.erase(current);
        }
    }
}

void EC_VolumeTrigger::OnPhysicsCollision(Entity* otherEntity, const float3& position, const float3& normal, float distance, float impulse, bool newCollision)
{
    PROFILE(EC_VolumeTrigger_OnPhysicsCollision);

    assert(otherEntity && "Physics collision with no entity.");

    if (!entities.Get().isEmpty() && !IsInterestingEntity(otherEntity->Name()))
        return;

    EntityPtr entity = otherEntity->shared_from_this();

    // If byPivot attribute is enabled, we require the object pivot to enter the volume trigger area.
    // Otherwise, we react on each physics collision message (i.e. we accept if the volumetrigger and other entity just touch).
    if (byPivot.Get() && !IsPivotInside(entity.get()))
        return;

    if (newCollision)
    {
        // make sure the entity isn't already inside the volume
        if (entities_.find(entity) == entities_.end())
        {
            emit entityEnter(otherEntity);
            connect(otherEntity, SIGNAL(EntityRemoved(Entity*, AttributeChange::Type)), this, SLOT(OnEntityRemoved(Entity*)), Qt::UniqueConnection);
        }
    }
    // Refresh the collision status to new
    entities_[entity] = true;
}

/** Called when the given entity is deleted from the scene. In that case, remove the Entity immediately from our tracking data structure (and signal listeners). */
void EC_VolumeTrigger::OnEntityRemoved(Entity *entity)
{
    assert(entity);
    EntitiesWithinVolumeMap::iterator i = entities_.find(entity->shared_from_this());
    if (i != entities_.end())
    {
        entities_.erase(i);
        emit entityLeave(entity);
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ContextClassLoader.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: ihi $ $Date: 2007-11-21 15:03:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"

#include "java/ContextClassLoader.hxx"
#include "java/lang/Object.hxx"

/** === begin UNO includes === **/
/** === end UNO includes === **/

//........................................................................
namespace connectivity { namespace jdbc
{
//........................................................................

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::uno::XInterface;
    /** === end UNO using === **/

    using ::connectivity::java_lang_Object;

    //====================================================================
    //= ContextClassLoaderScope
    //====================================================================
    //--------------------------------------------------------------------
    ContextClassLoaderScope::ContextClassLoaderScope( JNIEnv& environment, const GlobalRef< jobject >& newClassLoader,
        const ::comphelper::ResourceBasedEventLogger& _rLoggerForErrors, const Reference< XInterface >& _rxErrorContext )
        :m_environment( environment )
        ,m_currentThread( environment )
        ,m_oldContextClassLoader( environment )
    {
        if ( !newClassLoader.is() )
            return;

        do  // artificial loop for easier flow control
        {

        LocalRef< jclass > threadClass( m_environment );
        threadClass.set( m_environment.FindClass( "java/lang/Thread" ) );
        if ( !threadClass.is() )
            break;

        jmethodID currentThreadMethod( m_environment.GetStaticMethodID(
            threadClass.get(), "currentThread", "()Ljava/lang/Thread;" ) );
        if ( currentThreadMethod == NULL )
            break;

        m_currentThread.set( m_environment.CallStaticObjectMethod( threadClass.get(), currentThreadMethod ) );
        if ( !m_currentThread.is() )
            break;

        jmethodID getContextClassLoaderMethod( m_environment.GetMethodID(
            threadClass.get(), "getContextClassLoader", "()Ljava/lang/ClassLoader;" ) );
        if ( getContextClassLoaderMethod == NULL )
            break;
        m_oldContextClassLoader.set( m_environment.CallObjectMethod( m_currentThread.get(), getContextClassLoaderMethod ) );
        LocalRef< jthrowable > throwable( m_environment, m_environment.ExceptionOccurred() );
        if ( throwable.is() )
            break;

        m_setContextClassLoaderMethod = m_environment.GetMethodID(
            threadClass.get(), "setContextClassLoader", "(Ljava/lang/ClassLoader;)V" );
        if ( m_setContextClassLoaderMethod == NULL )
            break;

        }
        while ( false );

        if ( !isActive() )
        {
            java_lang_Object::ThrowLoggedSQLException( _rLoggerForErrors, &environment, _rxErrorContext );
            return;
        }

        // set the new class loader
        m_environment.CallObjectMethod( m_currentThread.get(), m_setContextClassLoaderMethod, newClassLoader.get() );
        LocalRef< jthrowable > throwable( m_environment, m_environment.ExceptionOccurred() );
        if ( throwable.is() )
        {
            m_currentThread.reset();
            m_setContextClassLoaderMethod = NULL;
            java_lang_Object::ThrowLoggedSQLException( _rLoggerForErrors, &environment, _rxErrorContext );
        }
    }

    //--------------------------------------------------------------------
    void ContextClassLoaderScope::pop( bool clearExceptions )
    {
        if ( isActive() )
        {
            LocalRef< jobject > currentThread( m_currentThread.env(), m_currentThread.release() );
            jmethodID setContextClassLoaderMethod( m_setContextClassLoaderMethod );
            m_setContextClassLoaderMethod = NULL;

            m_environment.CallObjectMethod( currentThread.get(), setContextClassLoaderMethod, m_oldContextClassLoader.get() );
            if ( clearExceptions )
            {
                m_environment.ExceptionClear();
            }
        }
    }
//........................................................................
} } // namespace connectivity::jdbc
//........................................................................
<commit_msg>INTEGRATION: CWS changefileheader (1.2.64); FILE MERGED 2008/03/28 15:23:41 rt 1.2.64.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: ContextClassLoader.cxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"

#include "java/ContextClassLoader.hxx"
#include "java/lang/Object.hxx"

/** === begin UNO includes === **/
/** === end UNO includes === **/

//........................................................................
namespace connectivity { namespace jdbc
{
//........................................................................

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::uno::XInterface;
    /** === end UNO using === **/

    using ::connectivity::java_lang_Object;

    //====================================================================
    //= ContextClassLoaderScope
    //====================================================================
    //--------------------------------------------------------------------
    ContextClassLoaderScope::ContextClassLoaderScope( JNIEnv& environment, const GlobalRef< jobject >& newClassLoader,
        const ::comphelper::ResourceBasedEventLogger& _rLoggerForErrors, const Reference< XInterface >& _rxErrorContext )
        :m_environment( environment )
        ,m_currentThread( environment )
        ,m_oldContextClassLoader( environment )
    {
        if ( !newClassLoader.is() )
            return;

        do  // artificial loop for easier flow control
        {

        LocalRef< jclass > threadClass( m_environment );
        threadClass.set( m_environment.FindClass( "java/lang/Thread" ) );
        if ( !threadClass.is() )
            break;

        jmethodID currentThreadMethod( m_environment.GetStaticMethodID(
            threadClass.get(), "currentThread", "()Ljava/lang/Thread;" ) );
        if ( currentThreadMethod == NULL )
            break;

        m_currentThread.set( m_environment.CallStaticObjectMethod( threadClass.get(), currentThreadMethod ) );
        if ( !m_currentThread.is() )
            break;

        jmethodID getContextClassLoaderMethod( m_environment.GetMethodID(
            threadClass.get(), "getContextClassLoader", "()Ljava/lang/ClassLoader;" ) );
        if ( getContextClassLoaderMethod == NULL )
            break;
        m_oldContextClassLoader.set( m_environment.CallObjectMethod( m_currentThread.get(), getContextClassLoaderMethod ) );
        LocalRef< jthrowable > throwable( m_environment, m_environment.ExceptionOccurred() );
        if ( throwable.is() )
            break;

        m_setContextClassLoaderMethod = m_environment.GetMethodID(
            threadClass.get(), "setContextClassLoader", "(Ljava/lang/ClassLoader;)V" );
        if ( m_setContextClassLoaderMethod == NULL )
            break;

        }
        while ( false );

        if ( !isActive() )
        {
            java_lang_Object::ThrowLoggedSQLException( _rLoggerForErrors, &environment, _rxErrorContext );
            return;
        }

        // set the new class loader
        m_environment.CallObjectMethod( m_currentThread.get(), m_setContextClassLoaderMethod, newClassLoader.get() );
        LocalRef< jthrowable > throwable( m_environment, m_environment.ExceptionOccurred() );
        if ( throwable.is() )
        {
            m_currentThread.reset();
            m_setContextClassLoaderMethod = NULL;
            java_lang_Object::ThrowLoggedSQLException( _rLoggerForErrors, &environment, _rxErrorContext );
        }
    }

    //--------------------------------------------------------------------
    void ContextClassLoaderScope::pop( bool clearExceptions )
    {
        if ( isActive() )
        {
            LocalRef< jobject > currentThread( m_currentThread.env(), m_currentThread.release() );
            jmethodID setContextClassLoaderMethod( m_setContextClassLoaderMethod );
            m_setContextClassLoaderMethod = NULL;

            m_environment.CallObjectMethod( currentThread.get(), setContextClassLoaderMethod, m_oldContextClassLoader.get() );
            if ( clearExceptions )
            {
                m_environment.ExceptionClear();
            }
        }
    }
//........................................................................
} } // namespace connectivity::jdbc
//........................................................................
<|endoftext|>