<commit_before>#line 2 "togo/game/world/world_manager.cpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <togo/game/config.hpp>
#include <togo/core/error/assert.hpp>
#include <togo/core/utility/utility.hpp>
#include <togo/core/collection/array.hpp>
#include <togo/core/collection/queue.hpp>
#include <togo/core/collection/hash_map.hpp>
#include <togo/game/world/types.hpp>
#include <togo/game/world/world_manager.hpp>

namespace togo {
namespace game {

namespace {
enum : unsigned {
	MIN_FREE_INDICES = 64,
};
} // anonymous namespace

WorldInstance::WorldInstance(
	Allocator& allocator
)
	: generation(0)
	, component_managers(allocator)
	, entities(allocator)
{}

WorldManager::WorldManager(
	Allocator& allocator
)
	: _component_manager_defs(allocator)
	, _instances(allocator)
	, _free_indices(allocator)
{
	hash_map::reserve(_component_manager_defs, 32);
	array::reserve(_instances, 32);
	queue::reserve(_free_indices, MIN_FREE_INDICES);
}

WorldManager::~WorldManager() {
	world_manager::shutdown(*this);
}

/// Whether a world is alive.
bool world_manager::alive(
	WorldManager const& wm,
	WorldID const& id
) {
	auto const index = id.index();
	return
		index < array::size(wm._instances) &&
		wm._instances[index].generation == id.generation()
	;
}

/// Register a component manager.
///
/// An assertion will fail if the component name has already been
/// registered.
/// Component managers must be registered before any worlds are created.
void world_manager::register_component_manager(
	WorldManager& wm,
	ComponentManagerDef const& def
) {
	TOGO_DEBUG_ASSERTE(
		def.name_hash != hash::IDENTITY32 &&
		def.func_create &&
		def.func_destroy &&
		def.func_clear
	);
	TOGO_ASSERT(
		!hash_map::has(wm._component_manager_defs, def.name_hash),
		"a component manager has already been registered with this name"
	);
	TOGO_ASSERT(
		array::empty(wm._instances),
		"component managers must be registered before any worlds are created"
	);
	hash_map::push(wm._component_manager_defs, def.name_hash, def);
}

/// Create world.
WorldID world_manager::create(WorldManager& wm) {
	WorldID::value_type index;
	if (queue::size(wm._free_indices) > MIN_FREE_INDICES) {
		index = queue::front(wm._free_indices);
		queue::pop_front(wm._free_indices);
	} else {
		index = array::size(wm._instances);
		array::increase_size(wm._instances, 1);
		auto& instance = array::back(wm._instances);
		new(&instance) WorldInstance(*wm._instances._allocator);
		hash_map::reserve(
			instance.component_managers,
			hash_map::size(wm._component_manager_defs)
		);
		for (auto const& entry : wm._component_manager_defs) {
			hash_map::push(instance.component_managers, entry.key, entry.value.func_create(wm));
		}
		TOGO_ASSERTE(index < (1 << WorldID::INDEX_BITS));
	}
	return WorldID{index | (wm._instances[index].generation << WorldID::INDEX_BITS)};
}

/// Destroy world.
void world_manager::destroy(
	WorldManager& wm,
	WorldID const& id
) {
	TOGO_ASSERTE(world_manager::alive(wm, id));
	auto const index = id.index();
	auto& instance = wm._instances[index];
	array::clear(instance.entities);
	for (auto& entry : instance.component_managers) {
		void* data = entry.value;
		auto* def = hash_map::find(wm._component_manager_defs, entry.key);
		TOGO_DEBUG_ASSERTE(def);
		def->func_clear(wm, data);
	}
	++instance.generation;
	queue::push_back(wm._free_indices, index);
}

/// Shutdown.
///
/// Removes all worlds and component manager definitions.
/// This should only be used as part of system deinitialization.
/// Using it during runtime can lead to zombie IDs pointing to valid
/// worlds (i.e., not the world originally created with the ID).
void world_manager::shutdown(WorldManager& wm) {
	for (auto& instance : wm._instances) {
		for (auto const& entry : instance.component_managers) {
			void* data = entry.value;
			auto* def = hash_map::find(wm._component_manager_defs, entry.key);
			TOGO_DEBUG_ASSERTE(def);
			def->func_destroy(wm, data);
		}
		instance.~WorldInstance();
	}
	queue::clear(wm._free_indices);
	array::clear(wm._instances);
	hash_map::clear(wm._component_manager_defs);
}

} // namespace game
} // namespace togo
<commit_msg>lib/game/world/world_manager: use push_back_inplace() instead of placement-new.<commit_after>#line 2 "togo/game/world/world_manager.cpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.
*/

#include <togo/game/config.hpp>
#include <togo/core/error/assert.hpp>
#include <togo/core/utility/utility.hpp>
#include <togo/core/collection/array.hpp>
#include <togo/core/collection/queue.hpp>
#include <togo/core/collection/hash_map.hpp>
#include <togo/game/world/types.hpp>
#include <togo/game/world/world_manager.hpp>

namespace togo {
namespace game {

namespace {
enum : unsigned {
	MIN_FREE_INDICES = 64,
};
} // anonymous namespace

WorldInstance::WorldInstance(
	Allocator& allocator
)
	: generation(0)
	, component_managers(allocator)
	, entities(allocator)
{}

WorldManager::WorldManager(
	Allocator& allocator
)
	: _component_manager_defs(allocator)
	, _instances(allocator)
	, _free_indices(allocator)
{
	hash_map::reserve(_component_manager_defs, 32);
	array::reserve(_instances, 32);
	queue::reserve(_free_indices, MIN_FREE_INDICES);
}

WorldManager::~WorldManager() {
	world_manager::shutdown(*this);
}

/// Whether a world is alive.
bool world_manager::alive(
	WorldManager const& wm,
	WorldID const& id
) {
	auto const index = id.index();
	return
		index < array::size(wm._instances) &&
		wm._instances[index].generation == id.generation()
	;
}

/// Register a component manager.
///
/// An assertion will fail if the component name has already been
/// registered.
/// Component managers must be registered before any worlds are created.
void world_manager::register_component_manager(
	WorldManager& wm,
	ComponentManagerDef const& def
) {
	TOGO_DEBUG_ASSERTE(
		def.name_hash != hash::IDENTITY32 &&
		def.func_create &&
		def.func_destroy &&
		def.func_clear
	);
	TOGO_ASSERT(
		!hash_map::has(wm._component_manager_defs, def.name_hash),
		"a component manager has already been registered with this name"
	);
	TOGO_ASSERT(
		array::empty(wm._instances),
		"component managers must be registered before any worlds are created"
	);
	hash_map::push(wm._component_manager_defs, def.name_hash, def);
}

/// Create world.
WorldID world_manager::create(WorldManager& wm) {
	WorldID::value_type index;
	if (queue::size(wm._free_indices) > MIN_FREE_INDICES) {
		index = queue::front(wm._free_indices);
		queue::pop_front(wm._free_indices);
	} else {
		index = array::size(wm._instances);
		auto& instance = array::push_back_inplace(wm._instances, *wm._instances._allocator);
		hash_map::reserve(
			instance.component_managers,
			hash_map::size(wm._component_manager_defs)
		);
		for (auto const& entry : wm._component_manager_defs) {
			hash_map::push(instance.component_managers, entry.key, entry.value.func_create(wm));
		}
		TOGO_ASSERTE(index < (1 << WorldID::INDEX_BITS));
	}
	return WorldID{index | (wm._instances[index].generation << WorldID::INDEX_BITS)};
}

/// Destroy world.
void world_manager::destroy(
	WorldManager& wm,
	WorldID const& id
) {
	TOGO_ASSERTE(world_manager::alive(wm, id));
	auto const index = id.index();
	auto& instance = wm._instances[index];
	array::clear(instance.entities);
	for (auto& entry : instance.component_managers) {
		void* data = entry.value;
		auto* def = hash_map::find(wm._component_manager_defs, entry.key);
		TOGO_DEBUG_ASSERTE(def);
		def->func_clear(wm, data);
	}
	++instance.generation;
	queue::push_back(wm._free_indices, index);
}

/// Shutdown.
///
/// Removes all worlds and component manager definitions.
/// This should only be used as part of system deinitialization.
/// Using it during runtime can lead to zombie IDs pointing to valid
/// worlds (i.e., not the world originally created with the ID).
void world_manager::shutdown(WorldManager& wm) {
	for (auto& instance : wm._instances) {
		for (auto const& entry : instance.component_managers) {
			void* data = entry.value;
			auto* def = hash_map::find(wm._component_manager_defs, entry.key);
			TOGO_DEBUG_ASSERTE(def);
			def->func_destroy(wm, data);
		}
		instance.~WorldInstance();
	}
	queue::clear(wm._free_indices);
	array::clear(wm._instances);
	hash_map::clear(wm._component_manager_defs);
}

} // namespace game
} // namespace togo
<|endoftext|>


<commit_before>// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "TestFixtures/Decoration.hpp"
#include <autowiring/autowiring.h>
#include <autowiring/AutoSelfUpdate.h>

class AutoFilterSequencing:
  public testing::Test
{
public:
  AutoFilterSequencing(void) {
    AutoCurrentContext()->Initiate();
  }
};

class FilterFirst {
public:
  FilterFirst(void) :
    m_magic(0xDEADBEEF),
    m_called(0)
  {}

  const int m_magic;
  int m_called;

  void AutoFilter(AutoPacket& pkt) {
    ASSERT_EQ(0xDEADBEEF, m_magic) << "Magic value was corrupted, pointer was not adjusted to the correct offset";
    ++m_called;
    pkt.Decorate(Decoration<0>());
  }
};

class FilterFirstValidateInheritance:
  public FilterFirst
{};

static_assert(
  std::is_same<
  FilterFirst,
  Decompose<decltype(&FilterFirstValidateInheritance::AutoFilter)>::type
  >::value,
  "Decomposed type did not correctly name the implementing type of an inherited method"
  );

TEST_F(AutoFilterSequencing, VerifyFirstLastCalls) {
  AutoRequired<AutoPacketFactory> factory;
  AutoRequired<FilterFirst> first;

  {
    auto pkt = factory->NewPacket();
    ASSERT_EQ(1, first->m_called) << "First-call filter was not applied";
  }
  ASSERT_EQ(1, first->m_called) << "First-call filter was applied as final call";
}

class FilterOutDeferred:
  public CoreThread
{
public:
  Deferred AutoFilter(auto_out<Decoration<0>> out) {
    //Default constructor sets i == 0
    return Deferred(this);
  }
};

TEST_F(AutoFilterSequencing, SuccessorAliasRules) {
  AutoRequired<AutoPacketFactory> factory;
  auto packet1 = factory->NewPacket();
  auto packet2 = packet1->Successor();
  ASSERT_TRUE(!!packet2) << "Returned successor packet was null";

  auto expected = factory->NewPacket();

  ASSERT_EQ(expected, packet2) << "Expected that the successor packet would match the next packet returned by the factory";
}

TEST_F(AutoFilterSequencing, SuccessorHoldViolationCheck) {
  AutoRequired<AutoPacketFactory> factory;
  auto packet1 = factory->NewPacket();
  auto packet2 = packet1->Successor();

  ASSERT_TRUE(packet1.unique()) << "Expected that the first issued packet shared pointer not to be aliased anywhere";

  packet1.reset();

  ASSERT_TRUE(packet2.unique()) << "Expected that a successor packet would be unique when the principal was destroyed";
}

TEST_F(AutoFilterSequencing, PacketReverseSuccessor) {
  AutoRequired<AutoPacketFactory> factory;

  auto packet1 = factory->NewPacket();
  auto packet2 = factory->NewPacket();

  ASSERT_EQ(packet2, packet1->Successor()) << "Successor packet obtained after generation from the factory did not match as expected";
}

TEST_F(AutoFilterSequencing, ManySuccessors) {
  AutoRequired<AutoPacketFactory> factory;

  auto packetA = factory->NewPacket();
  auto packet5 = packetA->Successor()->Successor()->Successor()->Successor();

  auto packetB = factory->NewPacket();
  auto packetC = factory->NewPacket();
  auto packetD = factory->NewPacket();
  auto packetE = factory->NewPacket();

  ASSERT_EQ(packet5, packetE) << "Successor packet obtained after generation from the factory did not match as expected";
}
<commit_msg>Add AutoPacket successor satisfaction test<commit_after>// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "TestFixtures/Decoration.hpp"
#include <autowiring/autowiring.h>
#include <autowiring/AutoSelfUpdate.h>

class AutoFilterSequencing:
  public testing::Test
{
public:
  AutoFilterSequencing(void) {
    AutoCurrentContext()->Initiate();
  }
};

class FilterFirst {
public:
  FilterFirst(void) :
    m_magic(0xDEADBEEF),
    m_called(0)
  {}

  const int m_magic;
  int m_called;

  void AutoFilter(AutoPacket& pkt) {
    ASSERT_EQ(0xDEADBEEF, m_magic) << "Magic value was corrupted, pointer was not adjusted to the correct offset";
    ++m_called;
    pkt.Decorate(Decoration<0>());
  }
};

class FilterFirstValidateInheritance:
  public FilterFirst
{};

static_assert(
  std::is_same<
  FilterFirst,
  Decompose<decltype(&FilterFirstValidateInheritance::AutoFilter)>::type
  >::value,
  "Decomposed type did not correctly name the implementing type of an inherited method"
  );

TEST_F(AutoFilterSequencing, VerifyFirstLastCalls) {
  AutoRequired<AutoPacketFactory> factory;
  AutoRequired<FilterFirst> first;

  {
    auto pkt = factory->NewPacket();
    ASSERT_EQ(1, first->m_called) << "First-call filter was not applied";
  }
  ASSERT_EQ(1, first->m_called) << "First-call filter was applied as final call";
}

class FilterOutDeferred:
  public CoreThread
{
public:
  Deferred AutoFilter(auto_out<Decoration<0>> out) {
    //Default constructor sets i == 0
    return Deferred(this);
  }
};

TEST_F(AutoFilterSequencing, SuccessorAliasRules) {
  AutoRequired<AutoPacketFactory> factory;
  auto packet1 = factory->NewPacket();
  auto packet2 = packet1->Successor();
  ASSERT_TRUE(!!packet2) << "Returned successor packet was null";

  auto expected = factory->NewPacket();

  ASSERT_EQ(expected, packet2) << "Expected that the successor packet would match the next packet returned by the factory";
}

TEST_F(AutoFilterSequencing, SuccessorHoldViolationCheck) {
  AutoRequired<AutoPacketFactory> factory;
  auto packet1 = factory->NewPacket();
  auto packet2 = packet1->Successor();

  ASSERT_TRUE(packet1.unique()) << "Expected that the first issued packet shared pointer not to be aliased anywhere";

  packet1.reset();

  ASSERT_TRUE(packet2.unique()) << "Expected that a successor packet would be unique when the principal was destroyed";
}

TEST_F(AutoFilterSequencing, PacketReverseSuccessor) {
  AutoRequired<AutoPacketFactory> factory;

  auto packet1 = factory->NewPacket();
  auto packet2 = factory->NewPacket();

  ASSERT_EQ(packet2, packet1->Successor()) << "Successor packet obtained after generation from the factory did not match as expected";
}

TEST_F(AutoFilterSequencing, ManySuccessors) {
  AutoRequired<AutoPacketFactory> factory;
  {
    auto packetA = factory->NewPacket();
    auto packet5 = packetA->Successor()->Successor()->Successor()->Successor();

    factory->NewPacket();
    factory->NewPacket();
    factory->NewPacket();
    auto packetE = factory->NewPacket();

    ASSERT_EQ(packet5, packetE) << "Successor packet obtained after generation from the factory did not match as expected";
  }

  AutoRequired<FilterFirst> first;
  {
    auto packetA = factory->NewPacket();
    packetA->Successor()->Successor()->Successor()->Successor();
    ASSERT_EQ(1, first->m_called) << "AutoFilter triggered from successor";

    factory->NewPacket();
    ASSERT_EQ(2, first->m_called) << "AutoFilter not triggered from new packet";
    factory->NewPacket();
    ASSERT_EQ(3, first->m_called) << "AutoFilter not triggered from new packet";
    factory->NewPacket();
    ASSERT_EQ(4, first->m_called) << "AutoFilter not triggered from new packet";
    factory->NewPacket();
    ASSERT_EQ(5, first->m_called) << "AutoFilter not triggered from new packet";
    factory->NewPacket();
    ASSERT_EQ(6, first->m_called) << "AutoFilter not triggered from new packet";
  }
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// index_scan_executor.cpp
//
// Identification: src/backend/executor/index_scan_executor.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "backend/executor/index_scan_executor.h"

#include <memory>
#include <utility>
#include <vector>

#include "backend/common/types.h"
#include "backend/executor/logical_tile.h"
#include "backend/executor/logical_tile_factory.h"
#include "backend/expression/abstract_expression.h"
#include "backend/expression/container_tuple.h"
#include "backend/storage/data_table.h"
#include "backend/storage/tile_group.h"

#include "backend/common/logger.h"

namespace peloton {
namespace executor {

/**
 * @brief Constructor for indexscan executor.
 * @param node Indexscan node corresponding to this executor.
 */
IndexScanExecutor::IndexScanExecutor(planner::AbstractPlanNode *node,
                                     ExecutorContext *executor_context)
    : AbstractScanExecutor(node, executor_context) {}

/**
 * @brief Let base class Dinit() first, then do my job.
 * @return true on success, false otherwise.
 */
bool IndexScanExecutor::DInit() {
  auto status = AbstractScanExecutor::DInit();

  if (!status) return false;

  assert(children_.size() == 0);
  LOG_TRACE("Index Scan executor :: 0 child");

  // Grab info from plan node and check it
  const planner::IndexScanNode &node = GetPlanNode<planner::IndexScanNode>();

  index_ = node.GetIndex();
  assert(index_ != nullptr);

  result_itr = START_OID;
  done_ = false;

  column_ids_ = node.GetColumnIds();
  key_column_ids_ = node.GetKeyColumnIds();
  expr_types_ = node.GetExprTypes();
  values_ = node.GetValues();

  auto table = node.GetTable();

  if (table != nullptr) {
    if (column_ids_.empty()) {
      column_ids_.resize(table->GetSchema()->GetColumnCount());
      std::iota(column_ids_.begin(), column_ids_.end(), 0);
    }
  }

  return true;
}

/**
 * @brief Creates logical tile(s) after scanning index.
 * @return true on success, false otherwise.
 */
bool IndexScanExecutor::DExecute() {
  if (!done_) {
    auto status = ExecIndexLookup();
    if (status == false) return false;
  }

  // Already performed the index lookup
  assert(done_);

  while (result_itr < result.size()) {  // Avoid returning empty tiles
    // In order to be as lazy as possible,
    // the generic predicate is checked here (instead of upfront)
    if (nullptr != predicate_) {
      for (oid_t tuple_id : *result[result_itr]) {
        expression::ContainerTuple<LogicalTile> tuple(result[result_itr],
                                                      tuple_id);
        if (predicate_->Evaluate(&tuple, nullptr, executor_context_)
                .IsFalse()) {
          result[result_itr]->RemoveVisibility(tuple_id);
        }
      }
    }

    if (result[result_itr]->GetTupleCount() == 0) {
      result_itr++;
      continue;
    } else {
      SetOutput(result[result_itr]);
      result_itr++;
      return true;
    }

  }  // end while

  return false;
}

bool IndexScanExecutor::ExecIndexLookup() {
  assert(!done_);

  std::vector<ItemPointer> tuple_locations;

  tuple_locations = index_->Scan(values_, key_column_ids_, expr_types_);

  LOG_INFO("Tuple locations : %lu", tuple_locations.size());

  if (tuple_locations.size() == 0) return false;

  auto transaction_ = executor_context_->GetTransaction();
  txn_id_t txn_id = transaction_->GetTransactionId();
  cid_t commit_id = transaction_->GetLastCommitId();

  // Get the logical tiles corresponding to the given tuple locations
  result = LogicalTileFactory::WrapTileGroups(tuple_locations, column_ids_,
                                              txn_id, commit_id);
  done_ = true;

  LOG_TRACE("Result tiles : %lu", result.size());

  return true;
}

}  // namespace executor
}  // namespace peloton
<commit_msg>index scan handles empty scan keys<commit_after>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// index_scan_executor.cpp
//
// Identification: src/backend/executor/index_scan_executor.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "backend/executor/index_scan_executor.h"

#include <memory>
#include <utility>
#include <vector>

#include "backend/common/types.h"
#include "backend/executor/logical_tile.h"
#include "backend/executor/logical_tile_factory.h"
#include "backend/expression/abstract_expression.h"
#include "backend/expression/container_tuple.h"
#include "backend/storage/data_table.h"
#include "backend/storage/tile_group.h"

#include "backend/common/logger.h"

namespace peloton {
namespace executor {

/**
 * @brief Constructor for indexscan executor.
 * @param node Indexscan node corresponding to this executor.
 */
IndexScanExecutor::IndexScanExecutor(planner::AbstractPlanNode *node,
                                     ExecutorContext *executor_context)
    : AbstractScanExecutor(node, executor_context) {}

/**
 * @brief Let base class Dinit() first, then do my job.
 * @return true on success, false otherwise.
 */
bool IndexScanExecutor::DInit() {
  auto status = AbstractScanExecutor::DInit();

  if (!status) return false;

  assert(children_.size() == 0);
  LOG_TRACE("Index Scan executor :: 0 child");

  // Grab info from plan node and check it
  const planner::IndexScanNode &node = GetPlanNode<planner::IndexScanNode>();

  index_ = node.GetIndex();
  assert(index_ != nullptr);

  result_itr = START_OID;
  done_ = false;

  column_ids_ = node.GetColumnIds();
  key_column_ids_ = node.GetKeyColumnIds();
  expr_types_ = node.GetExprTypes();
  values_ = node.GetValues();

  auto table = node.GetTable();

  if (table != nullptr) {
    if (column_ids_.empty()) {
      column_ids_.resize(table->GetSchema()->GetColumnCount());
      std::iota(column_ids_.begin(), column_ids_.end(), 0);
    }
  }

  return true;
}

/**
 * @brief Creates logical tile(s) after scanning index.
 * @return true on success, false otherwise.
 */
bool IndexScanExecutor::DExecute() {
  if (!done_) {
    auto status = ExecIndexLookup();
    if (status == false) return false;
  }

  // Already performed the index lookup
  assert(done_);

  while (result_itr < result.size()) {  // Avoid returning empty tiles
    // In order to be as lazy as possible,
    // the generic predicate is checked here (instead of upfront)
    if (nullptr != predicate_) {
      for (oid_t tuple_id : *result[result_itr]) {
        expression::ContainerTuple<LogicalTile> tuple(result[result_itr],
                                                      tuple_id);
        if (predicate_->Evaluate(&tuple, nullptr, executor_context_)
                .IsFalse()) {
          result[result_itr]->RemoveVisibility(tuple_id);
        }
      }
    }

    if (result[result_itr]->GetTupleCount() == 0) {
      result_itr++;
      continue;
    } else {
      SetOutput(result[result_itr]);
      result_itr++;
      return true;
    }

  }  // end while

  return false;
}

bool IndexScanExecutor::ExecIndexLookup() {
  assert(!done_);

  std::vector<ItemPointer> tuple_locations;

  if (0 == key_column_ids_.size()) {
    tuple_locations = index_->Scan();
  } else {
    tuple_locations = index_->Scan(values_, key_column_ids_, expr_types_);
  }

  LOG_INFO("Tuple locations : %lu", tuple_locations.size());

  if (tuple_locations.size() == 0) return false;

  auto transaction_ = executor_context_->GetTransaction();
  txn_id_t txn_id = transaction_->GetTransactionId();
  cid_t commit_id = transaction_->GetLastCommitId();

  // Get the logical tiles corresponding to the given tuple locations
  result = LogicalTileFactory::WrapTileGroups(tuple_locations, column_ids_,
                                              txn_id, commit_id);
  done_ = true;

  LOG_TRACE("Result tiles : %lu", result.size());

  return true;
}

}  // namespace executor
}  // namespace peloton
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Peng Xiao, pengxiao@outlook.com
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors as is and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation 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.
//
//M*/
#include "precomp.hpp"
#include "opencl_kernels.hpp"

using namespace cv;
using namespace cv::ocl;

// currently sort procedure on the host is more efficient
static bool use_cpu_sorter = true;

// compact structure for corners
struct DefCorner
{
    float eig;  //eigenvalue of corner
    short x;    //x coordinate of corner point
    short y;    //y coordinate of corner point
} ;

// compare procedure for corner
//it is used for sort on the host side
struct DefCornerCompare
{
    bool operator()(const DefCorner a, const DefCorner b) const
    {
        return a.eig > b.eig;
    }
};

// sort corner point using opencl bitonicosrt implementation
static void sortCorners_caller(oclMat& corners, const int count)
{
    Context * cxt = Context::getContext();
    int     GS = count/2;
    int     LS = min(255,GS);
    size_t  globalThreads[3] = {GS, 1, 1};
    size_t  localThreads[3]  = {LS, 1, 1};

    // 2^numStages should be equal to count or the output is invalid
    int numStages = 0;
    for(int i = count; i > 1; i >>= 1)
    {
        ++numStages;
    }
    const int argc = 4;
    std::vector< std::pair<size_t, const void *> > args(argc);
    std::string kernelname = "sortCorners_bitonicSort";
    args[0] = std::make_pair(sizeof(cl_mem), (void *)&corners.data);
    args[1] = std::make_pair(sizeof(cl_int), (void *)&count);
    for(int stage = 0; stage < numStages; ++stage)
    {
        args[2] = std::make_pair(sizeof(cl_int), (void *)&stage);
        for(int passOfStage = 0; passOfStage < stage + 1; ++passOfStage)
        {
            args[3] = std::make_pair(sizeof(cl_int), (void *)&passOfStage);
            openCLExecuteKernel(cxt, &imgproc_gftt, kernelname, globalThreads, localThreads, args, -1, -1);
        }
    }
}

// find corners on matrix and put it into array
static void findCorners_caller(
    const oclMat&   eig_mat,        //input matrix worth eigenvalues
    oclMat&         eigMinMax,      //input with min and max values of eigenvalues
    const float     qualityLevel,
    const oclMat&   mask,
    oclMat&         corners,        //output array with detected corners
    oclMat&         counter)        //output value with number of detected corners, have to be 0 before call
{
    string  opt;
    std::vector<int> k;
    Context * cxt = Context::getContext();

    std::vector< std::pair<size_t, const void*> > args;

    const int mask_strip = mask.step / mask.elemSize1();

    args.push_back(make_pair( sizeof(cl_mem),   (void*)&(eig_mat.data)));

    int src_pitch = (int)eig_mat.step;
    args.push_back(make_pair( sizeof(cl_int),   (void*)&src_pitch ));
    args.push_back(make_pair( sizeof(cl_mem),   (void*)&mask.data ));
    args.push_back(make_pair( sizeof(cl_mem),   (void*)&corners.data ));
    args.push_back(make_pair( sizeof(cl_int),   (void*)&mask_strip));
    args.push_back(make_pair( sizeof(cl_mem),   (void*)&eigMinMax.data ));
    args.push_back(make_pair( sizeof(cl_float), (void*)&qualityLevel ));
    args.push_back(make_pair( sizeof(cl_int),   (void*)&eig_mat.rows ));
    args.push_back(make_pair( sizeof(cl_int),   (void*)&eig_mat.cols ));
    args.push_back(make_pair( sizeof(cl_int),   (void*)&corners.cols ));
    args.push_back(make_pair( sizeof(cl_mem),   (void*)&counter.data ));

    size_t globalThreads[3] = {eig_mat.cols, eig_mat.rows, 1};
    size_t localThreads[3]  = {16, 16, 1};
    if(!mask.empty())
        opt += " -D WITH_MASK=1";

     openCLExecuteKernel(cxt, &imgproc_gftt, "findCorners", globalThreads, localThreads, args, -1, -1, opt.c_str());
}

static void minMaxEig_caller(const oclMat &src, oclMat &dst, oclMat & tozero)
{
    size_t groupnum = src.clCxt->getDeviceInfo().maxComputeUnits;
    CV_Assert(groupnum != 0);

    int dbsize = groupnum * 2 * src.elemSize();
    ensureSizeIsEnough(1, dbsize, CV_8UC1, dst);

    cl_mem dst_data = reinterpret_cast<cl_mem>(dst.data);

    int vElemSize = src.elemSize1();
    int src_step = src.step / vElemSize, src_offset = src.offset / vElemSize;
    int total = src.size().area();

    {
        // first parallel pass
        vector<pair<size_t , const void *> > args;
        args.push_back( make_pair( sizeof(cl_mem) , (void *)&src.data));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&src_step));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&src_offset));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&src.rows ));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&src.cols ));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&total));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&groupnum));
        args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst_data ));
        size_t globalThreads[3] = {groupnum * 256, 1, 1};
        size_t localThreads[3] = {256, 1, 1};
        openCLExecuteKernel(src.clCxt, &arithm_minMax, "arithm_op_minMax", globalThreads, localThreads,
                            args, -1, -1, "-D T=float -D DEPTH_5 -D vlen=1");
    }

    {
        // run final "serial" kernel to find accumulate results from threads and reset corner counter
        vector<pair<size_t , const void *> > args;
        args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst_data ));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&groupnum ));
        args.push_back( make_pair( sizeof(cl_mem) , (void *)&tozero.data ));
        size_t globalThreads[3] = {1, 1, 1};
        size_t localThreads[3] = {1, 1, 1};
        openCLExecuteKernel(src.clCxt, &imgproc_gftt, "arithm_op_minMax_final", globalThreads, localThreads,
                            args, -1, -1);
    }
}

void cv::ocl::GoodFeaturesToTrackDetector_OCL::operator ()(const oclMat& image, oclMat& corners, const oclMat& mask)
{
    CV_Assert(qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0);
    CV_Assert(mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()));

    ensureSizeIsEnough(image.size(), CV_32F, eig_);

    if (useHarrisDetector)
        cornerHarris_dxdy(image, eig_, Dx_, Dy_, blockSize, 3, harrisK);
    else
        cornerMinEigenVal_dxdy(image, eig_, Dx_, Dy_, blockSize, 3);

    ensureSizeIsEnough(1,1, CV_32SC1, counter_);

    // find max eigenvalue and reset detected counters
    minMaxEig_caller(eig_,eig_minmax_,counter_);

    // allocate buffer for kernels
    int corner_array_size = std::max(1024, static_cast<int>(image.size().area() * 0.05));

    if(!use_cpu_sorter)
    {   // round to 2^n
        unsigned int n=1;
        for(n=1;n<(unsigned int)corner_array_size;n<<=1) ;
        corner_array_size = (int)n;

        ensureSizeIsEnough(1, corner_array_size , CV_32FC2, tmpCorners_);

        // set to 0 to be able use bitonic sort on whole 2^n array
        tmpCorners_.setTo(0);
    }
    else
    {
        ensureSizeIsEnough(1, corner_array_size , CV_32FC2, tmpCorners_);
    }

    int total = tmpCorners_.cols; // by default the number of corner is full array
    vector<DefCorner>   tmp(tmpCorners_.cols); // input buffer with corner for HOST part of algorithm

    //find points with high eigenvalue and put it into the output array
    findCorners_caller(
        eig_,
        eig_minmax_,
        static_cast<float>(qualityLevel),
        mask,
        tmpCorners_,
        counter_);

    if(!use_cpu_sorter)
    {// sort detected corners on deivce side
        sortCorners_caller(tmpCorners_, corner_array_size);
    }
    else
    {// send non-blocking request to read real non-zero number of corners to sort it on the HOST side
        openCLVerifyCall(clEnqueueReadBuffer(getClCommandQueue(counter_.clCxt), (cl_mem)counter_.data, CL_FALSE, 0,sizeof(int), &total, 0, NULL, NULL));
    }

    //blocking read whole corners array (sorted or not sorted)
    openCLReadBuffer(tmpCorners_.clCxt,(cl_mem)tmpCorners_.data,&tmp[0],tmpCorners_.cols*sizeof(DefCorner));

    if (total == 0)
    {// check for trivial case
        corners.release();
        return;
    }

    if(use_cpu_sorter)
    {// sort detected corners on cpu side.
        tmp.resize(total);
        cv::sort(tmp,DefCornerCompare());
    }

    //estimate maximal size of final output array
    int total_max = maxCorners > 0 ? std::min(maxCorners, total) : total;
    int D2 = (int)ceil(minDistance * minDistance);
    // allocate output buffer
    vector<Point2f> tmp2;
    tmp2.reserve(total_max);

    if (minDistance < 1)
    {// we have not distance restriction. then just copy with conversion maximal allowed points into output array
        for(int i=0;i<total_max && tmp[i].eig>0.0f;++i)
        {
            tmp2.push_back(Point2f(tmp[i].x,tmp[i].y));
        }
    }
    else
    {// we have distance restriction. then start coping to output array from the first element and check distance for each next one
        const int cell_size = cvRound(minDistance);
        const int grid_width = (image.cols + cell_size - 1) / cell_size;
        const int grid_height = (image.rows + cell_size - 1) / cell_size;

        std::vector< std::vector<Point2i> > grid(grid_width * grid_height);

        for (int i = 0; i < total ; ++i)
        {
            DefCorner p = tmp[i];

            if(p.eig<=0.0f)
                break; // condition to stop that is needed for GPU bitonic sort usage.

            bool good = true;

            int x_cell = static_cast<int>(p.x / cell_size);
            int y_cell = static_cast<int>(p.y / cell_size);

            int x1 = x_cell - 1;
            int y1 = y_cell - 1;
            int x2 = x_cell + 1;
            int y2 = y_cell + 1;

            // boundary check
            x1 = std::max(0, x1);
            y1 = std::max(0, y1);
            x2 = std::min(grid_width - 1, x2);
            y2 = std::min(grid_height - 1, y2);

            for (int yy = y1; yy <= y2; yy++)
            {
                for (int xx = x1; xx <= x2; xx++)
                {
                    vector<Point2i>& m = grid[yy * grid_width + xx];
                    if (m.empty())
                        continue;
                    for(size_t j = 0; j < m.size(); j++)
                    {
                        int dx = p.x - m[j].x;
                        int dy = p.y - m[j].y;

                        if (dx * dx + dy * dy < D2)
                        {
                            good = false;
                            goto break_out_;
                        }
                    }
                }
            }

            break_out_:

            if(good)
            {
                grid[y_cell * grid_width + x_cell].push_back(Point2i(p.x,p.y));

                tmp2.push_back(Point2f(p.x,p.y));

                if (maxCorners > 0 && tmp2.size() == static_cast<size_t>(maxCorners))
                    break;
            }
        }

    }
    int final_size = static_cast<int>(tmp2.size());
    if(final_size>0)
        corners.upload(Mat(1, final_size, CV_32FC2, &tmp2[0]));
    else
        corners.release();
}
void cv::ocl::GoodFeaturesToTrackDetector_OCL::downloadPoints(const oclMat &points, vector<Point2f> &points_v)
{
    CV_DbgAssert(points.type() == CV_32FC2);
    points_v.resize(points.cols);
    openCLSafeCall(clEnqueueReadBuffer(
        *(cl_command_queue*)getClCommandQueuePtr(),
        reinterpret_cast<cl_mem>(points.data),
        CL_TRUE,
        0,
        points.cols * sizeof(Point2f),
        &points_v[0],
        0,
        NULL,
        NULL));
}
<commit_msg>remove unused variable in findCorners_caller()<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// @Authors
//    Peng Xiao, pengxiao@outlook.com
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors as is and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation 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.
//
//M*/
#include "precomp.hpp"
#include "opencl_kernels.hpp"

using namespace cv;
using namespace cv::ocl;

// currently sort procedure on the host is more efficient
static bool use_cpu_sorter = true;

// compact structure for corners
struct DefCorner
{
    float eig;  //eigenvalue of corner
    short x;    //x coordinate of corner point
    short y;    //y coordinate of corner point
} ;

// compare procedure for corner
//it is used for sort on the host side
struct DefCornerCompare
{
    bool operator()(const DefCorner a, const DefCorner b) const
    {
        return a.eig > b.eig;
    }
};

// sort corner point using opencl bitonicosrt implementation
static void sortCorners_caller(oclMat& corners, const int count)
{
    Context * cxt = Context::getContext();
    int     GS = count/2;
    int     LS = min(255,GS);
    size_t  globalThreads[3] = {GS, 1, 1};
    size_t  localThreads[3]  = {LS, 1, 1};

    // 2^numStages should be equal to count or the output is invalid
    int numStages = 0;
    for(int i = count; i > 1; i >>= 1)
    {
        ++numStages;
    }
    const int argc = 4;
    std::vector< std::pair<size_t, const void *> > args(argc);
    std::string kernelname = "sortCorners_bitonicSort";
    args[0] = std::make_pair(sizeof(cl_mem), (void *)&corners.data);
    args[1] = std::make_pair(sizeof(cl_int), (void *)&count);
    for(int stage = 0; stage < numStages; ++stage)
    {
        args[2] = std::make_pair(sizeof(cl_int), (void *)&stage);
        for(int passOfStage = 0; passOfStage < stage + 1; ++passOfStage)
        {
            args[3] = std::make_pair(sizeof(cl_int), (void *)&passOfStage);
            openCLExecuteKernel(cxt, &imgproc_gftt, kernelname, globalThreads, localThreads, args, -1, -1);
        }
    }
}

// find corners on matrix and put it into array
static void findCorners_caller(
    const oclMat&   eig_mat,        //input matrix worth eigenvalues
    oclMat&         eigMinMax,      //input with min and max values of eigenvalues
    const float     qualityLevel,
    const oclMat&   mask,
    oclMat&         corners,        //output array with detected corners
    oclMat&         counter)        //output value with number of detected corners, have to be 0 before call
{
    string  opt;
    Context * cxt = Context::getContext();

    std::vector< std::pair<size_t, const void*> > args;

    const int mask_strip = mask.step / mask.elemSize1();

    args.push_back(make_pair( sizeof(cl_mem),   (void*)&(eig_mat.data)));

    int src_pitch = (int)eig_mat.step;
    args.push_back(make_pair( sizeof(cl_int),   (void*)&src_pitch ));
    args.push_back(make_pair( sizeof(cl_mem),   (void*)&mask.data ));
    args.push_back(make_pair( sizeof(cl_mem),   (void*)&corners.data ));
    args.push_back(make_pair( sizeof(cl_int),   (void*)&mask_strip));
    args.push_back(make_pair( sizeof(cl_mem),   (void*)&eigMinMax.data ));
    args.push_back(make_pair( sizeof(cl_float), (void*)&qualityLevel ));
    args.push_back(make_pair( sizeof(cl_int),   (void*)&eig_mat.rows ));
    args.push_back(make_pair( sizeof(cl_int),   (void*)&eig_mat.cols ));
    args.push_back(make_pair( sizeof(cl_int),   (void*)&corners.cols ));
    args.push_back(make_pair( sizeof(cl_mem),   (void*)&counter.data ));

    size_t globalThreads[3] = {eig_mat.cols, eig_mat.rows, 1};
    size_t localThreads[3]  = {16, 16, 1};
    if(!mask.empty())
        opt += " -D WITH_MASK=1";

     openCLExecuteKernel(cxt, &imgproc_gftt, "findCorners", globalThreads, localThreads, args, -1, -1, opt.c_str());
}

static void minMaxEig_caller(const oclMat &src, oclMat &dst, oclMat & tozero)
{
    size_t groupnum = src.clCxt->getDeviceInfo().maxComputeUnits;
    CV_Assert(groupnum != 0);

    int dbsize = groupnum * 2 * src.elemSize();
    ensureSizeIsEnough(1, dbsize, CV_8UC1, dst);

    cl_mem dst_data = reinterpret_cast<cl_mem>(dst.data);

    int vElemSize = src.elemSize1();
    int src_step = src.step / vElemSize, src_offset = src.offset / vElemSize;
    int total = src.size().area();

    {
        // first parallel pass
        vector<pair<size_t , const void *> > args;
        args.push_back( make_pair( sizeof(cl_mem) , (void *)&src.data));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&src_step));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&src_offset));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&src.rows ));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&src.cols ));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&total));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&groupnum));
        args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst_data ));
        size_t globalThreads[3] = {groupnum * 256, 1, 1};
        size_t localThreads[3] = {256, 1, 1};
        openCLExecuteKernel(src.clCxt, &arithm_minMax, "arithm_op_minMax", globalThreads, localThreads,
                            args, -1, -1, "-D T=float -D DEPTH_5 -D vlen=1");
    }

    {
        // run final "serial" kernel to find accumulate results from threads and reset corner counter
        vector<pair<size_t , const void *> > args;
        args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst_data ));
        args.push_back( make_pair( sizeof(cl_int) , (void *)&groupnum ));
        args.push_back( make_pair( sizeof(cl_mem) , (void *)&tozero.data ));
        size_t globalThreads[3] = {1, 1, 1};
        size_t localThreads[3] = {1, 1, 1};
        openCLExecuteKernel(src.clCxt, &imgproc_gftt, "arithm_op_minMax_final", globalThreads, localThreads,
                            args, -1, -1);
    }
}

void cv::ocl::GoodFeaturesToTrackDetector_OCL::operator ()(const oclMat& image, oclMat& corners, const oclMat& mask)
{
    CV_Assert(qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0);
    CV_Assert(mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()));

    ensureSizeIsEnough(image.size(), CV_32F, eig_);

    if (useHarrisDetector)
        cornerHarris_dxdy(image, eig_, Dx_, Dy_, blockSize, 3, harrisK);
    else
        cornerMinEigenVal_dxdy(image, eig_, Dx_, Dy_, blockSize, 3);

    ensureSizeIsEnough(1,1, CV_32SC1, counter_);

    // find max eigenvalue and reset detected counters
    minMaxEig_caller(eig_,eig_minmax_,counter_);

    // allocate buffer for kernels
    int corner_array_size = std::max(1024, static_cast<int>(image.size().area() * 0.05));

    if(!use_cpu_sorter)
    {   // round to 2^n
        unsigned int n=1;
        for(n=1;n<(unsigned int)corner_array_size;n<<=1) ;
        corner_array_size = (int)n;

        ensureSizeIsEnough(1, corner_array_size , CV_32FC2, tmpCorners_);

        // set to 0 to be able use bitonic sort on whole 2^n array
        tmpCorners_.setTo(0);
    }
    else
    {
        ensureSizeIsEnough(1, corner_array_size , CV_32FC2, tmpCorners_);
    }

    int total = tmpCorners_.cols; // by default the number of corner is full array
    vector<DefCorner>   tmp(tmpCorners_.cols); // input buffer with corner for HOST part of algorithm

    //find points with high eigenvalue and put it into the output array
    findCorners_caller(
        eig_,
        eig_minmax_,
        static_cast<float>(qualityLevel),
        mask,
        tmpCorners_,
        counter_);

    if(!use_cpu_sorter)
    {// sort detected corners on deivce side
        sortCorners_caller(tmpCorners_, corner_array_size);
    }
    else
    {// send non-blocking request to read real non-zero number of corners to sort it on the HOST side
        openCLVerifyCall(clEnqueueReadBuffer(getClCommandQueue(counter_.clCxt), (cl_mem)counter_.data, CL_FALSE, 0,sizeof(int), &total, 0, NULL, NULL));
    }

    //blocking read whole corners array (sorted or not sorted)
    openCLReadBuffer(tmpCorners_.clCxt,(cl_mem)tmpCorners_.data,&tmp[0],tmpCorners_.cols*sizeof(DefCorner));

    if (total == 0)
    {// check for trivial case
        corners.release();
        return;
    }

    if(use_cpu_sorter)
    {// sort detected corners on cpu side.
        tmp.resize(total);
        cv::sort(tmp,DefCornerCompare());
    }

    //estimate maximal size of final output array
    int total_max = maxCorners > 0 ? std::min(maxCorners, total) : total;
    int D2 = (int)ceil(minDistance * minDistance);
    // allocate output buffer
    vector<Point2f> tmp2;
    tmp2.reserve(total_max);

    if (minDistance < 1)
    {// we have not distance restriction. then just copy with conversion maximal allowed points into output array
        for(int i=0;i<total_max && tmp[i].eig>0.0f;++i)
        {
            tmp2.push_back(Point2f(tmp[i].x,tmp[i].y));
        }
    }
    else
    {// we have distance restriction. then start coping to output array from the first element and check distance for each next one
        const int cell_size = cvRound(minDistance);
        const int grid_width = (image.cols + cell_size - 1) / cell_size;
        const int grid_height = (image.rows + cell_size - 1) / cell_size;

        std::vector< std::vector<Point2i> > grid(grid_width * grid_height);

        for (int i = 0; i < total ; ++i)
        {
            DefCorner p = tmp[i];

            if(p.eig<=0.0f)
                break; // condition to stop that is needed for GPU bitonic sort usage.

            bool good = true;

            int x_cell = static_cast<int>(p.x / cell_size);
            int y_cell = static_cast<int>(p.y / cell_size);

            int x1 = x_cell - 1;
            int y1 = y_cell - 1;
            int x2 = x_cell + 1;
            int y2 = y_cell + 1;

            // boundary check
            x1 = std::max(0, x1);
            y1 = std::max(0, y1);
            x2 = std::min(grid_width - 1, x2);
            y2 = std::min(grid_height - 1, y2);

            for (int yy = y1; yy <= y2; yy++)
            {
                for (int xx = x1; xx <= x2; xx++)
                {
                    vector<Point2i>& m = grid[yy * grid_width + xx];
                    if (m.empty())
                        continue;
                    for(size_t j = 0; j < m.size(); j++)
                    {
                        int dx = p.x - m[j].x;
                        int dy = p.y - m[j].y;

                        if (dx * dx + dy * dy < D2)
                        {
                            good = false;
                            goto break_out_;
                        }
                    }
                }
            }

            break_out_:

            if(good)
            {
                grid[y_cell * grid_width + x_cell].push_back(Point2i(p.x,p.y));

                tmp2.push_back(Point2f(p.x,p.y));

                if (maxCorners > 0 && tmp2.size() == static_cast<size_t>(maxCorners))
                    break;
            }
        }

    }
    int final_size = static_cast<int>(tmp2.size());
    if(final_size>0)
        corners.upload(Mat(1, final_size, CV_32FC2, &tmp2[0]));
    else
        corners.release();
}
void cv::ocl::GoodFeaturesToTrackDetector_OCL::downloadPoints(const oclMat &points, vector<Point2f> &points_v)
{
    CV_DbgAssert(points.type() == CV_32FC2);
    points_v.resize(points.cols);
    openCLSafeCall(clEnqueueReadBuffer(
        *(cl_command_queue*)getClCommandQueuePtr(),
        reinterpret_cast<cl_mem>(points.data),
        CL_TRUE,
        0,
        points.cols * sizeof(Point2f),
        &points_v[0],
        0,
        NULL,
        NULL));
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestHyperOctreeDual.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// This example demonstrates how to use a vtkHyperOctreeSampleFunction and
// apply a vtkHyperOctreeCutter filter on it.
//
// The command line arguments are:
// -I        => run in interactive mode; unless this is used, the program will
//              not allow interaction and exit
// -D <path> => path to the data; the data should be in <path>/Data/

// If WRITE_RESULT is defined, the result of the surface filter is saved.
//#define WRITE_RESULT

#include "vtkActor.h"
#include "vtkCellData.h"
#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include <assert.h>
#include "vtkLookupTable.h"
#include "vtkPolyData.h"
#include "vtkXMLPolyDataWriter.h"
#include "vtkHyperOctreeDualGridContourFilter.h"
#include "vtkContourFilter.h"
#include "vtkProperty.h"
#include "vtkDataSetMapper.h"
#include "vtkPolyDataMapper.h"
#include "vtkTimerLog.h"
#include "vtkHyperOctreeFractalSource.h"
#include "vtkSphere.h"
#include "vtkCamera.h"

int TestHyperOctreeDual(int argc, char* argv[])
{
  // Standard rendering classes
  vtkRenderer *renderer = vtkRenderer::New();
  vtkRenderWindow *renWin = vtkRenderWindow::New();
  renWin->AddRenderer(renderer);
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
  iren->SetRenderWindow(renWin);

  vtkTimerLog *timer=vtkTimerLog::New();

  // 3D
  vtkHyperOctreeFractalSource* source3d = vtkHyperOctreeFractalSource::New();
  source3d->SetMaximumNumberOfIterations(17);
  source3d->SetMaximumLevel(7);
  source3d->SetMinimumLevel(3);

  cout<<"update source3d..."<<endl;
  timer->StartTimer();
  source3d->Update(); // Update now, make things easier with a debugger
  timer->StopTimer();
  cout<<"source updated3d"<<endl;
  cout<<"source3d time="<<timer->GetElapsedTime()<<" s"<<endl;

  vtkHyperOctreeDualGridContourFilter *contour3d;
  contour3d = vtkHyperOctreeDualGridContourFilter::New();
  contour3d->SetNumberOfContours(2);
  contour3d->SetValue(0,4.5);
  contour3d->SetValue(1,10.5);

  contour3d->SetInputConnection(0,source3d->GetOutputPort(0));
  cout<<"update contour3d..."<<endl;
  timer->StartTimer();
  contour3d->Update(); // Update now, make things easier with a debugger
  timer->StopTimer();
  cout<<"contour3d updated"<<endl;
  cout<<"contour3d time="<<timer->GetElapsedTime()<<" s"<<endl;

  // This creates a blue to red lut.
  vtkLookupTable *lut3d = vtkLookupTable::New();
  lut3d->SetHueRange (0.667, 0.0);

  vtkPolyDataMapper *mapper3d = vtkPolyDataMapper::New();
  mapper3d->SetInputConnection(0, contour3d->GetOutputPort(0) );
  mapper3d->SetScalarRange(0, 17);

  vtkActor *actor3d = vtkActor::New();
  actor3d->SetMapper(mapper3d);
  renderer->AddActor(actor3d);

#ifdef WRITE_RESULT
  // Save the result of the filter in a file
  vtkXMLPolyDataWriter *writer3d=vtkXMLPolyDataWriter::New();
  writer3d->SetInputConnection(0,contour3d->GetOutputPort(0));
  writer3d->SetFileName("contour3d.vtp");
  writer3d->SetDataModeToAscii();
  writer3d->Write();
  writer3d->Delete();
#endif // #ifdef WRITE_RESULT

  // 2D
  vtkHyperOctreeFractalSource* source2d = vtkHyperOctreeFractalSource::New();
  source2d->SetDimension(2);
  source2d->SetMaximumNumberOfIterations(17);
  source2d->SetMaximumLevel(7);
  source2d->SetMinimumLevel(4);

  cout<<"update source2d..."<<endl;
  timer->StartTimer();
  source2d->Update(); // Update now, make things easier with a debugger
  timer->StopTimer();
  cout<<"source updated2d"<<endl;
  cout<<"source2d time="<<timer->GetElapsedTime()<<" s"<<endl;

  // This creates a blue to red lut.
  vtkLookupTable *lut2d = vtkLookupTable::New();
  lut2d->SetHueRange (0.667, 0.0);

  vtkDataSetMapper *mapper2d = vtkDataSetMapper::New();
  mapper2d->SetInputConnection(0,source2d->GetOutputPort(0));
  mapper2d->SetLookupTable(lut2d);
  mapper2d->SetScalarRange(0, 17);

  vtkActor *actor2d = vtkActor::New();
  actor2d->SetPosition(2.5,0,0);
  actor2d->SetOrientation(180,0,0);
  actor2d->SetMapper(mapper2d);
  actor2d->GetProperty()->SetRepresentationToWireframe();
  actor2d->GetProperty()->SetAmbient(1.0);
  actor2d->GetProperty()->SetDiffuse(0.0);
  renderer->AddActor(actor2d);

#ifdef WRITE_RESULT
  // Save the result of the filter in a file
  vtkXMLPolyDataWriter *writer2d=vtkXMLPolyDataWriter::New();
  writer2d->SetInputConnection(0,source2d->GetOutputPort(0));
  writer2d->SetFileName("dual2d.vtp");
  writer2d->SetDataModeToAscii();
  writer2d->Write();
  writer2d->Delete();
#endif // #ifdef WRITE_RESULT

  // Contour using data set API.
  vtkHyperOctreeFractalSource* source3dHack = vtkHyperOctreeFractalSource::New();
  source3dHack->SetMaximumNumberOfIterations(17);
  source3dHack->SetMaximumLevel(7);
  source3dHack->SetMinimumLevel(3);

  vtkContourFilter *contourDS=vtkContourFilter::New();
  contourDS->SetNumberOfContours(2);
  contourDS->SetValue(0,4.5);
  contourDS->SetValue(1,10.5);

  contourDS->SetInputConnection(0,source3dHack->GetOutputPort(0));
  cout<<"update contour data set..."<<endl;
  timer->StartTimer();
  contourDS->Update(); // Update now, make things easier with a debugger
  timer->StopTimer();
  cout<<"contour data set updated"<<endl;
  cout<<"contour data set time="<<timer->GetElapsedTime()<<" s"<<endl;

  // This creates a blue to red lut.
  vtkLookupTable *lutDS = vtkLookupTable::New();
  lutDS->SetHueRange (0.667, 0.0);

  vtkPolyDataMapper *mapperDS = vtkPolyDataMapper::New();
  mapperDS->SetInputConnection(0,contourDS->GetOutputPort(0));
  mapperDS->SetLookupTable(lutDS);
  mapperDS->SetScalarRange(0, 17);

  vtkActor *actorDS = vtkActor::New();
  actorDS->SetPosition(2.5,2.5,0);
  actorDS->SetMapper(mapperDS);
  renderer->AddActor(actorDS);

#ifdef WRITE_RESULT
  // Save the result of the filter in a file
  vtkXMLPolyDataWriter *writerDS=vtkXMLPolyDataWriter::New();
  writerDS->SetInputConnection(0,contourDS->GetOutputPort(0));
  writerDS->SetFileName("contourDS.vtp");
  writerDS->SetDataModeToAscii();
  writerDS->Write();
  writerDS->Delete();
#endif // #ifdef WRITE_RESULT

  // Standard testing code.
  renderer->SetBackground(0.5,0.5,0.5);
  renWin->SetSize(300,300);
  vtkCamera *cam=renderer->GetActiveCamera();
  renderer->ResetCamera();
  cam->Azimuth(180);
  cam->Zoom(1.35);
  renWin->Render();

  int retVal = vtkRegressionTestImage( renWin );
  if (retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }

  // Cleanup
  renderer->Delete();
  renWin->Delete();
  iren->Delete();

  contourDS->Delete();
  lutDS->Delete();
  mapperDS->Delete();
  actorDS->Delete();

  source3d->Delete();
  source3dHack->Delete();
  contour3d->Delete();
  mapper3d->Delete();
  actor3d->Delete();
  lut3d->Delete();

  source2d->Delete();
  mapper2d->Delete();
  actor2d->Delete();
  lut2d->Delete();

  timer->Delete();

  return !retVal;
}
<commit_msg>BUG: This hack is no longer useful.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestHyperOctreeDual.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// This example demonstrates how to use a vtkHyperOctreeSampleFunction and
// apply a vtkHyperOctreeCutter filter on it.
//
// The command line arguments are:
// -I        => run in interactive mode; unless this is used, the program will
//              not allow interaction and exit
// -D <path> => path to the data; the data should be in <path>/Data/

// If WRITE_RESULT is defined, the result of the surface filter is saved.
//#define WRITE_RESULT

#include "vtkActor.h"
#include "vtkCellData.h"
#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include <assert.h>
#include "vtkLookupTable.h"
#include "vtkPolyData.h"
#include "vtkXMLPolyDataWriter.h"
#include "vtkHyperOctreeDualGridContourFilter.h"
#include "vtkContourFilter.h"
#include "vtkProperty.h"
#include "vtkDataSetMapper.h"
#include "vtkPolyDataMapper.h"
#include "vtkTimerLog.h"
#include "vtkHyperOctreeFractalSource.h"
#include "vtkSphere.h"
#include "vtkCamera.h"

int TestHyperOctreeDual(int argc, char* argv[])
{
  // Standard rendering classes
  vtkRenderer *renderer = vtkRenderer::New();
  vtkRenderWindow *renWin = vtkRenderWindow::New();
  renWin->AddRenderer(renderer);
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
  iren->SetRenderWindow(renWin);

  vtkTimerLog *timer=vtkTimerLog::New();

  // 3D
  vtkHyperOctreeFractalSource* source3d = vtkHyperOctreeFractalSource::New();
  source3d->SetMaximumNumberOfIterations(17);
  source3d->SetMaximumLevel(7);
  source3d->SetMinimumLevel(3);

  cout<<"update source3d..."<<endl;
  timer->StartTimer();
  source3d->Update(); // Update now, make things easier with a debugger
  timer->StopTimer();
  cout<<"source updated3d"<<endl;
  cout<<"source3d time="<<timer->GetElapsedTime()<<" s"<<endl;

  vtkHyperOctreeDualGridContourFilter *contour3d;
  contour3d = vtkHyperOctreeDualGridContourFilter::New();
  contour3d->SetNumberOfContours(2);
  contour3d->SetValue(0,4.5);
  contour3d->SetValue(1,10.5);

  contour3d->SetInputConnection(0,source3d->GetOutputPort(0));
  cout<<"update contour3d..."<<endl;
  timer->StartTimer();
  contour3d->Update(); // Update now, make things easier with a debugger
  timer->StopTimer();
  cout<<"contour3d updated"<<endl;
  cout<<"contour3d time="<<timer->GetElapsedTime()<<" s"<<endl;

  // This creates a blue to red lut.
  vtkLookupTable *lut3d = vtkLookupTable::New();
  lut3d->SetHueRange (0.667, 0.0);

  vtkPolyDataMapper *mapper3d = vtkPolyDataMapper::New();
  mapper3d->SetInputConnection(0, contour3d->GetOutputPort(0) );
  mapper3d->SetScalarRange(0, 17);

  vtkActor *actor3d = vtkActor::New();
  actor3d->SetMapper(mapper3d);
  renderer->AddActor(actor3d);

#ifdef WRITE_RESULT
  // Save the result of the filter in a file
  vtkXMLPolyDataWriter *writer3d=vtkXMLPolyDataWriter::New();
  writer3d->SetInputConnection(0,contour3d->GetOutputPort(0));
  writer3d->SetFileName("contour3d.vtp");
  writer3d->SetDataModeToAscii();
  writer3d->Write();
  writer3d->Delete();
#endif // #ifdef WRITE_RESULT

  // 2D
  vtkHyperOctreeFractalSource* source2d = vtkHyperOctreeFractalSource::New();
  source2d->SetDimension(2);
  source2d->SetMaximumNumberOfIterations(17);
  source2d->SetMaximumLevel(7);
  source2d->SetMinimumLevel(4);

  cout<<"update source2d..."<<endl;
  timer->StartTimer();
  source2d->Update(); // Update now, make things easier with a debugger
  timer->StopTimer();
  cout<<"source updated2d"<<endl;
  cout<<"source2d time="<<timer->GetElapsedTime()<<" s"<<endl;

  // This creates a blue to red lut.
  vtkLookupTable *lut2d = vtkLookupTable::New();
  lut2d->SetHueRange (0.667, 0.0);

  vtkDataSetMapper *mapper2d = vtkDataSetMapper::New();
  mapper2d->SetInputConnection(0,source2d->GetOutputPort(0));
  mapper2d->SetLookupTable(lut2d);
  mapper2d->SetScalarRange(0, 17);

  vtkActor *actor2d = vtkActor::New();
  actor2d->SetPosition(2.5,0,0);
  actor2d->SetOrientation(180,0,0);
  actor2d->SetMapper(mapper2d);
  actor2d->GetProperty()->SetRepresentationToWireframe();
  actor2d->GetProperty()->SetAmbient(1.0);
  actor2d->GetProperty()->SetDiffuse(0.0);
  renderer->AddActor(actor2d);

#ifdef WRITE_RESULT
  // Save the result of the filter in a file
  vtkXMLPolyDataWriter *writer2d=vtkXMLPolyDataWriter::New();
  writer2d->SetInputConnection(0,source2d->GetOutputPort(0));
  writer2d->SetFileName("dual2d.vtp");
  writer2d->SetDataModeToAscii();
  writer2d->Write();
  writer2d->Delete();
#endif // #ifdef WRITE_RESULT

  vtkContourFilter *contourDS=vtkContourFilter::New();
  contourDS->SetNumberOfContours(2);
  contourDS->SetValue(0,4.5);
  contourDS->SetValue(1,10.5);

  contourDS->SetInputConnection(0,source3d->GetOutputPort(0));
  cout<<"update contour data set..."<<endl;
  timer->StartTimer();
  contourDS->Update(); // Update now, make things easier with a debugger
  timer->StopTimer();
  cout<<"contour data set updated"<<endl;
  cout<<"contour data set time="<<timer->GetElapsedTime()<<" s"<<endl;

  // This creates a blue to red lut.
  vtkLookupTable *lutDS = vtkLookupTable::New();
  lutDS->SetHueRange (0.667, 0.0);

  vtkPolyDataMapper *mapperDS = vtkPolyDataMapper::New();
  mapperDS->SetInputConnection(0,contourDS->GetOutputPort(0));
  mapperDS->SetLookupTable(lutDS);
  mapperDS->SetScalarRange(0, 17);

  vtkActor *actorDS = vtkActor::New();
  actorDS->SetPosition(2.5,2.5,0);
  actorDS->SetMapper(mapperDS);
  renderer->AddActor(actorDS);

#ifdef WRITE_RESULT
  // Save the result of the filter in a file
  vtkXMLPolyDataWriter *writerDS=vtkXMLPolyDataWriter::New();
  writerDS->SetInputConnection(0,contourDS->GetOutputPort(0));
  writerDS->SetFileName("contourDS.vtp");
  writerDS->SetDataModeToAscii();
  writerDS->Write();
  writerDS->Delete();
#endif // #ifdef WRITE_RESULT

  // Standard testing code.
  renderer->SetBackground(0.5,0.5,0.5);
  renWin->SetSize(300,300);
  vtkCamera *cam=renderer->GetActiveCamera();
  renderer->ResetCamera();
  cam->Azimuth(180);
  cam->Zoom(1.35);
  renWin->Render();

  int retVal = vtkRegressionTestImage( renWin );
  if (retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }

  // Cleanup
  renderer->Delete();
  renWin->Delete();
  iren->Delete();

  contourDS->Delete();
  lutDS->Delete();
  mapperDS->Delete();
  actorDS->Delete();

  source3d->Delete();
  contour3d->Delete();
  mapper3d->Delete();
  actor3d->Delete();
  lut3d->Delete();

  source2d->Delete();
  mapper2d->Delete();
  actor2d->Delete();
  lut2d->Delete();

  timer->Delete();

  return !retVal;
}
<|endoftext|>


<commit_before>#include "clustering/administration/main/import.hpp"

#include "arch/io/network.hpp"
#include "clustering/administration/admin_tracker.hpp"
#include "clustering/administration/auto_reconnect.hpp"
#include "clustering/administration/issues/local.hpp"
#include "clustering/administration/logger.hpp"
#include "clustering/administration/main/initial_join.hpp"
#include "clustering/administration/main/json_import.hpp"
#include "clustering/administration/main/watchable_fields.hpp"
#include "clustering/administration/metadata.hpp"
#include "clustering/administration/network_logger.hpp"
#include "clustering/administration/perfmon_collection_repo.hpp"
#include "clustering/administration/proc_stats.hpp"
#include "clustering/administration/sys_stats.hpp"
#include "extproc/pool.hpp"
#include "http/json.hpp"
#include "rpc/connectivity/multiplexer.hpp"
#include "rpc/directory/read_manager.hpp"
#include "rpc/directory/write_manager.hpp"
#include "rpc/semilattice/semilattice_manager.hpp"
#include "rpc/semilattice/view/field.hpp"
#include "utils.hpp"

bool do_json_importation(const boost::shared_ptr<semilattice_readwrite_view_t<databases_semilattice_metadata_t> > &databases,
                         const boost::shared_ptr<semilattice_readwrite_view_t<cow_ptr_t<namespaces_semilattice_metadata_t<rdb_protocol_t> > > > &namespaces,
                         namespace_repo_t<rdb_protocol_t> *repo, json_importer_t *importer,
                         std::string db_name, std::string table_name, signal_t *interruptor);

bool run_json_import(extproc::spawner_t::info_t *spawner_info, UNUSED io_backender_t *backender, std::set<peer_address_t> joins, int ports_port, int ports_client_port, std::string db_name, std::string table_name, json_importer_t *importer, signal_t *stop_cond) {

    guarantee(spawner_info);
    extproc::pool_group_t extproc_pool_group(spawner_info, extproc::pool_group_t::DEFAULTS);

    machine_id_t machine_id = generate_uuid();

    local_issue_tracker_t local_issue_tracker;
    thread_pool_log_writer_t log_writer(&local_issue_tracker);

    connectivity_cluster_t connectivity_cluster;
    message_multiplexer_t message_multiplexer(&connectivity_cluster);
    message_multiplexer_t::client_t mailbox_manager_client(&message_multiplexer, 'M');
    mailbox_manager_t mailbox_manager(&mailbox_manager_client);
    message_multiplexer_t::client_t::run_t mailbox_manager_client_run(&mailbox_manager_client, &mailbox_manager);

    message_multiplexer_t::client_t semilattice_manager_client(&message_multiplexer, 'S');
    semilattice_manager_t<cluster_semilattice_metadata_t> semilattice_manager_cluster(&semilattice_manager_client, cluster_semilattice_metadata_t());
    message_multiplexer_t::client_t::run_t semilattice_manager_client_run(&semilattice_manager_client, &semilattice_manager_cluster);

    log_server_t log_server(&mailbox_manager, &log_writer);

    stat_manager_t stat_manager(&mailbox_manager);

    metadata_change_handler_t<cluster_semilattice_metadata_t> metadata_change_handler(&mailbox_manager, semilattice_manager_cluster.get_root_view());

    watchable_variable_t<cluster_directory_metadata_t> our_root_directory_variable(
        cluster_directory_metadata_t(
            machine_id,
            get_ips(),
            stat_manager.get_address(),
            metadata_change_handler.get_request_mailbox_address(),
            log_server.get_business_card(),
            PROXY_PEER));

    message_multiplexer_t::client_t directory_manager_client(&message_multiplexer, 'D');
    // TODO(sam): Are we going to use the write manager at all?
    directory_write_manager_t<cluster_directory_metadata_t> directory_write_manager(&directory_manager_client, our_root_directory_variable.get_watchable());
    directory_read_manager_t<cluster_directory_metadata_t> directory_read_manager(connectivity_cluster.get_connectivity_service());
    message_multiplexer_t::client_t::run_t directory_manager_client_run(&directory_manager_client, &directory_read_manager);

    network_logger_t network_logger(
        connectivity_cluster.get_me(),
        directory_read_manager.get_root_view(),
        metadata_field(&cluster_semilattice_metadata_t::machines, semilattice_manager_cluster.get_root_view()));

    message_multiplexer_t::run_t message_multiplexer_run(&message_multiplexer);
    connectivity_cluster_t::run_t connectivity_cluster_run(&connectivity_cluster, ports_port, &message_multiplexer_run, ports_client_port);

    if (0 == ports_port) {
        ports_port = connectivity_cluster_run.get_port();
    } else {
        guarantee(ports_port == connectivity_cluster_run.get_port());
    }
    logINF("Listening for intracluster traffic on port %d.\n", ports_port);

    auto_reconnector_t auto_reconnector(
        &connectivity_cluster,
        &connectivity_cluster_run,
        directory_read_manager.get_root_view()->subview(
            field_getter_t<machine_id_t, cluster_directory_metadata_t>(&cluster_directory_metadata_t::machine_id)),
        metadata_field(&cluster_semilattice_metadata_t::machines, semilattice_manager_cluster.get_root_view()));

    // Skipped field_copier_t, for fun.

    admin_tracker_t admin_tracker(
        semilattice_manager_cluster.get_root_view(), directory_read_manager.get_root_view());

    perfmon_collection_t proc_stats_collection;
    perfmon_membership_t proc_stats_membership(&get_global_perfmon_collection(), &proc_stats_collection, "proc");

    proc_stats_collector_t proc_stats_collector(&proc_stats_collection);

    perfmon_collection_t sys_stats_collection;
    perfmon_membership_t sys_stats_membership(&get_global_perfmon_collection(), &sys_stats_collection, "sys");

    const char *bs_filepath = "";
    sys_stats_collector_t sys_stats_collector(bs_filepath, &sys_stats_collection);

    scoped_ptr_t<initial_joiner_t> initial_joiner;
    if (!joins.empty()) {
        initial_joiner.init(new initial_joiner_t(&connectivity_cluster, &connectivity_cluster_run, joins));
        try {
            wait_interruptible(initial_joiner->get_ready_signal(), stop_cond);
        } catch (interrupted_exc_t) {
            return false;
        }
    }

    perfmon_collection_repo_t perfmon_repo(&get_global_perfmon_collection());

    // Namespace repos

    // (rdb only)

    rdb_protocol_t::context_t rdb_ctx(&extproc_pool_group,
                                      NULL,
                                      semilattice_manager_cluster.get_root_view(),
                                      &directory_read_manager,
                                      machine_id);

    namespace_repo_t<rdb_protocol_t> rdb_namespace_repo(&mailbox_manager,
        directory_read_manager.get_root_view()->subview(
            field_getter_t<namespaces_directory_metadata_t<rdb_protocol_t>, cluster_directory_metadata_t>(&cluster_directory_metadata_t::rdb_namespaces)),
        &rdb_ctx);

    //This is an annoying chicken and egg problem here
    rdb_ctx.ns_repo = &rdb_namespace_repo;

    // TODO: Handle interrupted exceptions?
    return do_json_importation(metadata_field(&cluster_semilattice_metadata_t::databases, semilattice_manager_cluster.get_root_view()),
                               metadata_field(&cluster_semilattice_metadata_t::rdb_namespaces, semilattice_manager_cluster.get_root_view()),
                               &rdb_namespace_repo, importer, db_name, table_name, stop_cond);
}

bool get_or_create_namespace(const boost::shared_ptr<semilattice_readwrite_view_t<cow_ptr_t<namespaces_semilattice_metadata_t<rdb_protocol_t> > > > &namespaces,
                             database_id_t db_id,
                             std::string table_name,
                             namespace_id_t *namespace_out) {
    namespaces_semilattice_metadata_t<rdb_protocol_t> ns = *namespaces->get();
    metadata_searcher_t<namespace_semilattice_metadata_t<rdb_protocol_t> > searcher(&ns.namespaces);
    const char *error;
    std::map<namespace_id_t, deletable_t<namespace_semilattice_metadata_t<rdb_protocol_t> > >::iterator it = searcher.find_uniq(namespace_predicate_t(table_name, db_id), &error);

    if (error != METADATA_SUCCESS) {
        *namespace_out = namespace_id_t();
        return false;
    } else {
        *namespace_out = it->first;
        return true;
    }
}

bool get_or_create_database(const boost::shared_ptr<semilattice_readwrite_view_t<databases_semilattice_metadata_t> > &databases, std::string db_name, database_id_t *db_out) {
    std::map<database_id_t, deletable_t<database_semilattice_metadata_t> > dbmap = databases->get().databases;
    metadata_searcher_t<database_semilattice_metadata_t> searcher(&dbmap);

    const char *error;
    std::map<database_id_t, deletable_t<database_semilattice_metadata_t> >::iterator it = searcher.find_uniq(db_name, &error);

    if (error != METADATA_SUCCESS) {
        // TODO(sam): Actually support _creating_ the database.
        *db_out = database_id_t();
        return false;
    } else {
        *db_out = it->first;
        return true;
    }
}

bool do_json_importation(const boost::shared_ptr<semilattice_readwrite_view_t<databases_semilattice_metadata_t> > &databases,
                         const boost::shared_ptr<semilattice_readwrite_view_t<cow_ptr_t<namespaces_semilattice_metadata_t<rdb_protocol_t> > > > &namespaces,
                         namespace_repo_t<rdb_protocol_t> *repo, json_importer_t *importer,
                         std::string db_name, std::string table_name, signal_t *interruptor) {

    database_id_t db_id;
    if (!get_or_create_database(databases, db_name, &db_id)) {
        return false;
    }

    namespace_id_t namespace_id;
    if (!get_or_create_namespace(namespaces, db_id, table_name, &namespace_id)) {
        return false;
    }

    // TODO(sam): What if construction fails?  An exception is thrown?
    namespace_repo_t<rdb_protocol_t>::access_t access(repo, namespace_id, interruptor);

    UNUSED namespace_interface_t<rdb_protocol_t> *ni = access.get_namespace_if();

    // bogus implementation
    for (scoped_cJSON_t json; importer->get_json(&json); json.reset(NULL)) {
        debugf("json: %s\n", json.Print().c_str());
    }

    debugf("do_json_importation ... returning bogus success!\n");
    return true;
}
<commit_msg>Separate unimplemented branches for METADATA_ERR_NONE.<commit_after>#include "clustering/administration/main/import.hpp"

#include "arch/io/network.hpp"
#include "clustering/administration/admin_tracker.hpp"
#include "clustering/administration/auto_reconnect.hpp"
#include "clustering/administration/issues/local.hpp"
#include "clustering/administration/logger.hpp"
#include "clustering/administration/main/initial_join.hpp"
#include "clustering/administration/main/json_import.hpp"
#include "clustering/administration/main/watchable_fields.hpp"
#include "clustering/administration/metadata.hpp"
#include "clustering/administration/network_logger.hpp"
#include "clustering/administration/perfmon_collection_repo.hpp"
#include "clustering/administration/proc_stats.hpp"
#include "clustering/administration/sys_stats.hpp"
#include "extproc/pool.hpp"
#include "http/json.hpp"
#include "rpc/connectivity/multiplexer.hpp"
#include "rpc/directory/read_manager.hpp"
#include "rpc/directory/write_manager.hpp"
#include "rpc/semilattice/semilattice_manager.hpp"
#include "rpc/semilattice/view/field.hpp"
#include "utils.hpp"

bool do_json_importation(const boost::shared_ptr<semilattice_readwrite_view_t<databases_semilattice_metadata_t> > &databases,
                         const boost::shared_ptr<semilattice_readwrite_view_t<cow_ptr_t<namespaces_semilattice_metadata_t<rdb_protocol_t> > > > &namespaces,
                         namespace_repo_t<rdb_protocol_t> *repo, json_importer_t *importer,
                         std::string db_name, std::string table_name, signal_t *interruptor);

bool run_json_import(extproc::spawner_t::info_t *spawner_info, UNUSED io_backender_t *backender, std::set<peer_address_t> joins, int ports_port, int ports_client_port, std::string db_name, std::string table_name, json_importer_t *importer, signal_t *stop_cond) {

    guarantee(spawner_info);
    extproc::pool_group_t extproc_pool_group(spawner_info, extproc::pool_group_t::DEFAULTS);

    machine_id_t machine_id = generate_uuid();

    local_issue_tracker_t local_issue_tracker;
    thread_pool_log_writer_t log_writer(&local_issue_tracker);

    connectivity_cluster_t connectivity_cluster;
    message_multiplexer_t message_multiplexer(&connectivity_cluster);
    message_multiplexer_t::client_t mailbox_manager_client(&message_multiplexer, 'M');
    mailbox_manager_t mailbox_manager(&mailbox_manager_client);
    message_multiplexer_t::client_t::run_t mailbox_manager_client_run(&mailbox_manager_client, &mailbox_manager);

    message_multiplexer_t::client_t semilattice_manager_client(&message_multiplexer, 'S');
    semilattice_manager_t<cluster_semilattice_metadata_t> semilattice_manager_cluster(&semilattice_manager_client, cluster_semilattice_metadata_t());
    message_multiplexer_t::client_t::run_t semilattice_manager_client_run(&semilattice_manager_client, &semilattice_manager_cluster);

    log_server_t log_server(&mailbox_manager, &log_writer);

    stat_manager_t stat_manager(&mailbox_manager);

    metadata_change_handler_t<cluster_semilattice_metadata_t> metadata_change_handler(&mailbox_manager, semilattice_manager_cluster.get_root_view());

    watchable_variable_t<cluster_directory_metadata_t> our_root_directory_variable(
        cluster_directory_metadata_t(
            machine_id,
            get_ips(),
            stat_manager.get_address(),
            metadata_change_handler.get_request_mailbox_address(),
            log_server.get_business_card(),
            PROXY_PEER));

    message_multiplexer_t::client_t directory_manager_client(&message_multiplexer, 'D');
    // TODO(sam): Are we going to use the write manager at all?
    directory_write_manager_t<cluster_directory_metadata_t> directory_write_manager(&directory_manager_client, our_root_directory_variable.get_watchable());
    directory_read_manager_t<cluster_directory_metadata_t> directory_read_manager(connectivity_cluster.get_connectivity_service());
    message_multiplexer_t::client_t::run_t directory_manager_client_run(&directory_manager_client, &directory_read_manager);

    network_logger_t network_logger(
        connectivity_cluster.get_me(),
        directory_read_manager.get_root_view(),
        metadata_field(&cluster_semilattice_metadata_t::machines, semilattice_manager_cluster.get_root_view()));

    message_multiplexer_t::run_t message_multiplexer_run(&message_multiplexer);
    connectivity_cluster_t::run_t connectivity_cluster_run(&connectivity_cluster, ports_port, &message_multiplexer_run, ports_client_port);

    if (0 == ports_port) {
        ports_port = connectivity_cluster_run.get_port();
    } else {
        guarantee(ports_port == connectivity_cluster_run.get_port());
    }
    logINF("Listening for intracluster traffic on port %d.\n", ports_port);

    auto_reconnector_t auto_reconnector(
        &connectivity_cluster,
        &connectivity_cluster_run,
        directory_read_manager.get_root_view()->subview(
            field_getter_t<machine_id_t, cluster_directory_metadata_t>(&cluster_directory_metadata_t::machine_id)),
        metadata_field(&cluster_semilattice_metadata_t::machines, semilattice_manager_cluster.get_root_view()));

    // Skipped field_copier_t, for fun.

    admin_tracker_t admin_tracker(
        semilattice_manager_cluster.get_root_view(), directory_read_manager.get_root_view());

    perfmon_collection_t proc_stats_collection;
    perfmon_membership_t proc_stats_membership(&get_global_perfmon_collection(), &proc_stats_collection, "proc");

    proc_stats_collector_t proc_stats_collector(&proc_stats_collection);

    perfmon_collection_t sys_stats_collection;
    perfmon_membership_t sys_stats_membership(&get_global_perfmon_collection(), &sys_stats_collection, "sys");

    const char *bs_filepath = "";
    sys_stats_collector_t sys_stats_collector(bs_filepath, &sys_stats_collection);

    scoped_ptr_t<initial_joiner_t> initial_joiner;
    if (!joins.empty()) {
        initial_joiner.init(new initial_joiner_t(&connectivity_cluster, &connectivity_cluster_run, joins));
        try {
            wait_interruptible(initial_joiner->get_ready_signal(), stop_cond);
        } catch (interrupted_exc_t) {
            return false;
        }
    }

    perfmon_collection_repo_t perfmon_repo(&get_global_perfmon_collection());

    // Namespace repos

    // (rdb only)

    rdb_protocol_t::context_t rdb_ctx(&extproc_pool_group,
                                      NULL,
                                      semilattice_manager_cluster.get_root_view(),
                                      &directory_read_manager,
                                      machine_id);

    namespace_repo_t<rdb_protocol_t> rdb_namespace_repo(&mailbox_manager,
        directory_read_manager.get_root_view()->subview(
            field_getter_t<namespaces_directory_metadata_t<rdb_protocol_t>, cluster_directory_metadata_t>(&cluster_directory_metadata_t::rdb_namespaces)),
        &rdb_ctx);

    //This is an annoying chicken and egg problem here
    rdb_ctx.ns_repo = &rdb_namespace_repo;

    // TODO: Handle interrupted exceptions?
    return do_json_importation(metadata_field(&cluster_semilattice_metadata_t::databases, semilattice_manager_cluster.get_root_view()),
                               metadata_field(&cluster_semilattice_metadata_t::rdb_namespaces, semilattice_manager_cluster.get_root_view()),
                               &rdb_namespace_repo, importer, db_name, table_name, stop_cond);
}

bool get_or_create_namespace(const boost::shared_ptr<semilattice_readwrite_view_t<cow_ptr_t<namespaces_semilattice_metadata_t<rdb_protocol_t> > > > &namespaces,
                             database_id_t db_id,
                             std::string table_name,
                             namespace_id_t *namespace_out) {
    namespaces_semilattice_metadata_t<rdb_protocol_t> ns = *namespaces->get();
    metadata_searcher_t<namespace_semilattice_metadata_t<rdb_protocol_t> > searcher(&ns.namespaces);
    const char *error;
    std::map<namespace_id_t, deletable_t<namespace_semilattice_metadata_t<rdb_protocol_t> > >::iterator it = searcher.find_uniq(namespace_predicate_t(table_name, db_id), &error);

    if (error == METADATA_SUCCESS) {
        *namespace_out = it->first;
        return true;
    } else if (error == METADATA_ERR_NONE) {
        // TODO(sam):  impl this.
        *namespace_out = namespace_id_t();
        return false;
    } else {
        *namespace_out = namespace_id_t();
        return false;
    }
}

bool get_or_create_database(const boost::shared_ptr<semilattice_readwrite_view_t<databases_semilattice_metadata_t> > &databases, std::string db_name, database_id_t *db_out) {
    std::map<database_id_t, deletable_t<database_semilattice_metadata_t> > dbmap = databases->get().databases;
    metadata_searcher_t<database_semilattice_metadata_t> searcher(&dbmap);

    const char *error;
    std::map<database_id_t, deletable_t<database_semilattice_metadata_t> >::iterator it = searcher.find_uniq(db_name, &error);

    if (error == METADATA_SUCCESS) {
        *db_out = it->first;
        return true;
    } else if (error == METADATA_ERR_NONE) {
        // TODO(sam): Impl this.
        *db_out = database_id_t();
        return false;
    } else {
        // TODO(sam): Actually support _creating_ the database.
        *db_out = database_id_t();
        return false;
    }
}

bool do_json_importation(const boost::shared_ptr<semilattice_readwrite_view_t<databases_semilattice_metadata_t> > &databases,
                         const boost::shared_ptr<semilattice_readwrite_view_t<cow_ptr_t<namespaces_semilattice_metadata_t<rdb_protocol_t> > > > &namespaces,
                         namespace_repo_t<rdb_protocol_t> *repo, json_importer_t *importer,
                         std::string db_name, std::string table_name, signal_t *interruptor) {

    database_id_t db_id;
    if (!get_or_create_database(databases, db_name, &db_id)) {
        return false;
    }

    namespace_id_t namespace_id;
    if (!get_or_create_namespace(namespaces, db_id, table_name, &namespace_id)) {
        return false;
    }

    // TODO(sam): What if construction fails?  An exception is thrown?
    namespace_repo_t<rdb_protocol_t>::access_t access(repo, namespace_id, interruptor);

    UNUSED namespace_interface_t<rdb_protocol_t> *ni = access.get_namespace_if();

    // bogus implementation
    for (scoped_cJSON_t json; importer->get_json(&json); json.reset(NULL)) {
        debugf("json: %s\n", json.Print().c_str());
    }

    debugf("do_json_importation ... returning bogus success!\n");
    return true;
}
<|endoftext|>