<commit_before>#include "server/httplistener.h"
#include "common/config.h"

#include <Poco/Net/HTTPServer.h>
#include <Poco/Exception.h>

/*
 * http://www.codeproject.com/Articles/252827/Learning-Poco-A-simple-HTTP-server
 */

using namespace Batyr;

HttpListener::HttpListener(Configuration::Ptr _configuration)
    :   BaseListener(_configuration),
        logger(Poco::Logger::get("HttpListener")),
        isRunning(false)
{
    // prepare the server parameters and let them be managed by
    // a smart pointer
    auto serverParams = new Poco::Net::HTTPServerParams;
    serverParams->setMaxThreads( SERVER_HTTP_THREADS );
    serverParamsPtr.assign(serverParams);

    // set up the network socket
    try {
        socket.bind( configuration->getHttpPort() );
        socket.listen();
    }
    catch (Poco::Exception& e) {
        poco_error(logger, e.message());
        e.rethrow();
    }

    // will get destroyed with by the poco httpserver
    auto handlerFactory = new Batyr::HTTPRequestHandlerFactory(configuration);
    handlerFactoryPtr.assign(handlerFactory);

    server.reset(new Poco::Net::HTTPServer(handlerFactoryPtr, socket, serverParamsPtr));
}

HttpListener::~HttpListener()
{
    stop();
}

void
HttpListener::run()
{
    poco_debug(logger, "Starting http listener");
    if (!isRunning) {

        // set the joblist
        handlerFactoryPtr->setJobs(jobs);

        server->start();
        isRunning = true;
    }
}

void
HttpListener::stop()
{
    poco_debug(logger, "Stopping http listener");
    if (isRunning) {
        server->stop();
        isRunning = false;
    }
}
<commit_msg>closing http socket on shutdown<commit_after>#include "server/httplistener.h"
#include "common/config.h"

#include <Poco/Net/HTTPServer.h>
#include <Poco/Exception.h>

/*
 * http://www.codeproject.com/Articles/252827/Learning-Poco-A-simple-HTTP-server
 */

using namespace Batyr;

HttpListener::HttpListener(Configuration::Ptr _configuration)
    :   BaseListener(_configuration),
        logger(Poco::Logger::get("HttpListener")),
        isRunning(false)
{
    // prepare the server parameters and let them be managed by
    // a smart pointer
    auto serverParams = new Poco::Net::HTTPServerParams;
    serverParams->setMaxThreads( SERVER_HTTP_THREADS );
    serverParamsPtr.assign(serverParams);

    // set up the network socket
    try {
        socket.bind( configuration->getHttpPort() );
        socket.listen();
    }
    catch (Poco::Exception& e) {
        poco_error(logger, e.message());
        e.rethrow();
    }

    // will get destroyed with by the poco httpserver
    auto handlerFactory = new Batyr::HTTPRequestHandlerFactory(configuration);
    handlerFactoryPtr.assign(handlerFactory);

    server.reset(new Poco::Net::HTTPServer(handlerFactoryPtr, socket, serverParamsPtr));
}

HttpListener::~HttpListener()
{
    stop();
    socket.close();
}

void
HttpListener::run()
{
    poco_debug(logger, "Starting http listener");
    if (!isRunning) {

        // set the joblist
        handlerFactoryPtr->setJobs(jobs);

        server->start();
        isRunning = true;
    }
}

void
HttpListener::stop()
{
    poco_debug(logger, "Stopping http listener");
    if (isRunning) {
        server->stop();
        isRunning = false;
    }
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015-2016, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <string.h>

#include <node.h>
#include <nan.h>
#include "grpc/grpc.h"
#include "grpc/byte_buffer_reader.h"
#include "grpc/support/slice.h"

#include "byte_buffer.h"

namespace grpc {
namespace node {

using v8::Context;
using v8::Function;
using v8::Local;
using v8::Object;
using v8::Number;
using v8::Value;

grpc_byte_buffer *BufferToByteBuffer(Local<Value> buffer) {
  Nan::HandleScope scope;
  int length = ::node::Buffer::Length(buffer);
  char *data = ::node::Buffer::Data(buffer);
  gpr_slice slice = gpr_slice_malloc(length);
  memcpy(GPR_SLICE_START_PTR(slice), data, length);
  grpc_byte_buffer *byte_buffer(grpc_raw_byte_buffer_create(&slice, 1));
  gpr_slice_unref(slice);
  return byte_buffer;
}

Local<Value> ByteBufferToBuffer(grpc_byte_buffer *buffer) {
  Nan::EscapableHandleScope scope;
  if (buffer == NULL) {
    return scope.Escape(Nan::Null());
  }
  size_t length = grpc_byte_buffer_length(buffer);
  char *result = new char[length];
  size_t offset = 0;
  grpc_byte_buffer_reader reader;
  grpc_byte_buffer_reader_init(&reader, buffer);
  gpr_slice next;
  while (grpc_byte_buffer_reader_next(&reader, &next) != 0) {
    memcpy(result + offset, GPR_SLICE_START_PTR(next), GPR_SLICE_LENGTH(next));
    offset += GPR_SLICE_LENGTH(next);
    gpr_slice_unref(next);
  }
  return scope.Escape(MakeFastBuffer(
      Nan::NewBuffer(result, length).ToLocalChecked()));
}

Local<Value> MakeFastBuffer(Local<Value> slowBuffer) {
  Nan::EscapableHandleScope scope;
  Local<Object> globalObj = Nan::GetCurrentContext()->Global();
  Local<Function> bufferConstructor = Local<Function>::Cast(
      globalObj->Get(Nan::New("Buffer").ToLocalChecked()));
  Local<Value> consArgs[3] = {
    slowBuffer,
    Nan::New<Number>(::node::Buffer::Length(slowBuffer)),
    Nan::New<Number>(0)
  };
  Local<Object> fastBuffer = bufferConstructor->NewInstance(3, consArgs);
  return scope.Escape(fastBuffer);
}
}  // namespace node
}  // namespace grpc
<commit_msg>Pass delete[] explicitely to Nan::NewBuffer.<commit_after>/*
 *
 * Copyright 2015-2016, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <string.h>

#include <node.h>
#include <nan.h>
#include "grpc/grpc.h"
#include "grpc/byte_buffer_reader.h"
#include "grpc/support/slice.h"

#include "byte_buffer.h"

namespace grpc {
namespace node {

using v8::Context;
using v8::Function;
using v8::Local;
using v8::Object;
using v8::Number;
using v8::Value;

grpc_byte_buffer *BufferToByteBuffer(Local<Value> buffer) {
  Nan::HandleScope scope;
  int length = ::node::Buffer::Length(buffer);
  char *data = ::node::Buffer::Data(buffer);
  gpr_slice slice = gpr_slice_malloc(length);
  memcpy(GPR_SLICE_START_PTR(slice), data, length);
  grpc_byte_buffer *byte_buffer(grpc_raw_byte_buffer_create(&slice, 1));
  gpr_slice_unref(slice);
  return byte_buffer;
}

namespace {
void delete_buffer(char *data, void *hint) { delete[] data; }
}

Local<Value> ByteBufferToBuffer(grpc_byte_buffer *buffer) {
  Nan::EscapableHandleScope scope;
  if (buffer == NULL) {
    return scope.Escape(Nan::Null());
  }
  size_t length = grpc_byte_buffer_length(buffer);
  char *result = new char[length];
  size_t offset = 0;
  grpc_byte_buffer_reader reader;
  grpc_byte_buffer_reader_init(&reader, buffer);
  gpr_slice next;
  while (grpc_byte_buffer_reader_next(&reader, &next) != 0) {
    memcpy(result + offset, GPR_SLICE_START_PTR(next), GPR_SLICE_LENGTH(next));
    offset += GPR_SLICE_LENGTH(next);
    gpr_slice_unref(next);
  }
  return scope.Escape(MakeFastBuffer(
      Nan::NewBuffer(result, length, delete_buffer, NULL).ToLocalChecked()));
}

Local<Value> MakeFastBuffer(Local<Value> slowBuffer) {
  Nan::EscapableHandleScope scope;
  Local<Object> globalObj = Nan::GetCurrentContext()->Global();
  Local<Function> bufferConstructor = Local<Function>::Cast(
      globalObj->Get(Nan::New("Buffer").ToLocalChecked()));
  Local<Value> consArgs[3] = {
    slowBuffer,
    Nan::New<Number>(::node::Buffer::Length(slowBuffer)),
    Nan::New<Number>(0)
  };
  Local<Object> fastBuffer = bufferConstructor->NewInstance(3, consArgs);
  return scope.Escape(fastBuffer);
}
}  // namespace node
}  // namespace grpc
<|endoftext|>


<commit_before>/*
    This file is part of KAddressBook.
    Copyright (c) 2002 Mike Pilone <mpilone@slac.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <QLayout>
#include <kvbox.h>
//Added by qt3to4:
#include <QPixmap>
#include <QVBoxLayout>

#include <kconfig.h>
#include <kdebug.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kpagewidget.h>
#include <ktoolinvocation.h>

#include "viewconfigurefieldspage.h"
#include "viewconfigurefilterpage.h"
#include "viewmanager.h"

#include "viewconfigurewidget.h"

ViewConfigureWidget::ViewConfigureWidget( KABC::AddressBook *ab, QWidget *parent )
  : KAB::ConfigureWidget( ab, parent )
{
  QVBoxLayout *topLayout = new QVBoxLayout( this );

  mMainWidget = new KPageWidget( this );
  mMainWidget->setFaceType( KPageView::List );
  topLayout->addWidget( mMainWidget );

  // Add the first page, the attributes
  KVBox *page = addPage( i18n( "Fields" ), QString(),
                         KIconLoader::global()->loadIcon( "view_detailed",
                         K3Icon::Panel ) );

  // Add the select fields page
  mFieldsPage = new ViewConfigureFieldsPage( addressBook(), page );

  // Add the second page, the filter selection
  page = addPage( i18n( "Default Filter" ), QString(),
                  KIconLoader::global()->loadIcon( "filter",
                  K3Icon::Panel ) );

  mFilterPage = new ViewConfigureFilterPage( page );
}

ViewConfigureWidget::~ViewConfigureWidget()
{
}

void ViewConfigureWidget::restoreSettings( KConfig *config )
{
  mFieldsPage->restoreSettings( config );
  mFilterPage->restoreSettings( config );
}

void ViewConfigureWidget::saveSettings( KConfig *config )
{
  mFieldsPage->saveSettings( config );
  mFilterPage->saveSettings( config );
}

KVBox *ViewConfigureWidget::addPage( const QString &item, const QString &header,
                                   const QPixmap &pixmap )
{
  KVBox *page = new KVBox( mMainWidget );
#ifdef __GNUC__
#warning What about the page icon and page header?
#endif
  mMainWidget->addPage( page, item );
  return page;
}

ViewConfigureDialog::ViewConfigureDialog( ViewConfigureWidget *wdg, const QString &viewName,
                                          QWidget *parent, const char *name )
  : KDialog( parent ), mConfigWidget( wdg )
{
  setCaption( i18n( "Modify View: " ) + viewName );
  setButtons( Help | Ok | Cancel );
  setDefaultButton( Ok );
  showButtonSeparator( true );

  setMainWidget( mConfigWidget );
  connect(this,SIGNAL(helpClicked()),this,SLOT(slotHelp()));
  resize( 600, 300 );
}

ViewConfigureDialog::~ViewConfigureDialog()
{
}

void ViewConfigureDialog::restoreSettings( KConfig *config )
{
  mConfigWidget->restoreSettings( config );
}

void ViewConfigureDialog::saveSettings( KConfig *config )
{
  mConfigWidget->saveSettings( config );
}

void ViewConfigureDialog::slotHelp()
{
  KToolInvocation::invokeHelp( "using-views" );
}

#include "viewconfigurewidget.moc"
<commit_msg>Port++<commit_after>/*
    This file is part of KAddressBook.
    Copyright (c) 2002 Mike Pilone <mpilone@slac.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <QLayout>
#include <kvbox.h>
//Added by qt3to4:
#include <QPixmap>
#include <QVBoxLayout>

#include <kconfig.h>
#include <kdebug.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kpagewidget.h>
#include <ktoolinvocation.h>

#include "viewconfigurefieldspage.h"
#include "viewconfigurefilterpage.h"
#include "viewmanager.h"

#include "viewconfigurewidget.h"

ViewConfigureWidget::ViewConfigureWidget( KABC::AddressBook *ab, QWidget *parent )
  : KAB::ConfigureWidget( ab, parent )
{
  QVBoxLayout *topLayout = new QVBoxLayout( this );

  mMainWidget = new KPageWidget( this );
  mMainWidget->setFaceType( KPageView::List );
  topLayout->addWidget( mMainWidget );

  // Add the first page, the attributes
  KVBox *page = addPage( i18n( "Fields" ), QString(),
                         KIconLoader::global()->loadIcon( "view_detailed",
                         K3Icon::Panel ) );

  // Add the select fields page
  mFieldsPage = new ViewConfigureFieldsPage( addressBook(), page );

  // Add the second page, the filter selection
  page = addPage( i18n( "Default Filter" ), QString(),
                  KIconLoader::global()->loadIcon( "filter",
                  K3Icon::Panel ) );

  mFilterPage = new ViewConfigureFilterPage( page );
}

ViewConfigureWidget::~ViewConfigureWidget()
{
}

void ViewConfigureWidget::restoreSettings( KConfig *config )
{
  mFieldsPage->restoreSettings( config );
  mFilterPage->restoreSettings( config );
}

void ViewConfigureWidget::saveSettings( KConfig *config )
{
  mFieldsPage->saveSettings( config );
  mFilterPage->saveSettings( config );
}

KVBox *ViewConfigureWidget::addPage( const QString &item, const QString &header,
                                   const QPixmap &pixmap )
{
  KVBox *page = new KVBox( mMainWidget );
  KPageWidgetItem*itemPage=mMainWidget->addPage( page, item );
  itemPage->setHeader(header);
  itemPage->setIcon(KIcon(pixmap));
  return page;
}

ViewConfigureDialog::ViewConfigureDialog( ViewConfigureWidget *wdg, const QString &viewName,
                                          QWidget *parent, const char *name )
  : KDialog( parent ), mConfigWidget( wdg )
{
  setCaption( i18n( "Modify View: " ) + viewName );
  setButtons( Help | Ok | Cancel );
  setDefaultButton( Ok );
  showButtonSeparator( true );

  setMainWidget( mConfigWidget );
  connect(this,SIGNAL(helpClicked()),this,SLOT(slotHelp()));
  resize( 600, 300 );
}

ViewConfigureDialog::~ViewConfigureDialog()
{
}

void ViewConfigureDialog::restoreSettings( KConfig *config )
{
  mConfigWidget->restoreSettings( config );
}

void ViewConfigureDialog::saveSettings( KConfig *config )
{
  mConfigWidget->saveSettings( config );
}

void ViewConfigureDialog::slotHelp()
{
  KToolInvocation::invokeHelp( "using-views" );
}

#include "viewconfigurewidget.moc"
<|endoftext|>


<commit_before>/// @file
/// @author uentity
/// @date 23.04.2019
/// @brief BS kernel Python subsystem impl
/// @copyright
/// This Source Code Form is subject to the terms of the Mozilla Public License,
/// v. 2.0. If a copy of the MPL was not distributed with this file,
/// You can obtain one at https://mozilla.org/MPL/2.0/

#include <bs/python/common.h>
#include <bs/log.h>
#include <bs/kernel/errors.h>

#include "kimpl.h"
#include "python_subsyst_impl.h"
#include "plugins_subsyst.h"

#include <functional>

#define WITH_KMOD \
[[maybe_unused]] auto res = pykmod(this).map([&](auto kmod_ptr) { \
[[maybe_unused]] auto& kmod = *kmod_ptr;

#define END_WITH });

#define RETURN_WITH END_WITH return res.value();

#define RETURN_WITH_FAIL(err_val) END_WITH return res.value_or(err_val);

NAMESPACE_BEGIN(blue_sky::kernel::detail)
using namespace blue_sky::detail;
namespace py = pybind11;

NAMESPACE_BEGIN()

auto pykmod(const python_subsyst* v) -> result_or_err<pybind11::module*> {
	if(v) if(auto kmod = v->py_kmod())
		return { static_cast<pybind11::module*>(kmod) };
	return tl::unexpected{Error::BadPymod};
}

std::string extract_root_name(const std::string& full_name) {
	using namespace std;

	//extract user-friendly lib name from full name
	string pyl_name = full_name;
	//cut path
	string::size_type pos = pyl_name.rfind('/');
	if(pos != string::npos) pyl_name = pyl_name.substr(pos + 1, string::npos);
	pos = pyl_name.rfind('\\');
	if(pos != string::npos) pyl_name = pyl_name.substr(pos + 1, string::npos);
	//cut extension
	pyl_name = pyl_name.substr(0, pyl_name.find('.'));
	//cut "lib" prefix if exists
	if(pyl_name.compare(0, 3, string("lib")) == 0)
		pyl_name = pyl_name.substr(3, string::npos);

	return pyl_name;
}

constexpr auto sp_obj_hash = std::hash<sp_obj>{};

NAMESPACE_END()

python_subsyst_impl::python_subsyst_impl(void* kmod_ptr) {
	setup_py_kmod(kmod_ptr);
}

auto python_subsyst_impl::py_kmod() const -> void* { return kmod_; }

auto python_subsyst_impl::setup_py_kmod(void* kmod_ptr) -> void {
	if(kmod_ptr) {
		kmod_ = kmod_ptr;
		auto& kmod = *static_cast<pybind11::module*>(kmod_);

		auto& kpd = plugins_subsyst::kernel_pd();
		kmod.doc() = kpd.description;
		kpd.py_namespace = PyModule_GetName(kmod.ptr());
	}
}

auto python_subsyst_impl::py_init_plugin(
	const blue_sky::detail::lib_descriptor& lib, plugin_descriptor& p_descr
) -> result_or_err<std::string> {
	return pykmod(this).and_then([&](auto kmod_ptr) -> result_or_err<std::string> {
		bs_init_py_fn init_py_fn;
		lib.load_sym("bs_init_py_subsystem", init_py_fn);
		if(!init_py_fn) return tl::make_unexpected(error{p_descr.name, kernel::Error::PythonDisabled});

		if(p_descr.py_namespace.empty())
			p_descr.py_namespace = extract_root_name(lib.fname_);

		// create submodule
		auto plugin_mod = kmod_ptr->def_submodule(p_descr.py_namespace.c_str(), p_descr.description.c_str());
		// invoke init function
		init_py_fn(&plugin_mod);

		return plugins_subsyst::kernel_pd().py_namespace + '.' + p_descr.py_namespace;
	});
}

auto python_subsyst_impl::py_add_error_closure() -> void {
WITH_KMOD
	auto err_class = (pybind11::class_<std::error_code>)kmod.attr("error_code");
	pybind11::init([](int ec) {
		return std::error_code(static_cast<Error>(ec));
	}).execute(err_class);
END_WITH
}

auto python_subsyst_impl::register_adapter(std::string obj_type_id, adapter_fn f) -> void {
	if(f)
		adapters_.insert_or_assign(std::move(obj_type_id), std::move(f));
	else {
		auto pa = adapters_.find(obj_type_id);
		if(pa != adapters_.end())
			adapters_.erase(pa);
	}
}

auto python_subsyst_impl::register_default_adapter(adapter_fn f) -> void {
	def_adapter_ = std::move(f);
}

auto python_subsyst_impl::clear_adapters() -> void {
	adapters_.clear();
	def_adapter_ = nullptr;
}

auto python_subsyst_impl::adapted_types() const -> std::vector<std::string> {
	std::vector<std::string> res(adapters_.size());
	std::transform(
		adapters_.begin(), adapters_.end(), res.begin(),
		[](const auto& A){ return A.first; }
	);
	if(def_adapter_) res.push_back("*");
	return res;
}

auto python_subsyst_impl::adapt(sp_obj source) -> py::object {
	if(!source) return py::none();
	// check if adpater already created for given object
	auto cached_A = acache_.find(sp_obj_hash(source));
	if(cached_A != acache_.end())
		return cached_A->second;
	// adapt or passthrough
	auto pf = adapters_.find(source->type_id());
	auto&& obj = std::move(source);
	auto A = pf != adapters_.end() ?
		pf->second(obj) :
		( def_adapter_ ? def_adapter_(obj) : py::cast(obj) );
	// cache adapter instance
	acache_[sp_obj_hash(source)] = A;
	return A;
}

auto python_subsyst_impl::drop_adapted_cache(const sp_obj& obj) -> std::size_t {
	std::size_t res = 0;
	if(!obj) {
		res = acache_.size();
		acache_.clear();
	}
	else {
		auto cached_A = acache_.find(sp_obj_hash(obj));
		if(cached_A != acache_.end()) {
			acache_.erase(cached_A);
			res = 1;
		}
	}
	return res;
}

auto python_subsyst_impl::self() -> python_subsyst_impl& {
	// [NOTE] unconditional cast, because if self() is called, then instance MUST be self for sure
	return static_cast<python_subsyst_impl&>(singleton<python_subsyst>::Instance());
}

NAMESPACE_END(blue_sky::kernel::detail)
<commit_msg>kernel/python: null-init kernel kmod ptr with when not in Py environment<commit_after>/// @file
/// @author uentity
/// @date 23.04.2019
/// @brief BS kernel Python subsystem impl
/// @copyright
/// This Source Code Form is subject to the terms of the Mozilla Public License,
/// v. 2.0. If a copy of the MPL was not distributed with this file,
/// You can obtain one at https://mozilla.org/MPL/2.0/

#include <bs/python/common.h>
#include <bs/log.h>
#include <bs/kernel/errors.h>

#include "kimpl.h"
#include "python_subsyst_impl.h"
#include "plugins_subsyst.h"

#include <functional>

#define WITH_KMOD \
[[maybe_unused]] auto res = pykmod(this).map([&](auto kmod_ptr) { \
[[maybe_unused]] auto& kmod = *kmod_ptr;

#define END_WITH });

#define RETURN_WITH END_WITH return res.value();

#define RETURN_WITH_FAIL(err_val) END_WITH return res.value_or(err_val);

NAMESPACE_BEGIN(blue_sky::kernel::detail)
using namespace blue_sky::detail;
namespace py = pybind11;

NAMESPACE_BEGIN()

auto pykmod(const python_subsyst* v) -> result_or_err<pybind11::module*> {
	if(v) if(auto kmod = v->py_kmod())
		return { static_cast<pybind11::module*>(kmod) };
	return tl::unexpected{Error::BadPymod};
}

std::string extract_root_name(const std::string& full_name) {
	using namespace std;

	//extract user-friendly lib name from full name
	string pyl_name = full_name;
	//cut path
	string::size_type pos = pyl_name.rfind('/');
	if(pos != string::npos) pyl_name = pyl_name.substr(pos + 1, string::npos);
	pos = pyl_name.rfind('\\');
	if(pos != string::npos) pyl_name = pyl_name.substr(pos + 1, string::npos);
	//cut extension
	pyl_name = pyl_name.substr(0, pyl_name.find('.'));
	//cut "lib" prefix if exists
	if(pyl_name.compare(0, 3, string("lib")) == 0)
		pyl_name = pyl_name.substr(3, string::npos);

	return pyl_name;
}

constexpr auto sp_obj_hash = std::hash<sp_obj>{};

NAMESPACE_END()

python_subsyst_impl::python_subsyst_impl(void* kmod_ptr)
	: kmod_(nullptr)
{
	setup_py_kmod(kmod_ptr);
}

auto python_subsyst_impl::py_kmod() const -> void* { return kmod_; }

auto python_subsyst_impl::setup_py_kmod(void* kmod_ptr) -> void {
	if(kmod_ptr) {
		kmod_ = kmod_ptr;
		auto& kmod = *static_cast<pybind11::module*>(kmod_);

		auto& kpd = plugins_subsyst::kernel_pd();
		kmod.doc() = kpd.description;
		kpd.py_namespace = PyModule_GetName(kmod.ptr());
	}
}

auto python_subsyst_impl::py_init_plugin(
	const blue_sky::detail::lib_descriptor& lib, plugin_descriptor& p_descr
) -> result_or_err<std::string> {
	return pykmod(this).and_then([&](auto kmod_ptr) -> result_or_err<std::string> {
		bs_init_py_fn init_py_fn;
		lib.load_sym("bs_init_py_subsystem", init_py_fn);
		if(!init_py_fn) return tl::make_unexpected(error{p_descr.name, kernel::Error::PythonDisabled});

		if(p_descr.py_namespace.empty())
			p_descr.py_namespace = extract_root_name(lib.fname_);

		// create submodule
		auto plugin_mod = kmod_ptr->def_submodule(p_descr.py_namespace.c_str(), p_descr.description.c_str());
		// invoke init function
		init_py_fn(&plugin_mod);

		return plugins_subsyst::kernel_pd().py_namespace + '.' + p_descr.py_namespace;
	});
}

auto python_subsyst_impl::py_add_error_closure() -> void {
WITH_KMOD
	auto err_class = (pybind11::class_<std::error_code>)kmod.attr("error_code");
	pybind11::init([](int ec) {
		return std::error_code(static_cast<Error>(ec));
	}).execute(err_class);
END_WITH
}

auto python_subsyst_impl::register_adapter(std::string obj_type_id, adapter_fn f) -> void {
	if(f)
		adapters_.insert_or_assign(std::move(obj_type_id), std::move(f));
	else {
		auto pa = adapters_.find(obj_type_id);
		if(pa != adapters_.end())
			adapters_.erase(pa);
	}
}

auto python_subsyst_impl::register_default_adapter(adapter_fn f) -> void {
	def_adapter_ = std::move(f);
}

auto python_subsyst_impl::clear_adapters() -> void {
	adapters_.clear();
	def_adapter_ = nullptr;
}

auto python_subsyst_impl::adapted_types() const -> std::vector<std::string> {
	std::vector<std::string> res(adapters_.size());
	std::transform(
		adapters_.begin(), adapters_.end(), res.begin(),
		[](const auto& A){ return A.first; }
	);
	if(def_adapter_) res.push_back("*");
	return res;
}

auto python_subsyst_impl::adapt(sp_obj source) -> py::object {
	if(!source) return py::none();
	// check if adpater already created for given object
	auto cached_A = acache_.find(sp_obj_hash(source));
	if(cached_A != acache_.end())
		return cached_A->second;
	// adapt or passthrough
	auto pf = adapters_.find(source->type_id());
	auto&& obj = std::move(source);
	auto A = pf != adapters_.end() ?
		pf->second(obj) :
		( def_adapter_ ? def_adapter_(obj) : py::cast(obj) );
	// cache adapter instance
	acache_[sp_obj_hash(source)] = A;
	return A;
}

auto python_subsyst_impl::drop_adapted_cache(const sp_obj& obj) -> std::size_t {
	std::size_t res = 0;
	if(!obj) {
		res = acache_.size();
		acache_.clear();
	}
	else {
		auto cached_A = acache_.find(sp_obj_hash(obj));
		if(cached_A != acache_.end()) {
			acache_.erase(cached_A);
			res = 1;
		}
	}
	return res;
}

auto python_subsyst_impl::self() -> python_subsyst_impl& {
	// [NOTE] unconditional cast, because if self() is called, then instance MUST be self for sure
	return static_cast<python_subsyst_impl&>(singleton<python_subsyst>::Instance());
}

NAMESPACE_END(blue_sky::kernel::detail)
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// optimizer.cpp
//
// Identification: src/optimizer/optimizer.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <memory>

#include "optimizer/optimizer.h"

#include "catalog/column_catalog.h"
#include "catalog/manager.h"
#include "catalog/table_catalog.h"

#include "optimizer/binding.h"
#include "optimizer/cost_and_stats_calculator.h"
#include "optimizer/operator_visitor.h"
#include "optimizer/properties.h"
#include "optimizer/property_enforcer.h"
#include "optimizer/query_to_operator_transformer.h"
#include "optimizer/input_column_deriver.h"
#include "optimizer/plan_generator.h"
#include "optimizer/rule.h"
#include "optimizer/rule_impls.h"
#include "optimizer/optimizer_task_pool.h"
#include "optimizer/optimize_context.h"
#include "parser/create_statement.h"

#include "planner/analyze_plan.h"
#include "planner/create_plan.h"
#include "planner/drop_plan.h"
#include "planner/order_by_plan.h"
#include "planner/populate_index_plan.h"
#include "planner/projection_plan.h"
#include "planner/seq_scan_plan.h"

#include "storage/data_table.h"

#include "binder/bind_node_visitor.h"

using std::vector;
using std::unordered_map;
using std::shared_ptr;
using std::unique_ptr;
using std::move;
using std::pair;
using std::make_shared;

namespace peloton {
namespace optimizer {

//===--------------------------------------------------------------------===//
// Optimizer
//===--------------------------------------------------------------------===//
Optimizer::Optimizer() {}

void Optimizer::OptimizeLoop(int root_group_id,
                             std::shared_ptr<PropertySet> required_props) {
  std::shared_ptr<OptimizeContext> root_context =
      std::make_shared<OptimizeContext>(&metadata_, required_props);
  auto task_stack = std::unique_ptr<OptimizerTaskStack>(new OptimizerTaskStack());
  metadata_.SetTaskPool(task_stack.get());

  // Head group expression with the root group as its only child.
  // This object is only used for simplified the logics for the rewrite phase
  // std::vector<GroupID> head_child_groups = {root_group_id};
  // std::shared_ptr<GroupExpression> head_gexpr =
  //     std::make_shared<GroupExpression>(Operator(), head_child_groups);

  // Perform optimization after the rewrite
  task_stack->Push(new OptimizeGroup(metadata_.memo.GetGroupByID(root_group_id),
                                     root_context));
  // Perform rewrite first
  // task_stack->Push(new RewriteExpression(head_gexpr.get(), 0, root_context));
  task_stack->Push(new TopDownRewrite(root_group_id, root_context,
                                      RewriteRuleSetName::PREDICATE_PUSH_DOWN));

  // TODO: Add timer for early stop
  while (!task_stack->Empty()) {
    auto task = task_stack->Pop();
    task->execute();
  }
}

shared_ptr<planner::AbstractPlan> Optimizer::BuildPelotonPlanTree(
    const unique_ptr<parser::SQLStatementList> &parse_tree_list,
    const std::string default_database_name, concurrency::TransactionContext *txn) {
  // Base Case
  if (parse_tree_list->GetStatements().size() == 0) return nullptr;

  unique_ptr<planner::AbstractPlan> child_plan = nullptr;

  auto parse_tree = parse_tree_list->GetStatements().at(0).get();

  // Run binder
  auto bind_node_visitor =
      make_shared<binder::BindNodeVisitor>(txn, default_database_name);
  bind_node_visitor->BindNameToNode(parse_tree);

  // Handle ddl statement
  bool is_ddl_stmt;
  auto ddl_plan = HandleDDLStatement(parse_tree, is_ddl_stmt, txn);
  if (is_ddl_stmt) {
    return move(ddl_plan);
  }

  // Generate initial operator tree from query tree
  shared_ptr<GroupExpression> gexpr = InsertQueryTree(parse_tree, txn);
  GroupID root_id = gexpr->GetGroupID();
  // Get the physical properties the final plan must output
  auto query_info = GetQueryInfo(parse_tree);

  OptimizeLoop(root_id, query_info.physical_props);

  try {
    auto best_plan = ChooseBestPlan(root_id, query_info.physical_props,
                                    query_info.output_exprs);
    if (best_plan == nullptr) return nullptr;
    // Reset memo after finishing the optimization
    Reset();
    //  return shared_ptr<planner::AbstractPlan>(best_plan.release());
    return move(best_plan);
  } catch (Exception &e) {
    Reset();
    throw e;
  }
}

void Optimizer::Reset() { metadata_ = OptimizerMetadata(); }

unique_ptr<planner::AbstractPlan> Optimizer::HandleDDLStatement(
    parser::SQLStatement *tree, bool &is_ddl_stmt,
    concurrency::TransactionContext *txn) {
  unique_ptr<planner::AbstractPlan> ddl_plan = nullptr;
  is_ddl_stmt = true;
  auto stmt_type = tree->GetType();
  switch (stmt_type) {
    case StatementType::DROP: {
      LOG_TRACE("Adding Drop plan...");
      unique_ptr<planner::AbstractPlan> drop_plan(
          new planner::DropPlan((parser::DropStatement *)tree));
      ddl_plan = move(drop_plan);
      break;
    }

    case StatementType::CREATE: {
      LOG_TRACE("Adding Create plan...");

      // This is adapted from the simple optimizer
      auto create_plan =
          new planner::CreatePlan((parser::CreateStatement *)tree);
      std::unique_ptr<planner::AbstractPlan> child_CreatePlan(create_plan);
      ddl_plan = move(child_CreatePlan);

      if (create_plan->GetCreateType() == peloton::CreateType::INDEX) {
        auto create_stmt = (parser::CreateStatement *)tree;
        auto target_table = catalog::Catalog::GetInstance()->GetTableWithName(
            create_stmt->GetDatabaseName(), create_stmt->GetTableName(), txn);
        std::vector<oid_t> column_ids;
        // use catalog object instead of schema to acquire metadata
        auto table_object = catalog::Catalog::GetInstance()->GetTableObject(
            create_stmt->GetDatabaseName(), create_stmt->GetTableName(), txn);
        for (auto column_name : create_plan->GetIndexAttributes()) {
          auto column_object = table_object->GetColumnObject(column_name);
          // Check if column is missing
          if (column_object == nullptr)
            throw CatalogException(
                "Some columns are missing when create index " +
                std::string(create_stmt->index_name));
          oid_t col_pos = column_object->GetColumnId();
          column_ids.push_back(col_pos);
        }
        // Create a plan to retrieve data
        std::unique_ptr<planner::SeqScanPlan> child_SeqScanPlan(
            new planner::SeqScanPlan(target_table, nullptr, column_ids, false));

        child_SeqScanPlan->AddChild(std::move(ddl_plan));
        ddl_plan = std::move(child_SeqScanPlan);
        // Create a plan to add data to index
        std::unique_ptr<planner::AbstractPlan> child_PopulateIndexPlan(
            new planner::PopulateIndexPlan(target_table, column_ids));
        child_PopulateIndexPlan->AddChild(std::move(ddl_plan));
        create_plan->SetKeyAttrs(column_ids);
        ddl_plan = std::move(child_PopulateIndexPlan);
      }
      break;
    }
    case StatementType::TRANSACTION: {
      break;
    }
    case StatementType::ANALYZE: {
      LOG_TRACE("Adding Analyze plan...");
      unique_ptr<planner::AbstractPlan> analyze_plan(new planner::AnalyzePlan(
          static_cast<parser::AnalyzeStatement *>(tree), txn));
      ddl_plan = move(analyze_plan);
      break;
    }
    case StatementType::COPY: {
      LOG_TRACE("Adding Copy plan...");
      parser::CopyStatement *copy_parse_tree =
          static_cast<parser::CopyStatement *>(tree);
      ddl_plan = util::CreateCopyPlan(copy_parse_tree);
      break;
    }
    default:
      is_ddl_stmt = false;
  }
  return ddl_plan;
}

shared_ptr<GroupExpression> Optimizer::InsertQueryTree(
    parser::SQLStatement *tree, concurrency::TransactionContext *txn) {
  QueryToOperatorTransformer converter(txn);
  shared_ptr<OperatorExpression> initial =
      converter.ConvertToOpExpression(tree);
  shared_ptr<GroupExpression> gexpr;
  metadata_.RecordTransformedExpression(initial, gexpr);
  return gexpr;
}

QueryInfo Optimizer::GetQueryInfo(parser::SQLStatement *tree) {
  auto GetQueryInfoHelper =
      [](std::vector<unique_ptr<expression::AbstractExpression>> &select_list,
         std::unique_ptr<parser::OrderDescription> &order_info,
         std::vector<expression::AbstractExpression *> &output_exprs,
         std::shared_ptr<PropertySet> &physical_props) {
        // Extract output column
        for (auto &expr : select_list) output_exprs.push_back(expr.get());

        // Extract sort property
        if (order_info != nullptr) {
          std::vector<expression::AbstractExpression *> sort_exprs;
          std::vector<bool> sort_ascending;
          for (auto &expr : order_info->exprs) {
            sort_exprs.push_back(expr.get());
          }
          for (auto &type : order_info->types) {
            sort_ascending.push_back(type == parser::kOrderAsc);
          }
          if (!sort_exprs.empty())
            physical_props->AddProperty(
                std::make_shared<PropertySort>(sort_exprs, sort_ascending));
        }
      };

  std::vector<expression::AbstractExpression *> output_exprs;
  std::shared_ptr<PropertySet> physical_props = std::make_shared<PropertySet>();
  switch (tree->GetType()) {
    case StatementType::SELECT: {
      auto select = reinterpret_cast<parser::SelectStatement *>(tree);
      GetQueryInfoHelper(select->select_list, select->order, output_exprs,
                         physical_props);
      break;
    }
    case StatementType::INSERT: {
      auto insert = reinterpret_cast<parser::InsertStatement *>(tree);
      if (insert->select != nullptr)
        GetQueryInfoHelper(insert->select->select_list, insert->select->order,
                           output_exprs, physical_props);
      break;
    }
    default:
      ;
  }

  return QueryInfo(output_exprs, physical_props);
}

unique_ptr<planner::AbstractPlan> Optimizer::ChooseBestPlan(
    GroupID id, std::shared_ptr<PropertySet> required_props,
    std::vector<expression::AbstractExpression *> required_cols) {
  Group *group = metadata_.memo.GetGroupByID(id);
  LOG_TRACE("Choosing with property : %s", required_props->ToString().c_str());
  auto gexpr = group->GetBestExpression(required_props);

  LOG_TRACE("Choosing best plan for group %d with op %s", gexpr->GetGroupID(),
            gexpr->Op().name().c_str());

  vector<GroupID> child_groups = gexpr->GetChildGroupIDs();
  auto required_input_props = gexpr->GetInputProperties(required_props);
  PL_ASSERT(required_input_props.size() == child_groups.size());
  // Firstly derive input/output columns
  InputColumnDeriver deriver;
  auto output_input_cols_pair = deriver.DeriveInputColumns(
      gexpr, required_props, required_cols, &metadata_.memo);
  auto &output_cols = output_input_cols_pair.first;
  auto &input_cols = output_input_cols_pair.second;
  PL_ASSERT(input_cols.size() == required_input_props.size());

  // Derive chidren plans first because they are useful in the derivation of
  // root plan. Also keep propagate expression to column offset mapping
  vector<unique_ptr<planner::AbstractPlan>> children_plans;
  vector<ExprMap> children_expr_map;
  for (size_t i = 0; i < child_groups.size(); ++i) {
    ExprMap child_expr_map;
    for (unsigned offset = 0; offset < input_cols[i].size(); ++offset) {
      PL_ASSERT(input_cols[i][offset] != nullptr);
      child_expr_map[input_cols[i][offset]] = offset;
    }
    auto child_plan =
        ChooseBestPlan(child_groups[i], required_input_props[i], input_cols[i]);
    children_expr_map.push_back(move(child_expr_map));
    PL_ASSERT(child_plan != nullptr);
    children_plans.push_back(move(child_plan));
  }

  // Derive root plan
  shared_ptr<OperatorExpression> op =
      make_shared<OperatorExpression>(gexpr->Op());

  PlanGenerator generator;
  auto plan = generator.ConvertOpExpression(op, required_props, required_cols,
                                            output_cols, children_plans,
                                            children_expr_map);

  LOG_TRACE("Finish Choosing best plan for group %d", id);
  return plan;
}
}  // namespace optimizer
}  // namespace peloton
<commit_msg>Remove unused code<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// optimizer.cpp
//
// Identification: src/optimizer/optimizer.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <memory>

#include "optimizer/optimizer.h"

#include "catalog/column_catalog.h"
#include "catalog/manager.h"
#include "catalog/table_catalog.h"

#include "optimizer/binding.h"
#include "optimizer/cost_and_stats_calculator.h"
#include "optimizer/operator_visitor.h"
#include "optimizer/properties.h"
#include "optimizer/property_enforcer.h"
#include "optimizer/query_to_operator_transformer.h"
#include "optimizer/input_column_deriver.h"
#include "optimizer/plan_generator.h"
#include "optimizer/rule.h"
#include "optimizer/rule_impls.h"
#include "optimizer/optimizer_task_pool.h"
#include "optimizer/optimize_context.h"
#include "parser/create_statement.h"

#include "planner/analyze_plan.h"
#include "planner/create_plan.h"
#include "planner/drop_plan.h"
#include "planner/order_by_plan.h"
#include "planner/populate_index_plan.h"
#include "planner/projection_plan.h"
#include "planner/seq_scan_plan.h"

#include "storage/data_table.h"

#include "binder/bind_node_visitor.h"

using std::vector;
using std::unordered_map;
using std::shared_ptr;
using std::unique_ptr;
using std::move;
using std::pair;
using std::make_shared;

namespace peloton {
namespace optimizer {

//===--------------------------------------------------------------------===//
// Optimizer
//===--------------------------------------------------------------------===//
Optimizer::Optimizer() {}

void Optimizer::OptimizeLoop(int root_group_id,
                             std::shared_ptr<PropertySet> required_props) {
  std::shared_ptr<OptimizeContext> root_context =
      std::make_shared<OptimizeContext>(&metadata_, required_props);
  auto task_stack = std::unique_ptr<OptimizerTaskStack>(new OptimizerTaskStack());
  metadata_.SetTaskPool(task_stack.get());

  // Head group expression with the root group as its only child.
  // This object is only used for simplified the logics for the rewrite phase

  // Perform optimization after the rewrite
  task_stack->Push(new OptimizeGroup(metadata_.memo.GetGroupByID(root_group_id),
                                     root_context));
  // Perform rewrite first
  // task_stack->Push(new RewriteExpression(head_gexpr.get(), 0, root_context));
  task_stack->Push(new TopDownRewrite(root_group_id, root_context,
                                      RewriteRuleSetName::PREDICATE_PUSH_DOWN));

  // TODO: Add timer for early stop
  while (!task_stack->Empty()) {
    auto task = task_stack->Pop();
    task->execute();
  }
}

shared_ptr<planner::AbstractPlan> Optimizer::BuildPelotonPlanTree(
    const unique_ptr<parser::SQLStatementList> &parse_tree_list,
    const std::string default_database_name, concurrency::TransactionContext *txn) {
  // Base Case
  if (parse_tree_list->GetStatements().size() == 0) return nullptr;

  unique_ptr<planner::AbstractPlan> child_plan = nullptr;

  auto parse_tree = parse_tree_list->GetStatements().at(0).get();

  // Run binder
  auto bind_node_visitor =
      make_shared<binder::BindNodeVisitor>(txn, default_database_name);
  bind_node_visitor->BindNameToNode(parse_tree);

  // Handle ddl statement
  bool is_ddl_stmt;
  auto ddl_plan = HandleDDLStatement(parse_tree, is_ddl_stmt, txn);
  if (is_ddl_stmt) {
    return move(ddl_plan);
  }

  // Generate initial operator tree from query tree
  shared_ptr<GroupExpression> gexpr = InsertQueryTree(parse_tree, txn);
  GroupID root_id = gexpr->GetGroupID();
  // Get the physical properties the final plan must output
  auto query_info = GetQueryInfo(parse_tree);

  OptimizeLoop(root_id, query_info.physical_props);

  try {
    auto best_plan = ChooseBestPlan(root_id, query_info.physical_props,
                                    query_info.output_exprs);
    if (best_plan == nullptr) return nullptr;
    // Reset memo after finishing the optimization
    Reset();
    //  return shared_ptr<planner::AbstractPlan>(best_plan.release());
    return move(best_plan);
  } catch (Exception &e) {
    Reset();
    throw e;
  }
}

void Optimizer::Reset() { metadata_ = OptimizerMetadata(); }

unique_ptr<planner::AbstractPlan> Optimizer::HandleDDLStatement(
    parser::SQLStatement *tree, bool &is_ddl_stmt,
    concurrency::TransactionContext *txn) {
  unique_ptr<planner::AbstractPlan> ddl_plan = nullptr;
  is_ddl_stmt = true;
  auto stmt_type = tree->GetType();
  switch (stmt_type) {
    case StatementType::DROP: {
      LOG_TRACE("Adding Drop plan...");
      unique_ptr<planner::AbstractPlan> drop_plan(
          new planner::DropPlan((parser::DropStatement *)tree));
      ddl_plan = move(drop_plan);
      break;
    }

    case StatementType::CREATE: {
      LOG_TRACE("Adding Create plan...");

      // This is adapted from the simple optimizer
      auto create_plan =
          new planner::CreatePlan((parser::CreateStatement *)tree);
      std::unique_ptr<planner::AbstractPlan> child_CreatePlan(create_plan);
      ddl_plan = move(child_CreatePlan);

      if (create_plan->GetCreateType() == peloton::CreateType::INDEX) {
        auto create_stmt = (parser::CreateStatement *)tree;
        auto target_table = catalog::Catalog::GetInstance()->GetTableWithName(
            create_stmt->GetDatabaseName(), create_stmt->GetTableName(), txn);
        std::vector<oid_t> column_ids;
        // use catalog object instead of schema to acquire metadata
        auto table_object = catalog::Catalog::GetInstance()->GetTableObject(
            create_stmt->GetDatabaseName(), create_stmt->GetTableName(), txn);
        for (auto column_name : create_plan->GetIndexAttributes()) {
          auto column_object = table_object->GetColumnObject(column_name);
          // Check if column is missing
          if (column_object == nullptr)
            throw CatalogException(
                "Some columns are missing when create index " +
                std::string(create_stmt->index_name));
          oid_t col_pos = column_object->GetColumnId();
          column_ids.push_back(col_pos);
        }
        // Create a plan to retrieve data
        std::unique_ptr<planner::SeqScanPlan> child_SeqScanPlan(
            new planner::SeqScanPlan(target_table, nullptr, column_ids, false));

        child_SeqScanPlan->AddChild(std::move(ddl_plan));
        ddl_plan = std::move(child_SeqScanPlan);
        // Create a plan to add data to index
        std::unique_ptr<planner::AbstractPlan> child_PopulateIndexPlan(
            new planner::PopulateIndexPlan(target_table, column_ids));
        child_PopulateIndexPlan->AddChild(std::move(ddl_plan));
        create_plan->SetKeyAttrs(column_ids);
        ddl_plan = std::move(child_PopulateIndexPlan);
      }
      break;
    }
    case StatementType::TRANSACTION: {
      break;
    }
    case StatementType::ANALYZE: {
      LOG_TRACE("Adding Analyze plan...");
      unique_ptr<planner::AbstractPlan> analyze_plan(new planner::AnalyzePlan(
          static_cast<parser::AnalyzeStatement *>(tree), txn));
      ddl_plan = move(analyze_plan);
      break;
    }
    case StatementType::COPY: {
      LOG_TRACE("Adding Copy plan...");
      parser::CopyStatement *copy_parse_tree =
          static_cast<parser::CopyStatement *>(tree);
      ddl_plan = util::CreateCopyPlan(copy_parse_tree);
      break;
    }
    default:
      is_ddl_stmt = false;
  }
  return ddl_plan;
}

shared_ptr<GroupExpression> Optimizer::InsertQueryTree(
    parser::SQLStatement *tree, concurrency::TransactionContext *txn) {
  QueryToOperatorTransformer converter(txn);
  shared_ptr<OperatorExpression> initial =
      converter.ConvertToOpExpression(tree);
  shared_ptr<GroupExpression> gexpr;
  metadata_.RecordTransformedExpression(initial, gexpr);
  return gexpr;
}

QueryInfo Optimizer::GetQueryInfo(parser::SQLStatement *tree) {
  auto GetQueryInfoHelper =
      [](std::vector<unique_ptr<expression::AbstractExpression>> &select_list,
         std::unique_ptr<parser::OrderDescription> &order_info,
         std::vector<expression::AbstractExpression *> &output_exprs,
         std::shared_ptr<PropertySet> &physical_props) {
        // Extract output column
        for (auto &expr : select_list) output_exprs.push_back(expr.get());

        // Extract sort property
        if (order_info != nullptr) {
          std::vector<expression::AbstractExpression *> sort_exprs;
          std::vector<bool> sort_ascending;
          for (auto &expr : order_info->exprs) {
            sort_exprs.push_back(expr.get());
          }
          for (auto &type : order_info->types) {
            sort_ascending.push_back(type == parser::kOrderAsc);
          }
          if (!sort_exprs.empty())
            physical_props->AddProperty(
                std::make_shared<PropertySort>(sort_exprs, sort_ascending));
        }
      };

  std::vector<expression::AbstractExpression *> output_exprs;
  std::shared_ptr<PropertySet> physical_props = std::make_shared<PropertySet>();
  switch (tree->GetType()) {
    case StatementType::SELECT: {
      auto select = reinterpret_cast<parser::SelectStatement *>(tree);
      GetQueryInfoHelper(select->select_list, select->order, output_exprs,
                         physical_props);
      break;
    }
    case StatementType::INSERT: {
      auto insert = reinterpret_cast<parser::InsertStatement *>(tree);
      if (insert->select != nullptr)
        GetQueryInfoHelper(insert->select->select_list, insert->select->order,
                           output_exprs, physical_props);
      break;
    }
    default:
      ;
  }

  return QueryInfo(output_exprs, physical_props);
}

unique_ptr<planner::AbstractPlan> Optimizer::ChooseBestPlan(
    GroupID id, std::shared_ptr<PropertySet> required_props,
    std::vector<expression::AbstractExpression *> required_cols) {
  Group *group = metadata_.memo.GetGroupByID(id);
  LOG_TRACE("Choosing with property : %s", required_props->ToString().c_str());
  auto gexpr = group->GetBestExpression(required_props);

  LOG_TRACE("Choosing best plan for group %d with op %s", gexpr->GetGroupID(),
            gexpr->Op().name().c_str());

  vector<GroupID> child_groups = gexpr->GetChildGroupIDs();
  auto required_input_props = gexpr->GetInputProperties(required_props);
  PL_ASSERT(required_input_props.size() == child_groups.size());
  // Firstly derive input/output columns
  InputColumnDeriver deriver;
  auto output_input_cols_pair = deriver.DeriveInputColumns(
      gexpr, required_props, required_cols, &metadata_.memo);
  auto &output_cols = output_input_cols_pair.first;
  auto &input_cols = output_input_cols_pair.second;
  PL_ASSERT(input_cols.size() == required_input_props.size());

  // Derive chidren plans first because they are useful in the derivation of
  // root plan. Also keep propagate expression to column offset mapping
  vector<unique_ptr<planner::AbstractPlan>> children_plans;
  vector<ExprMap> children_expr_map;
  for (size_t i = 0; i < child_groups.size(); ++i) {
    ExprMap child_expr_map;
    for (unsigned offset = 0; offset < input_cols[i].size(); ++offset) {
      PL_ASSERT(input_cols[i][offset] != nullptr);
      child_expr_map[input_cols[i][offset]] = offset;
    }
    auto child_plan =
        ChooseBestPlan(child_groups[i], required_input_props[i], input_cols[i]);
    children_expr_map.push_back(move(child_expr_map));
    PL_ASSERT(child_plan != nullptr);
    children_plans.push_back(move(child_plan));
  }

  // Derive root plan
  shared_ptr<OperatorExpression> op =
      make_shared<OperatorExpression>(gexpr->Op());

  PlanGenerator generator;
  auto plan = generator.ConvertOpExpression(op, required_props, required_cols,
                                            output_cols, children_plans,
                                            children_expr_map);

  LOG_TRACE("Finish Choosing best plan for group %d", id);
  return plan;
}
}  // namespace optimizer
}  // namespace peloton
<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2012, Stuart W Baker
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 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 HOLDER 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.
 *
 * \file HwInit.cxx
 * This file represents the hardware initialization for the TI Tiva MCU.
 *
 * @author Stuart W. Baker
 * @date 5 January 2013
 */

#include <new>
#include <cstdint>

#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "os/OS.hxx"
#include "TivaDev.hxx"
#include "TivaDCC.hxx"
#include "TivaEEPROMEmulation.hxx"

struct Debug {
  // High between start_cutout and end_cutout from the TivaRailcom driver.
  typedef DummyPin RailcomDriverCutout;
  // Flips every time an uart byte is received error.
  typedef DummyPin RailcomError;
  // Flips every time an 'E0' byte is received in the railcom driver.
  typedef DummyPin RailcomE0;
  // Sets to 1 if we have seen any data from the railcom uart.
  typedef DummyPin RailcomAnyData;
  // Flips for every byte from the railcom uart.
  typedef DummyPin RailcomDataReceived;
  // Flipped for every packet that is sent from the railcom layer to the
  // application.
  typedef DummyPin RailcomPackets;
};
#include "TivaRailcom.hxx"

/** override stdin */
const char *STDIN_DEVICE = "/dev/ser0";

/** override stdout */
const char *STDOUT_DEVICE = "/dev/ser0";

/** override stderr */
const char *STDERR_DEVICE = "/dev/ser0";

/** USB Device CDC serial driver instance */
static TivaCdc cdc0("/dev/serUSB0", INT_RESOLVE(INT_USB0_, 0));

/** UART 0 serial driver instance */
static TivaUart uart0("/dev/ser0", UART0_BASE, INT_RESOLVE(INT_UART0_, 0));

/** CAN 0 CAN driver instance */
static TivaCan can0("/dev/can0", CAN0_BASE, INT_RESOLVE(INT_CAN0_, 0));

extern const uint16_t __eeprom_start[];
const uint16_t* const TivaEEPROMEmulation::raw = __eeprom_start;
extern const uint16_t __eeprom_end[];
const size_t TivaEEPROMEmulation::FLASH_SIZE = __eeprom_end - __eeprom_start;

static TivaEEPROMEmulation eeprom("/dev/eeprom", 256);

#define ONE_BIT_HALF_PERIOD  4480
#define ZERO_BIT_HALF_PERIOD 8000
#define STARTUP_DELAY_CYCLES 2
#define DEADBAND_ADJUST      80

#define DECL_PIN(NAME, PORT, NUM)                \
  static const auto NAME##_PERIPH = SYSCTL_PERIPH_GPIO##PORT; \
  static const auto NAME##_BASE = GPIO_PORT##PORT##_BASE; \
  static const auto NAME##_PIN = GPIO_PIN_##NUM

struct RailcomDefs
{
    static const uint32_t CHANNEL_COUNT = 1;
    static const uint32_t UART_PERIPH[CHANNEL_COUNT];
    static const uint32_t UART_BASE[CHANNEL_COUNT];
    // Make sure there are enough entries here for all the channels times a few
    // DCC packets.
    static const uint32_t Q_SIZE = 6;

    static const auto OS_INTERRUPT = INT_UART1;

    GPIO_HWPIN(CH1, GpioHwPin, B, 0, U1RX);

    static void hw_init() {
         CH1_Pin::hw_init();
    }

    static void set_input() {
        CH1_Pin::set_input();
    }

    static void set_hw() {
        CH1_Pin::set_hw();
    }

    /** @returns a bitmask telling which pins are active. Bit 0 will be set if
     * channel 0 is active (drawing current).*/
    static uint8_t sample() {
        uint8_t ret = 0;
        if (!CH1_Pin::get()) ret |= 1;
        return ret;
    }
};

const uint32_t RailcomDefs::UART_BASE[] = {UART1_BASE};
const uint32_t RailcomDefs::UART_PERIPH[] = {SYSCTL_PERIPH_UART1};

static TivaRailcomDriver<RailcomDefs> railcom_driver("/dev/railcom");

struct DccHwDefs {
  /// base address of a capture compare pwm timer pair
  static const unsigned long CCP_BASE = TIMER0_BASE;
  /// an otherwise unused interrupt number (could be that of the capture compare pwm timer)
  static const unsigned long OS_INTERRUPT = INT_TIMER0A;
  /// base address of an interval timer
  static const unsigned long INTERVAL_BASE = TIMER1_BASE;
  /// interrupt number of the interval timer
  static const unsigned long INTERVAL_INTERRUPT = INT_TIMER1A;

  /** These timer blocks will be synchronized once per packet, when the
   *  deadband delay is set up. */
  static const auto TIMER_SYNC = TIMER_0A_SYNC | TIMER_0B_SYNC | TIMER_1A_SYNC | TIMER_1B_SYNC;

  // Peripherals to enable at boot.
  static const auto CCP_PERIPH = SYSCTL_PERIPH_TIMER1;
  static const auto INTERVAL_PERIPH = SYSCTL_PERIPH_TIMER0;
  static const auto PIN_H_GPIO_PERIPH = SYSCTL_PERIPH_GPIOB;
  static const auto PIN_L_GPIO_PERIPH = SYSCTL_PERIPH_GPIOB;

  static const auto PIN_H_GPIO_CONFIG = GPIO_PB6_T0CCP0;
  static const auto PIN_L_GPIO_CONFIG = GPIO_PB7_T0CCP1;

  static const auto PIN_H_GPIO_BASE = GPIO_PORTB_BASE;
  static const auto PIN_L_GPIO_BASE = GPIO_PORTB_BASE;

  static const auto PIN_H_GPIO_PIN = GPIO_PIN_6;
  static const auto PIN_L_GPIO_PIN = GPIO_PIN_7;

  /** Defines whether the high driver pin is inverted or not. A non-inverted
   *  (value==false) pin will be driven high during the first half of the DCC
   *  bit (minus H_DEADBAND_DELAY_NSEC at the end), and low during the second
   *  half.  A non-inverted pin will be driven low as safe setting at
   *  startup. */
  static const bool PIN_H_INVERT = false;

  /** Defines whether the drive-low pin is inverted or not. A non-inverted pin
   *  (value==false) will be driven high during the second half of the DCC bit
   *  (minus L_DEADBAND_DELAY_NSEC), and low during the first half.  A
   *  non-inverted pin will be driven low as safe setting at startup. */
  static const bool PIN_L_INVERT = false;

  /** @returns the number of preamble bits to send exclusive of end of packet
   *  '1' bit */
  static int dcc_preamble_count() { return 16; }

  static void flip_led() {}

  /** the time (in nanoseconds) to wait between turning off the low driver and
   * turning on the high driver. */
  static const int H_DEADBAND_DELAY_NSEC = 250;
  /** the time (in nanoseconds) to wait between turning off the high driver and
   * turning on the low driver. */
  static const int L_DEADBAND_DELAY_NSEC = 250;

  /** @returns true to produce the RailCom cutout, else false */
  static bool railcom_cutout() { return false; }

  /** number of outgoing messages we can queue */
  static const size_t Q_SIZE = 4;

  // Pins defined for railcom
  //DECL_PIN(RAILCOM_TRIGGER, B, 4);
  DECL_PIN(RAILCOM_TRIGGER, D, 6);
  static const auto RAILCOM_TRIGGER_INVERT = true;

  static const auto RAILCOM_UART_BASE = UART1_BASE;
  static const auto RAILCOM_UART_PERIPH = SYSCTL_PERIPH_UART1;
  DECL_PIN(RAILCOM_UARTPIN, B, 0);
  static const auto RAILCOM_UARTPIN_CONFIG = GPIO_PB0_U1RX;
};

static TivaDCC<DccHwDefs> tivaDCC("/dev/mainline", &railcom_driver);

extern "C" {
/** Blink LED */
uint32_t blinker_pattern = 0;
static uint32_t rest_pattern = 0;

void dcc_generator_init(void);

void hw_set_to_safe(void)
{
    tivaDCC.disable_output();
}

void resetblink(uint32_t pattern)
{
    blinker_pattern = pattern;
    /* make a timer event trigger immediately */
}

void setblink(uint32_t pattern)
{
    resetblink(pattern);
}

void timer5a_interrupt_handler(void)
{
    //
    // Clear the timer interrupt.
    //
    MAP_TimerIntClear(TIMER5_BASE, TIMER_TIMA_TIMEOUT);
    // Set output LED.
    MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1,
                     (rest_pattern & 1) ? GPIO_PIN_1 : 0);
    // Shift and maybe reset pattern.
    rest_pattern >>= 1;
    if (!rest_pattern)
        rest_pattern = blinker_pattern;
}

void uart1_interrupt_handler(void)
{
  railcom_driver.os_interrupt_handler();
}

void diewith(uint32_t pattern)
{
    vPortClearInterruptMask(0x20);
    asm("cpsie i\n");

    resetblink(pattern);
    while (1)
        ;
}

/** Initialize the processor hardware.
 */
void hw_preinit(void)
{
    /* Globally disables interrupts until the FreeRTOS scheduler is up. */
    asm("cpsid i\n");

    /* Setup the system clock. */
    MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);

    /* Red LED pin initialization */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
    MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);

    /* Blinker timer initialization. */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5);
    MAP_TimerConfigure(TIMER5_BASE, TIMER_CFG_PERIODIC);
    MAP_TimerLoadSet(TIMER5_BASE, TIMER_A, MAP_SysCtlClockGet() / 8);
    MAP_IntEnable(INT_TIMER5A);

    /* This interrupt should hit even during kernel operations. */
    MAP_IntPrioritySet(INT_TIMER5A, 0);
    MAP_TimerIntEnable(TIMER5_BASE, TIMER_TIMA_TIMEOUT);
    MAP_TimerEnable(TIMER5_BASE, TIMER_A);

    /* UART0 pin initialization */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
    MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
    MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    /* USB0 pin initialization */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    MAP_GPIOPinTypeUSBAnalog(GPIO_PORTD_BASE, GPIO_PIN_5 | GPIO_PIN_4);

    /* CAN pin initialization */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    MAP_GPIOPinConfigure(GPIO_PE4_CAN0RX);
    MAP_GPIOPinConfigure(GPIO_PE5_CAN0TX);
    MAP_GPIOPinTypeCAN(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5);

    /* Blue LED pin initialization */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);

    /* Green LED pin initialization */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_PIN_3);
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3);

    /* USB interrupt priority */
    MAP_IntPrioritySet(INT_USB0, 0xff); // USB interrupt low priority

    /* Initialize the DCC Timers and GPIO outputs */
    tivaDCC.hw_init();
}

/** Timer interrupt for DCC packet handling.
 */
void timer1a_interrupt_handler(void)
{
    tivaDCC.interrupt_handler();
}

}
<commit_msg>Adds an optional delay into the boot process to catch potential crashes in the debugger before they occur.<commit_after>/** \copyright
 * Copyright (c) 2012, Stuart W Baker
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 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 HOLDER 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.
 *
 * \file HwInit.cxx
 * This file represents the hardware initialization for the TI Tiva MCU.
 *
 * @author Stuart W. Baker
 * @date 5 January 2013
 */

#include <new>
#include <cstdint>

#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "os/OS.hxx"
#include "TivaDev.hxx"
#include "TivaDCC.hxx"
#include "TivaEEPROMEmulation.hxx"

struct Debug {
  // High between start_cutout and end_cutout from the TivaRailcom driver.
  typedef DummyPin RailcomDriverCutout;
  // Flips every time an uart byte is received error.
  typedef DummyPin RailcomError;
  // Flips every time an 'E0' byte is received in the railcom driver.
  typedef DummyPin RailcomE0;
  // Sets to 1 if we have seen any data from the railcom uart.
  typedef DummyPin RailcomAnyData;
  // Flips for every byte from the railcom uart.
  typedef DummyPin RailcomDataReceived;
  // Flipped for every packet that is sent from the railcom layer to the
  // application.
  typedef DummyPin RailcomPackets;
};
#include "TivaRailcom.hxx"
#include "TivaGPIO.hxx"

GPIO_PIN(SW1, GpioInputPU, F, 4);

/** override stdin */
const char *STDIN_DEVICE = "/dev/ser0";

/** override stdout */
const char *STDOUT_DEVICE = "/dev/ser0";

/** override stderr */
const char *STDERR_DEVICE = "/dev/ser0";

/** USB Device CDC serial driver instance */
static TivaCdc cdc0("/dev/serUSB0", INT_RESOLVE(INT_USB0_, 0));

/** UART 0 serial driver instance */
static TivaUart uart0("/dev/ser0", UART0_BASE, INT_RESOLVE(INT_UART0_, 0));

/** CAN 0 CAN driver instance */
static TivaCan can0("/dev/can0", CAN0_BASE, INT_RESOLVE(INT_CAN0_, 0));

extern const uint16_t __eeprom_start[];
const uint16_t* const TivaEEPROMEmulation::raw = __eeprom_start;
extern const uint16_t __eeprom_end[];
const size_t TivaEEPROMEmulation::FLASH_SIZE = __eeprom_end - __eeprom_start;

static TivaEEPROMEmulation eeprom("/dev/eeprom", 256);

#define ONE_BIT_HALF_PERIOD  4480
#define ZERO_BIT_HALF_PERIOD 8000
#define STARTUP_DELAY_CYCLES 2
#define DEADBAND_ADJUST      80

#define DECL_PIN(NAME, PORT, NUM)                \
  static const auto NAME##_PERIPH = SYSCTL_PERIPH_GPIO##PORT; \
  static const auto NAME##_BASE = GPIO_PORT##PORT##_BASE; \
  static const auto NAME##_PIN = GPIO_PIN_##NUM

struct RailcomDefs
{
    static const uint32_t CHANNEL_COUNT = 1;
    static const uint32_t UART_PERIPH[CHANNEL_COUNT];
    static const uint32_t UART_BASE[CHANNEL_COUNT];
    // Make sure there are enough entries here for all the channels times a few
    // DCC packets.
    static const uint32_t Q_SIZE = 6;

    static const auto OS_INTERRUPT = INT_UART1;

    GPIO_HWPIN(CH1, GpioHwPin, B, 0, U1RX);

    static void hw_init() {
         CH1_Pin::hw_init();
    }

    static void set_input() {
        CH1_Pin::set_input();
    }

    static void set_hw() {
        CH1_Pin::set_hw();
    }

    /** @returns a bitmask telling which pins are active. Bit 0 will be set if
     * channel 0 is active (drawing current).*/
    static uint8_t sample() {
        uint8_t ret = 0;
        if (!CH1_Pin::get()) ret |= 1;
        return ret;
    }
};

const uint32_t RailcomDefs::UART_BASE[] = {UART1_BASE};
const uint32_t RailcomDefs::UART_PERIPH[] = {SYSCTL_PERIPH_UART1};

static TivaRailcomDriver<RailcomDefs> railcom_driver("/dev/railcom");

struct DccHwDefs {
  /// base address of a capture compare pwm timer pair
  static const unsigned long CCP_BASE = TIMER0_BASE;
  /// an otherwise unused interrupt number (could be that of the capture compare pwm timer)
  static const unsigned long OS_INTERRUPT = INT_TIMER0A;
  /// base address of an interval timer
  static const unsigned long INTERVAL_BASE = TIMER1_BASE;
  /// interrupt number of the interval timer
  static const unsigned long INTERVAL_INTERRUPT = INT_TIMER1A;

  /** These timer blocks will be synchronized once per packet, when the
   *  deadband delay is set up. */
  static const auto TIMER_SYNC = TIMER_0A_SYNC | TIMER_0B_SYNC | TIMER_1A_SYNC | TIMER_1B_SYNC;

  // Peripherals to enable at boot.
  static const auto CCP_PERIPH = SYSCTL_PERIPH_TIMER1;
  static const auto INTERVAL_PERIPH = SYSCTL_PERIPH_TIMER0;
  static const auto PIN_H_GPIO_PERIPH = SYSCTL_PERIPH_GPIOB;
  static const auto PIN_L_GPIO_PERIPH = SYSCTL_PERIPH_GPIOB;

  static const auto PIN_H_GPIO_CONFIG = GPIO_PB6_T0CCP0;
  static const auto PIN_L_GPIO_CONFIG = GPIO_PB7_T0CCP1;

  static const auto PIN_H_GPIO_BASE = GPIO_PORTB_BASE;
  static const auto PIN_L_GPIO_BASE = GPIO_PORTB_BASE;

  static const auto PIN_H_GPIO_PIN = GPIO_PIN_6;
  static const auto PIN_L_GPIO_PIN = GPIO_PIN_7;

  /** Defines whether the high driver pin is inverted or not. A non-inverted
   *  (value==false) pin will be driven high during the first half of the DCC
   *  bit (minus H_DEADBAND_DELAY_NSEC at the end), and low during the second
   *  half.  A non-inverted pin will be driven low as safe setting at
   *  startup. */
  static const bool PIN_H_INVERT = false;

  /** Defines whether the drive-low pin is inverted or not. A non-inverted pin
   *  (value==false) will be driven high during the second half of the DCC bit
   *  (minus L_DEADBAND_DELAY_NSEC), and low during the first half.  A
   *  non-inverted pin will be driven low as safe setting at startup. */
  static const bool PIN_L_INVERT = false;

  /** @returns the number of preamble bits to send exclusive of end of packet
   *  '1' bit */
  static int dcc_preamble_count() { return 16; }

  static void flip_led() {}

  /** the time (in nanoseconds) to wait between turning off the low driver and
   * turning on the high driver. */
  static const int H_DEADBAND_DELAY_NSEC = 250;
  /** the time (in nanoseconds) to wait between turning off the high driver and
   * turning on the low driver. */
  static const int L_DEADBAND_DELAY_NSEC = 250;

  /** @returns true to produce the RailCom cutout, else false */
  static bool railcom_cutout() { return false; }

  /** number of outgoing messages we can queue */
  static const size_t Q_SIZE = 4;

  // Pins defined for railcom
  //DECL_PIN(RAILCOM_TRIGGER, B, 4);
  DECL_PIN(RAILCOM_TRIGGER, D, 6);
  static const auto RAILCOM_TRIGGER_INVERT = true;

  static const auto RAILCOM_UART_BASE = UART1_BASE;
  static const auto RAILCOM_UART_PERIPH = SYSCTL_PERIPH_UART1;
  DECL_PIN(RAILCOM_UARTPIN, B, 0);
  static const auto RAILCOM_UARTPIN_CONFIG = GPIO_PB0_U1RX;
};

static TivaDCC<DccHwDefs> tivaDCC("/dev/mainline", &railcom_driver);

extern "C" {
/** Blink LED */
uint32_t blinker_pattern = 0;
static volatile uint32_t rest_pattern = 0;

void dcc_generator_init(void);

void hw_set_to_safe(void)
{
    tivaDCC.disable_output();
}

void resetblink(uint32_t pattern)
{
    blinker_pattern = pattern;
    /* make a timer event trigger immediately */
}

void setblink(uint32_t pattern)
{
    resetblink(pattern);
}

void timer5a_interrupt_handler(void)
{
    //
    // Clear the timer interrupt.
    //
    MAP_TimerIntClear(TIMER5_BASE, TIMER_TIMA_TIMEOUT);
    // Set output LED.
    MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1,
                     (rest_pattern & 1) ? GPIO_PIN_1 : 0);
    // Shift and maybe reset pattern.
    rest_pattern >>= 1;
    if (!rest_pattern)
        rest_pattern = blinker_pattern;
}

void uart1_interrupt_handler(void)
{
  railcom_driver.os_interrupt_handler();
}

void diewith(uint32_t pattern)
{
    vPortClearInterruptMask(0x20);
    asm("cpsie i\n");

    resetblink(pattern);
    while (1)
        ;
}

/** Initialize the processor hardware.
 */
void hw_preinit(void)
{
    /* Globally disables interrupts until the FreeRTOS scheduler is up. */
    asm("cpsid i\n");

    /* Setup the system clock. */
    MAP_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);

    /* Red LED pin initialization */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
    MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);

    /* Blinker timer initialization. */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER5);
    MAP_TimerConfigure(TIMER5_BASE, TIMER_CFG_PERIODIC);
    MAP_TimerLoadSet(TIMER5_BASE, TIMER_A, MAP_SysCtlClockGet() / 8);
    MAP_IntEnable(INT_TIMER5A);

    /* This interrupt should hit even during kernel operations. */
    MAP_IntPrioritySet(INT_TIMER5A, 0);
    MAP_TimerIntEnable(TIMER5_BASE, TIMER_TIMA_TIMEOUT);
    MAP_TimerEnable(TIMER5_BASE, TIMER_A);

    /* UART0 pin initialization */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
    MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
    MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    /* USB0 pin initialization */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    MAP_GPIOPinTypeUSBAnalog(GPIO_PORTD_BASE, GPIO_PIN_5 | GPIO_PIN_4);

    /* CAN pin initialization */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    MAP_GPIOPinConfigure(GPIO_PE4_CAN0RX);
    MAP_GPIOPinConfigure(GPIO_PE5_CAN0TX);
    MAP_GPIOPinTypeCAN(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5);

    /* Blue LED pin initialization */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);

    /* Green LED pin initialization */
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    MAP_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_PIN_3);
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3);

    /* USB interrupt priority */
    MAP_IntPrioritySet(INT_USB0, 0xff); // USB interrupt low priority

    /* Initialize the DCC Timers and GPIO outputs */
    tivaDCC.hw_init();

    SW1_Pin::hw_init();
    /* Checks the SW1 pin at boot time in case we want to allow for a debugger
     * to connect. */
    asm volatile ("cpsie i\n");
    do {
      if (!SW1_Pin::get()) {
        blinker_pattern = 0xAAAA;
      } else {
        blinker_pattern = 0;
      }
    } while (blinker_pattern || rest_pattern);
    asm volatile ("cpsid i\n");
}

/** Timer interrupt for DCC packet handling.
 */
void timer1a_interrupt_handler(void)
{
    tivaDCC.interrupt_handler();
}

}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// transaction_context.cpp
//
// Identification: src/concurrency/transaction_context.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "concurrency/transaction_context.h"

#include <sstream>

#include "common/logger.h"
#include "common/macros.h"
#include "common/platform.h"
#include "trigger/trigger.h"

#include <chrono>
#include <iomanip>
#include <thread>

namespace peloton {
namespace concurrency {

/*
 * TransactionContext state transition:
 *                r           r/ro            u/r/ro
 *              +--<--+     +---<--+        +---<--+
 *           r  |     |     |      |        |      |     d
 *  (init)-->-- +-> Read  --+-> Read Own ---+--> Update ---> Delete (final)
 *                    |   ro             u  |
 *                    |                     |
 *                    +----->--------->-----+
 *                              u
 *              r/ro/u
 *            +---<---+
 *         i  |       |     d
 *  (init)-->-+---> Insert ---> Ins_Del (final)
 *
 *    r : read
 *    ro: read_own
 *    u : update
 *    d : delete
 *    i : insert
 */

TransactionContext::TransactionContext(const size_t thread_id,
                                       const IsolationLevelType isolation,
                                       const cid_t &read_id) {
  Init(thread_id, isolation, read_id);
}

TransactionContext::TransactionContext(const size_t thread_id,
                                       const IsolationLevelType isolation,
                                       const cid_t &read_id,
                                       const cid_t &commit_id) {
  Init(thread_id, isolation, read_id, commit_id);
}

void TransactionContext::Init(const size_t thread_id,
                              const IsolationLevelType isolation,
                              const cid_t &read_id, const cid_t &commit_id) {
  read_id_ = read_id;

  // commit id can be set at a transaction's commit phase.
  commit_id_ = commit_id;

  // set txn_id to commit_id.
  txn_id_ = commit_id_;

  epoch_id_ = read_id_ >> 32;

  thread_id_ = thread_id;

  is_written_ = false;

  isolation_level_ = isolation;

  gc_set_ = std::make_shared<GCSet>();
  gc_object_set_ = std::make_shared<GCObjectSet>();

  on_commit_triggers_.reset();
}

RWType TransactionContext::GetRWType(const ItemPointer &location) {
  const auto rw_set_it = rw_set_.find(location);
  if (rw_set_it != rw_set_.end()) {
    return rw_set_it->second;
  }
  return RWType::INVALID;
}

void TransactionContext::RecordRead(const ItemPointer &location) {
  PELOTON_ASSERT(rw_set_.find(location) == rw_set_.end() ||
                 (rw_set_[location] != RWType::DELETE &&
                  rw_set_[location] != RWType::INS_DEL));
  auto rw_set_it = rw_set_.find(location);
  if (rw_set_it != rw_set_.end()) {
    return;
  }
  rw_set_[location] = RWType::READ;
}

void TransactionContext::RecordReadOwn(const ItemPointer &location) {
  PELOTON_ASSERT(rw_set_.find(location) == rw_set_.end() ||
                 (rw_set_[location] != RWType::DELETE &&
                  rw_set_[location] != RWType::INS_DEL));
  rw_set_[location] = RWType::READ_OWN;
}

void TransactionContext::RecordUpdate(const ItemPointer &location) {
  PELOTON_ASSERT(rw_set_.find(location) == rw_set_.end() ||
                 (rw_set_[location] != RWType::DELETE &&
                  rw_set_[location] != RWType::INS_DEL));
  auto rw_set_it = rw_set_.find(location);
  if (rw_set_it != rw_set_.end() && (rw_set_it->second == RWType::READ ||
                                  rw_set_it->second == RWType::READ_OWN)) {
    rw_set_it->second = RWType::UPDATE;
    is_written_ = true;
  }
  PELOTON_ASSERT(is_written_);
}

void TransactionContext::RecordInsert(const ItemPointer &location) {
  PELOTON_ASSERT(rw_set_.find(location) == rw_set_.end());
  rw_set_[location] = RWType::INSERT;
  is_written_ = true;
}

bool TransactionContext::RecordDelete(const ItemPointer &location) {
  PELOTON_ASSERT(rw_set_.find(location) == rw_set_.end() ||
                 (rw_set_[location] != RWType::DELETE &&
                  rw_set_[location] != RWType::INS_DEL));
  auto rw_set_it = rw_set_.find(location);
  if (rw_set_it != rw_set_.end() && rw_set_it->second == RWType::INSERT) {
    PELOTON_ASSERT(is_written_);
    rw_set_it->second = RWType::INS_DEL;
    return true;
  } else {
    rw_set_[location] = RWType::DELETE;
    is_written_ = true;
    return false;
  }
}

const std::string TransactionContext::GetInfo() const {
  std::ostringstream os;

  os << " Txn :: @" << this << " ID : " << std::setw(4) << txn_id_
     << " Read ID : " << std::setw(4) << read_id_
     << " Commit ID : " << std::setw(4) << commit_id_
     << " Result : " << result_;

  return os.str();
}

void TransactionContext::AddOnCommitTrigger(
    trigger::TriggerData &trigger_data) {
  if (on_commit_triggers_ == nullptr) {
    on_commit_triggers_.reset(new trigger::TriggerSet());
  }
  on_commit_triggers_->push_back(trigger_data);
}

void TransactionContext::ExecOnCommitTriggers() {
  if (on_commit_triggers_ != nullptr) {
    on_commit_triggers_->ExecTriggers();
  }
}

}  // namespace concurrency
}  // namespace peloton
<commit_msg>Formatting.<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// transaction_context.cpp
//
// Identification: src/concurrency/transaction_context.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "concurrency/transaction_context.h"

#include <sstream>

#include "common/logger.h"
#include "common/macros.h"
#include "common/platform.h"
#include "trigger/trigger.h"

#include <chrono>
#include <iomanip>
#include <thread>

namespace peloton {
namespace concurrency {

/*
 * TransactionContext state transition:
 *                r           r/ro            u/r/ro
 *              +--<--+     +---<--+        +---<--+
 *           r  |     |     |      |        |      |     d
 *  (init)-->-- +-> Read  --+-> Read Own ---+--> Update ---> Delete (final)
 *                    |   ro             u  |
 *                    |                     |
 *                    +----->--------->-----+
 *                              u
 *              r/ro/u
 *            +---<---+
 *         i  |       |     d
 *  (init)-->-+---> Insert ---> Ins_Del (final)
 *
 *    r : read
 *    ro: read_own
 *    u : update
 *    d : delete
 *    i : insert
 */

TransactionContext::TransactionContext(const size_t thread_id,
                                       const IsolationLevelType isolation,
                                       const cid_t &read_id) {
  Init(thread_id, isolation, read_id);
}

TransactionContext::TransactionContext(const size_t thread_id,
                                       const IsolationLevelType isolation,
                                       const cid_t &read_id,
                                       const cid_t &commit_id) {
  Init(thread_id, isolation, read_id, commit_id);
}

void TransactionContext::Init(const size_t thread_id,
                              const IsolationLevelType isolation,
                              const cid_t &read_id, const cid_t &commit_id) {
  read_id_ = read_id;

  // commit id can be set at a transaction's commit phase.
  commit_id_ = commit_id;

  // set txn_id to commit_id.
  txn_id_ = commit_id_;

  epoch_id_ = read_id_ >> 32;

  thread_id_ = thread_id;

  is_written_ = false;

  isolation_level_ = isolation;

  gc_set_ = std::make_shared<GCSet>();
  gc_object_set_ = std::make_shared<GCObjectSet>();

  on_commit_triggers_.reset();
}

RWType TransactionContext::GetRWType(const ItemPointer &location) {
  const auto rw_set_it = rw_set_.find(location);
  if (rw_set_it != rw_set_.end()) {
    return rw_set_it->second;
  }
  return RWType::INVALID;
}

void TransactionContext::RecordRead(const ItemPointer &location) {
  PELOTON_ASSERT(rw_set_.find(location) == rw_set_.end() ||
                 (rw_set_[location] != RWType::DELETE &&
                  rw_set_[location] != RWType::INS_DEL));
  auto rw_set_it = rw_set_.find(location);
  if (rw_set_it != rw_set_.end()) {
    return;
  }
  rw_set_[location] = RWType::READ;
}

void TransactionContext::RecordReadOwn(const ItemPointer &location) {
  PELOTON_ASSERT(rw_set_.find(location) == rw_set_.end() ||
                 (rw_set_[location] != RWType::DELETE &&
                  rw_set_[location] != RWType::INS_DEL));
  rw_set_[location] = RWType::READ_OWN;
}

void TransactionContext::RecordUpdate(const ItemPointer &location) {
  PELOTON_ASSERT(rw_set_.find(location) == rw_set_.end() ||
                 (rw_set_[location] != RWType::DELETE &&
                  rw_set_[location] != RWType::INS_DEL));
  auto rw_set_it = rw_set_.find(location);
  if (rw_set_it != rw_set_.end() && (rw_set_it->second == RWType::READ ||
                                     rw_set_it->second == RWType::READ_OWN)) {
    rw_set_it->second = RWType::UPDATE;
    is_written_ = true;
  }
  PELOTON_ASSERT(is_written_);
}

void TransactionContext::RecordInsert(const ItemPointer &location) {
  PELOTON_ASSERT(rw_set_.find(location) == rw_set_.end());
  rw_set_[location] = RWType::INSERT;
  is_written_ = true;
}

bool TransactionContext::RecordDelete(const ItemPointer &location) {
  PELOTON_ASSERT(rw_set_.find(location) == rw_set_.end() ||
                 (rw_set_[location] != RWType::DELETE &&
                  rw_set_[location] != RWType::INS_DEL));
  auto rw_set_it = rw_set_.find(location);
  if (rw_set_it != rw_set_.end() && rw_set_it->second == RWType::INSERT) {
    PELOTON_ASSERT(is_written_);
    rw_set_it->second = RWType::INS_DEL;
    return true;
  } else {
    rw_set_[location] = RWType::DELETE;
    is_written_ = true;
    return false;
  }
}

const std::string TransactionContext::GetInfo() const {
  std::ostringstream os;

  os << " Txn :: @" << this << " ID : " << std::setw(4) << txn_id_
     << " Read ID : " << std::setw(4) << read_id_
     << " Commit ID : " << std::setw(4) << commit_id_
     << " Result : " << result_;

  return os.str();
}

void TransactionContext::AddOnCommitTrigger(
    trigger::TriggerData &trigger_data) {
  if (on_commit_triggers_ == nullptr) {
    on_commit_triggers_.reset(new trigger::TriggerSet());
  }
  on_commit_triggers_->push_back(trigger_data);
}

void TransactionContext::ExecOnCommitTriggers() {
  if (on_commit_triggers_ != nullptr) {
    on_commit_triggers_->ExecTriggers();
  }
}

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