<commit_before>// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @file PubSubWriter.hpp
 *
 */

#ifndef _TEST_PROFILING_PUBSUBWRITER_HPP_
#define _TEST_PROFILING_PUBSUBWRITER_HPP_

#include <fastrtps/fastrtps_fwd.h>
#include <fastrtps/Domain.h>
#include <fastrtps/participant/Participant.h>
#include <fastrtps/attributes/ParticipantAttributes.h>
#include <fastrtps/publisher/Publisher.h>
#include <fastrtps/publisher/PublisherListener.h>
#include <fastrtps/attributes/PublisherAttributes.h>

#include <string>
#include <list>
#include <condition_variable>
#include <boost/asio.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>
#include <gtest/gtest.h>

template<class TypeSupport>
class PubSubWriter
{
    class Listener : public eprosima::fastrtps::PublisherListener
    {
        public:

            Listener(PubSubWriter &writer) : writer_(writer){};

            ~Listener(){};

            void onPublicationMatched(eprosima::fastrtps::Publisher* /*pub*/, MatchingInfo &info)
            {
                if (info.status == MATCHED_MATCHING)
                    writer_.matched();
                else
                    writer_.unmatched();
            }

        private:

            Listener& operator=(const Listener&) NON_COPYABLE_CXX11;

            PubSubWriter &writer_;

    } listener_;

    public:

    typedef TypeSupport type_support;
    typedef typename type_support::type type;

    PubSubWriter(const std::string &topic_name) : listener_(*this), participant_(nullptr),
    publisher_(nullptr), topic_name_(topic_name), initialized_(false), matched_(0)
    {
            publisher_attr_.topic.topicDataType = type_.getName();
            // Generate topic name
            std::ostringstream t;
            t << topic_name_ << "_" << boost::asio::ip::host_name() << "_" << boost::interprocess::ipcdetail::get_current_process_id();
            publisher_attr_.topic.topicName = t.str();
    }

    ~PubSubWriter()
    {
        if(participant_ != nullptr)
            eprosima::fastrtps::Domain::removeParticipant(participant_);
    }

    void init()
    {
        //Create participant
        eprosima::fastrtps::ParticipantAttributes pattr;
        pattr.rtps.builtin.domainId = (uint32_t)boost::interprocess::ipcdetail::get_current_process_id() % 230;
        participant_ = eprosima::fastrtps::Domain::createParticipant(pattr);

        if(participant_ != nullptr)
        {
            // Register type
            eprosima::fastrtps::Domain::registerType(participant_, &type_);

            //Create publisher
            publisher_ = eprosima::fastrtps::Domain::createPublisher(participant_, publisher_attr_, &listener_);

            if(publisher_ != nullptr)
            {
                initialized_ = true;
                return;
            }

            eprosima::fastrtps::Domain::removeParticipant(participant_);
        }
    }

    bool isInitialized() const { return initialized_; }

    void destroy()
    {
        if(participant_ != nullptr)
        {
            eprosima::fastrtps::Domain::removeParticipant(participant_);
            participant_ = nullptr;
        }
    }

    void send(std::list<type>& msgs)
    {
        auto it = msgs.begin();

        while(it != msgs.end())
        {
            if(publisher_->write((void*)&(*it)))
            {
                it = msgs.erase(it);
            }
            else
                break;
        }
    }

    void waitDiscovery()
    {
        std::cout << "Writer waiting for discovery..." << std::endl;
        std::unique_lock<std::mutex> lock(mutex_);

        if(matched_ == 0)
            cv_.wait_for(lock, std::chrono::seconds(10));

        std::cout << "Writer discovery phase finished" << std::endl;
    }

    void waitRemoval()
    {
        std::unique_lock<std::mutex> lock(mutex_);

        if(matched_ != 0)
            cv_.wait_for(lock, std::chrono::seconds(10));
    }

    bool waitForAllAcked(const std::chrono::seconds& max_wait)
    {
        return publisher_->wait_for_all_acked(Time_t((int32_t)max_wait.count(), 0));
    }

    /*** Function to change QoS ***/
    PubSubWriter& reliability(const eprosima::fastrtps::ReliabilityQosPolicyKind kind)
    {
        publisher_attr_.qos.m_reliability.kind = kind;
        return *this;
    }

    PubSubWriter& asynchronously(const eprosima::fastrtps::PublishModeQosPolicyKind kind)
    {
        publisher_attr_.qos.m_publishMode.kind = kind;
        return *this;
    }

    PubSubWriter& history_kind(const eprosima::fastrtps::HistoryQosPolicyKind kind)
    {
        publisher_attr_.topic.historyQos.kind = kind;
        return *this;
    }

    PubSubWriter& history_depth(const int32_t depth)
    {
        publisher_attr_.topic.historyQos.depth = depth;
        return *this;
    }

    PubSubWriter& durability_kind(const eprosima::fastrtps::DurabilityQosPolicyKind kind)
    {
        publisher_attr_.qos.m_durability.kind = kind;
        return *this;
    }

    PubSubWriter& resource_limits_max_samples(const int32_t max)
    {
        publisher_attr_.topic.resourceLimitsQos.max_samples = max;
        return *this;
    }

    PubSubWriter& heartbeat_period_seconds(int32_t sec)
    {
        publisher_attr_.times.heartbeatPeriod.seconds = sec;
        return *this;
    }

    PubSubWriter& heartbeat_period_fraction(uint32_t frac)
    {
        publisher_attr_.times.heartbeatPeriod.fraction = frac;
        return *this;
    }

    private:

    void matched()
    {
        std::unique_lock<std::mutex> lock(mutex_);
        ++matched_;
        cv_.notify_one();
    }

    void unmatched()
    {
        std::unique_lock<std::mutex> lock(mutex_);
        --matched_;
        cv_.notify_one();
    }

    PubSubWriter& operator=(const PubSubWriter&)NON_COPYABLE_CXX11;

    eprosima::fastrtps::Participant *participant_;
    eprosima::fastrtps::PublisherAttributes publisher_attr_;
    eprosima::fastrtps::Publisher *publisher_;
    std::string topic_name_;
    bool initialized_;
    std::mutex mutex_;
    std::condition_variable cv_;
    unsigned int matched_;
    type_support type_;
};

#endif // _TEST_PROFILING_PUBSUBWRITER_HPP_
<commit_msg>Refs #1706. Remove reference to gtest<commit_after>// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @file PubSubWriter.hpp
 *
 */

#ifndef _TEST_PROFILING_PUBSUBWRITER_HPP_
#define _TEST_PROFILING_PUBSUBWRITER_HPP_

#include <fastrtps/fastrtps_fwd.h>
#include <fastrtps/Domain.h>
#include <fastrtps/participant/Participant.h>
#include <fastrtps/attributes/ParticipantAttributes.h>
#include <fastrtps/publisher/Publisher.h>
#include <fastrtps/publisher/PublisherListener.h>
#include <fastrtps/attributes/PublisherAttributes.h>

#include <string>
#include <list>
#include <condition_variable>
#include <boost/asio.hpp>
#include <boost/interprocess/detail/os_thread_functions.hpp>

template<class TypeSupport>
class PubSubWriter
{
    class Listener : public eprosima::fastrtps::PublisherListener
    {
        public:

            Listener(PubSubWriter &writer) : writer_(writer){};

            ~Listener(){};

            void onPublicationMatched(eprosima::fastrtps::Publisher* /*pub*/, MatchingInfo &info)
            {
                if (info.status == MATCHED_MATCHING)
                    writer_.matched();
                else
                    writer_.unmatched();
            }

        private:

            Listener& operator=(const Listener&) NON_COPYABLE_CXX11;

            PubSubWriter &writer_;

    } listener_;

    public:

    typedef TypeSupport type_support;
    typedef typename type_support::type type;

    PubSubWriter(const std::string &topic_name) : listener_(*this), participant_(nullptr),
    publisher_(nullptr), topic_name_(topic_name), initialized_(false), matched_(0)
    {
            publisher_attr_.topic.topicDataType = type_.getName();
            // Generate topic name
            std::ostringstream t;
            t << topic_name_ << "_" << boost::asio::ip::host_name() << "_" << boost::interprocess::ipcdetail::get_current_process_id();
            publisher_attr_.topic.topicName = t.str();
    }

    ~PubSubWriter()
    {
        if(participant_ != nullptr)
            eprosima::fastrtps::Domain::removeParticipant(participant_);
    }

    void init()
    {
        //Create participant
        eprosima::fastrtps::ParticipantAttributes pattr;
        pattr.rtps.builtin.domainId = (uint32_t)boost::interprocess::ipcdetail::get_current_process_id() % 230;
        participant_ = eprosima::fastrtps::Domain::createParticipant(pattr);

        if(participant_ != nullptr)
        {
            // Register type
            eprosima::fastrtps::Domain::registerType(participant_, &type_);

            //Create publisher
            publisher_ = eprosima::fastrtps::Domain::createPublisher(participant_, publisher_attr_, &listener_);

            if(publisher_ != nullptr)
            {
                initialized_ = true;
                return;
            }

            eprosima::fastrtps::Domain::removeParticipant(participant_);
        }
    }

    bool isInitialized() const { return initialized_; }

    void destroy()
    {
        if(participant_ != nullptr)
        {
            eprosima::fastrtps::Domain::removeParticipant(participant_);
            participant_ = nullptr;
        }
    }

    void send(std::list<type>& msgs)
    {
        auto it = msgs.begin();

        while(it != msgs.end())
        {
            if(publisher_->write((void*)&(*it)))
            {
                it = msgs.erase(it);
            }
            else
                break;
        }
    }

    void waitDiscovery()
    {
        std::cout << "Writer waiting for discovery..." << std::endl;
        std::unique_lock<std::mutex> lock(mutex_);

        if(matched_ == 0)
            cv_.wait_for(lock, std::chrono::seconds(10));

        std::cout << "Writer discovery phase finished" << std::endl;
    }

    void waitRemoval()
    {
        std::unique_lock<std::mutex> lock(mutex_);

        if(matched_ != 0)
            cv_.wait_for(lock, std::chrono::seconds(10));
    }

    bool waitForAllAcked(const std::chrono::seconds& max_wait)
    {
        return publisher_->wait_for_all_acked(Time_t((int32_t)max_wait.count(), 0));
    }

    /*** Function to change QoS ***/
    PubSubWriter& reliability(const eprosima::fastrtps::ReliabilityQosPolicyKind kind)
    {
        publisher_attr_.qos.m_reliability.kind = kind;
        return *this;
    }

    PubSubWriter& asynchronously(const eprosima::fastrtps::PublishModeQosPolicyKind kind)
    {
        publisher_attr_.qos.m_publishMode.kind = kind;
        return *this;
    }

    PubSubWriter& history_kind(const eprosima::fastrtps::HistoryQosPolicyKind kind)
    {
        publisher_attr_.topic.historyQos.kind = kind;
        return *this;
    }

    PubSubWriter& history_depth(const int32_t depth)
    {
        publisher_attr_.topic.historyQos.depth = depth;
        return *this;
    }

    PubSubWriter& durability_kind(const eprosima::fastrtps::DurabilityQosPolicyKind kind)
    {
        publisher_attr_.qos.m_durability.kind = kind;
        return *this;
    }

    PubSubWriter& resource_limits_max_samples(const int32_t max)
    {
        publisher_attr_.topic.resourceLimitsQos.max_samples = max;
        return *this;
    }

    PubSubWriter& heartbeat_period_seconds(int32_t sec)
    {
        publisher_attr_.times.heartbeatPeriod.seconds = sec;
        return *this;
    }

    PubSubWriter& heartbeat_period_fraction(uint32_t frac)
    {
        publisher_attr_.times.heartbeatPeriod.fraction = frac;
        return *this;
    }

    private:

    void matched()
    {
        std::unique_lock<std::mutex> lock(mutex_);
        ++matched_;
        cv_.notify_one();
    }

    void unmatched()
    {
        std::unique_lock<std::mutex> lock(mutex_);
        --matched_;
        cv_.notify_one();
    }

    PubSubWriter& operator=(const PubSubWriter&)NON_COPYABLE_CXX11;

    eprosima::fastrtps::Participant *participant_;
    eprosima::fastrtps::PublisherAttributes publisher_attr_;
    eprosima::fastrtps::Publisher *publisher_;
    std::string topic_name_;
    bool initialized_;
    std::mutex mutex_;
    std::condition_variable cv_;
    unsigned int matched_;
    type_support type_;
};

#endif // _TEST_PROFILING_PUBSUBWRITER_HPP_
<|endoftext|>


<commit_before>// Copyright 2004-present Facebook. All Rights Reserved.

#include <folly/Memory.h>
#include <folly/io/async/AsyncServerSocket.h>
#include <gmock/gmock.h>
#include "src/FrameTransport.h"
#include "src/NullRequestHandler.h"
#include "src/SmartPointers.h"
#include "src/StandardReactiveSocket.h"
#include "src/SubscriptionBase.h"
#include "src/framed/FramedDuplexConnection.h"
#include "src/tcp/TcpDuplexConnection.h"
#include "test/simple/PrintSubscriber.h"
#include "test/simple/StatsPrinter.h"

using namespace ::testing;
using namespace ::reactivesocket;
using namespace ::folly;

DEFINE_string(address, "9898", "host:port to listen to");

namespace {

std::vector<std::pair<
    std::unique_ptr<StandardReactiveSocket>,
    ResumeIdentificationToken>>
    g_reactiveSockets;

class ServerSubscription : public SubscriptionBase {
 public:
  explicit ServerSubscription(std::shared_ptr<Subscriber<Payload>> response)
      : ExecutorBase(defaultExecutor()), response_(std::move(response)) {}

  ~ServerSubscription() {
    LOG(INFO) << "~ServerSubscription " << this;
  }

  // Subscription methods
  void requestImpl(size_t n) override {
    LOG(INFO) << "request " << this;
    response_.onNext(Payload("from server"));
    response_.onNext(Payload("from server2"));
    LOG(INFO) << "calling onComplete";
    response_.onComplete();
    //    response_.onError(std::runtime_error("XXX"));
  }

  void cancelImpl() override {
    LOG(INFO) << "cancel " << this;
  }

 private:
  SubscriberPtr<Subscriber<Payload>> response_;
};

class ServerRequestHandler : public DefaultRequestHandler {
 public:
  explicit ServerRequestHandler(std::shared_ptr<StreamState> streamState)
      : streamState_(streamState) {}

  /// Handles a new inbound Subscription requested by the other end.
  void handleRequestSubscription(
      Payload request,
      StreamId streamId,
      const std::shared_ptr<Subscriber<Payload>>& response) override {
    LOG(INFO) << "ServerRequestHandler.handleRequestSubscription " << request;
    response->onSubscribe(std::make_shared<ServerSubscription>(response));
  }

  /// Handles a new inbound Stream requested by the other end.
  void handleRequestStream(
      Payload request,
      StreamId streamId,
      const std::shared_ptr<Subscriber<Payload>>& response) override {
    LOG(INFO) << "ServerRequestHandler.handleRequestStream " << request;

    response->onSubscribe(std::make_shared<ServerSubscription>(response));
  }

  void handleFireAndForgetRequest(Payload request, StreamId streamId) override {
    LOG(INFO) << "ServerRequestHandler.handleFireAndForgetRequest " << request
              << "\n";
  }

  void handleMetadataPush(std::unique_ptr<folly::IOBuf> request) override {
    LOG(INFO) << "ServerRequestHandler.handleMetadataPush "
              << request->moveToFbString() << "\n";
  }

  std::shared_ptr<StreamState> handleSetupPayload(
      ReactiveSocket& socket,
      ConnectionSetupPayload request) override {
    std::stringstream str;

    str << "ServerRequestHandler.handleSetupPayload " << request
        << " setup token <";
    for (uint8_t byte : request.token.data()) {
      str << (int)byte;
    }
    str << "> " << streamState_.get() << " " << streamState_->streams_.size()
        << "\n";
    LOG(INFO) << str.str();
    // TODO: we need to get ReactiveSocket pointer somehow
    g_reactiveSockets[0].second = request.token;
    // TODO: the return value is not used now
    return streamState_;
  }

  bool handleResume(
      ReactiveSocket& socket,
      const ResumeIdentificationToken& token,
      ResumePosition position) override {
    std::stringstream str;

    str << "ServerRequestHandler.handleResume resume token <";
    for (uint8_t byte : token.data()) {
      str << (int)byte;
    }
    str << "> " << streamState_.get() << " " << streamState_->streams_.size()
        << "\n";

    LOG(INFO) << str.str();

    CHECK(g_reactiveSockets.size() == 2);
    CHECK(g_reactiveSockets[0].second == token);

    LOG(INFO) << "detaching frame transport";
    auto frameTransport = g_reactiveSockets[1].first->detachFrameTransport();
    LOG(INFO) << "tryResumeServer...";
    auto result =
        g_reactiveSockets[0].first->tryResumeServer(frameTransport, position);
    LOG(INFO) << "resume " << (result ? "SUCCEEDED" : "FAILED");

    // TODO(lehecka): unused, make it used again
    // return streamState_;
    return false;
  }

  void handleCleanResume(std::shared_ptr<Subscription> response) override {
    LOG(INFO) << "clean resume stream"
              << "\n";
  }

  void handleDirtyResume(std::shared_ptr<Subscription> response) override {
    LOG(INFO) << "dirty resume stream"
              << "\n";
  }

 private:
  // only keeping one
  std::shared_ptr<StreamState> streamState_;
};

class Callback : public AsyncServerSocket::AcceptCallback {
 public:
  Callback(EventBase& eventBase, Stats& stats)
      : streamState_(std::make_shared<StreamState>(Stats::noop())),
        eventBase_(eventBase),
        stats_(stats){};

  virtual ~Callback() = default;

  virtual void connectionAccepted(
      int fd,
      const SocketAddress& clientAddr) noexcept override {
    LOG(INFO) << "connectionAccepted" << clientAddr.describe();

    auto socket =
        folly::AsyncSocket::UniquePtr(new AsyncSocket(&eventBase_, fd));

    std::unique_ptr<DuplexConnection> connection =
        folly::make_unique<TcpDuplexConnection>(std::move(socket), stats_);
    std::unique_ptr<DuplexConnection> framedConnection =
        folly::make_unique<FramedDuplexConnection>(
            std::move(connection), inlineExecutor());
    std::unique_ptr<RequestHandler> requestHandler =
        folly::make_unique<ServerRequestHandler>(streamState_);

    std::unique_ptr<StandardReactiveSocket> rs =
        StandardReactiveSocket::disconnectedServer(
            eventBase_, std::move(requestHandler), stats_);

    rs->onConnected([](ReactiveSocket& socket) {
      LOG(INFO) << "socket connected " << &socket;
    });
    rs->onDisconnected([](ReactiveSocket& socket) {
      LOG(INFO) << "socket disconnect " << &socket;
      // to verify these frames will be queued up
      socket.requestStream(
          Payload("from server resume"), std::make_shared<PrintSubscriber>());
    });
    rs->onClosed([](ReactiveSocket& socket) {
      LOG(INFO) << "socket closed " << &socket;
    });

    if (g_reactiveSockets.empty()) {
      LOG(INFO) << "requestStream";
      rs->requestStream(
          Payload("from server"), std::make_shared<PrintSubscriber>());
    }

    LOG(INFO) << "serverConnecting ...";
    rs->serverConnect(
        std::make_shared<FrameTransport>(std::move(framedConnection)), true);

    LOG(INFO) << "RS " << rs.get();

    g_reactiveSockets.emplace_back(
        std::move(rs), ResumeIdentificationToken::generateNew());
  }

  void removeSocket(ReactiveSocket& socket) {
    if (!shuttingDown) {
      g_reactiveSockets.erase(std::remove_if(
          g_reactiveSockets.begin(),
          g_reactiveSockets.end(),
          [&socket](const std::pair<
                    std::unique_ptr<ReactiveSocket>,
                    ResumeIdentificationToken>& kv) {
            return kv.first.get() == &socket;
          }));
    }
  }

  virtual void acceptError(const std::exception& ex) noexcept override {
    LOG(INFO) << "acceptError" << ex.what();
  }

  void shutdown() {
    shuttingDown = true;
    g_reactiveSockets.clear();
  }

 private:
  // only one for demo purposes. Should be token dependent.
  std::shared_ptr<StreamState> streamState_;
  EventBase& eventBase_;
  Stats& stats_;
  bool shuttingDown{false};
};
}

int main(int argc, char* argv[]) {
  FLAGS_logtostderr = true;
  FLAGS_minloglevel = 0;

  google::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);
  google::InstallFailureSignalHandler();

  reactivesocket::StatsPrinter statsPrinter;

  EventBase eventBase;
  auto thread = std::thread([&eventBase]() { eventBase.loopForever(); });

  Callback callback(eventBase, statsPrinter);

  auto serverSocket = AsyncServerSocket::newSocket(&eventBase);

  eventBase.runInEventBaseThreadAndWait(
      [&callback, &eventBase, &serverSocket]() {
        folly::SocketAddress addr;
        addr.setFromLocalIpPort(FLAGS_address);

        serverSocket->setReusePortEnabled(true);
        serverSocket->bind(addr);
        serverSocket->addAcceptCallback(&callback, &eventBase);
        serverSocket->listen(10);
        serverSocket->startAccepting();

        LOG(INFO) << "server listening on ";
        for (auto i : serverSocket->getAddresses())
          LOG(INFO) << i.describe() << ' ';
      });

  std::string name;
  std::getline(std::cin, name);

  eventBase.runInEventBaseThreadAndWait([&callback]() { callback.shutdown(); });
  eventBase.terminateLoopSoon();

  thread.join();
}
<commit_msg>fixing travis<commit_after>// Copyright 2004-present Facebook. All Rights Reserved.

#include <folly/Memory.h>
#include <folly/io/async/AsyncServerSocket.h>
#include <gmock/gmock.h>
#include "src/FrameTransport.h"
#include "src/NullRequestHandler.h"
#include "src/SmartPointers.h"
#include "src/StandardReactiveSocket.h"
#include "src/SubscriptionBase.h"
#include "src/framed/FramedDuplexConnection.h"
#include "src/tcp/TcpDuplexConnection.h"
#include "test/simple/PrintSubscriber.h"
#include "test/simple/StatsPrinter.h"

using namespace ::testing;
using namespace ::reactivesocket;
using namespace ::folly;

DEFINE_string(address, "9898", "host:port to listen to");

namespace {

std::vector<std::pair<
    std::unique_ptr<StandardReactiveSocket>,
    ResumeIdentificationToken>>
    g_reactiveSockets;

class ServerSubscription : public SubscriptionBase {
 public:
  explicit ServerSubscription(std::shared_ptr<Subscriber<Payload>> response)
      : ExecutorBase(defaultExecutor()), response_(std::move(response)) {}

  ~ServerSubscription() {
    LOG(INFO) << "~ServerSubscription " << this;
  }

  // Subscription methods
  void requestImpl(size_t n) override {
    LOG(INFO) << "request " << this;
    response_.onNext(Payload("from server"));
    response_.onNext(Payload("from server2"));
    LOG(INFO) << "calling onComplete";
    response_.onComplete();
    //    response_.onError(std::runtime_error("XXX"));
  }

  void cancelImpl() override {
    LOG(INFO) << "cancel " << this;
  }

 private:
  SubscriberPtr<Subscriber<Payload>> response_;
};

class ServerRequestHandler : public DefaultRequestHandler {
 public:
  explicit ServerRequestHandler(std::shared_ptr<StreamState> streamState)
      : streamState_(streamState) {}

  /// Handles a new inbound Subscription requested by the other end.
  void handleRequestSubscription(
      Payload request,
      StreamId streamId,
      const std::shared_ptr<Subscriber<Payload>>& response) override {
    LOG(INFO) << "ServerRequestHandler.handleRequestSubscription " << request;
    response->onSubscribe(std::make_shared<ServerSubscription>(response));
  }

  /// Handles a new inbound Stream requested by the other end.
  void handleRequestStream(
      Payload request,
      StreamId streamId,
      const std::shared_ptr<Subscriber<Payload>>& response) override {
    LOG(INFO) << "ServerRequestHandler.handleRequestStream " << request;

    response->onSubscribe(std::make_shared<ServerSubscription>(response));
  }

  void handleFireAndForgetRequest(Payload request, StreamId streamId) override {
    LOG(INFO) << "ServerRequestHandler.handleFireAndForgetRequest " << request
              << "\n";
  }

  void handleMetadataPush(std::unique_ptr<folly::IOBuf> request) override {
    LOG(INFO) << "ServerRequestHandler.handleMetadataPush "
              << request->moveToFbString() << "\n";
  }

  std::shared_ptr<StreamState> handleSetupPayload(
      ReactiveSocket& socket,
      ConnectionSetupPayload request) override {
    std::stringstream str;

    str << "ServerRequestHandler.handleSetupPayload " << request
        << " setup token <";
    for (uint8_t byte : request.token.data()) {
      str << (int)byte;
    }
    str << "> " << streamState_.get() << " " << streamState_->streams_.size()
        << "\n";
    LOG(INFO) << str.str();
    // TODO: we need to get ReactiveSocket pointer somehow
    g_reactiveSockets[0].second = request.token;
    // TODO: the return value is not used now
    return streamState_;
  }

  bool handleResume(
      ReactiveSocket& socket,
      const ResumeIdentificationToken& token,
      ResumePosition position) override {
    std::stringstream str;

    str << "ServerRequestHandler.handleResume resume token <";
    for (uint8_t byte : token.data()) {
      str << (int)byte;
    }
    str << "> " << streamState_.get() << " " << streamState_->streams_.size()
        << "\n";

    LOG(INFO) << str.str();

    CHECK(g_reactiveSockets.size() == 2);
    CHECK(g_reactiveSockets[0].second == token);

    LOG(INFO) << "detaching frame transport";
    auto frameTransport = g_reactiveSockets[1].first->detachFrameTransport();
    LOG(INFO) << "tryResumeServer...";
    auto result =
        g_reactiveSockets[0].first->tryResumeServer(frameTransport, position);
    LOG(INFO) << "resume " << (result ? "SUCCEEDED" : "FAILED");

    // TODO(lehecka): unused, make it used again
    // return streamState_;
    return false;
  }

  void handleCleanResume(std::shared_ptr<Subscription> response) override {
    LOG(INFO) << "clean resume stream"
              << "\n";
  }

  void handleDirtyResume(std::shared_ptr<Subscription> response) override {
    LOG(INFO) << "dirty resume stream"
              << "\n";
  }

 private:
  // only keeping one
  std::shared_ptr<StreamState> streamState_;
};

class Callback : public AsyncServerSocket::AcceptCallback {
 public:
  Callback(EventBase& eventBase, Stats& stats)
      : streamState_(std::make_shared<StreamState>(Stats::noop())),
        eventBase_(eventBase),
        stats_(stats){};

  virtual ~Callback() = default;

  virtual void connectionAccepted(
      int fd,
      const SocketAddress& clientAddr) noexcept override {
    LOG(INFO) << "connectionAccepted" << clientAddr.describe();

    auto socket =
        folly::AsyncSocket::UniquePtr(new AsyncSocket(&eventBase_, fd));

    std::unique_ptr<DuplexConnection> connection =
        folly::make_unique<TcpDuplexConnection>(std::move(socket), stats_);
    std::unique_ptr<DuplexConnection> framedConnection =
        folly::make_unique<FramedDuplexConnection>(
            std::move(connection), inlineExecutor());
    std::unique_ptr<RequestHandler> requestHandler =
        folly::make_unique<ServerRequestHandler>(streamState_);

    std::unique_ptr<StandardReactiveSocket> rs =
        StandardReactiveSocket::disconnectedServer(
            eventBase_, std::move(requestHandler), stats_);

    rs->onConnected([](ReactiveSocket& socket) {
      LOG(INFO) << "socket connected " << &socket;
    });
    rs->onDisconnected([](ReactiveSocket& socket) {
      LOG(INFO) << "socket disconnect " << &socket;
      // to verify these frames will be queued up
      socket.requestStream(
          Payload("from server resume"), std::make_shared<PrintSubscriber>());
    });
    rs->onClosed([](ReactiveSocket& socket) {
      LOG(INFO) << "socket closed " << &socket;
    });

    if (g_reactiveSockets.empty()) {
      LOG(INFO) << "requestStream";
      rs->requestStream(
          Payload("from server"), std::make_shared<PrintSubscriber>());
    }

    LOG(INFO) << "serverConnecting ...";
    rs->serverConnect(
        std::make_shared<FrameTransport>(std::move(framedConnection)), true);

    LOG(INFO) << "RS " << rs.get();

    g_reactiveSockets.emplace_back(
        std::move(rs), ResumeIdentificationToken::generateNew());
  }

  void removeSocket(ReactiveSocket& socket) {
    if (!shuttingDown) {
      g_reactiveSockets.erase(std::remove_if(
          g_reactiveSockets.begin(),
          g_reactiveSockets.end(),
          [&socket](const std::pair<
                    std::unique_ptr<StandardReactiveSocket>,
                    ResumeIdentificationToken>& kv) {
            return kv.first.get() == &socket;
          }));
    }
  }

  virtual void acceptError(const std::exception& ex) noexcept override {
    LOG(INFO) << "acceptError" << ex.what();
  }

  void shutdown() {
    shuttingDown = true;
    g_reactiveSockets.clear();
  }

 private:
  // only one for demo purposes. Should be token dependent.
  std::shared_ptr<StreamState> streamState_;
  EventBase& eventBase_;
  Stats& stats_;
  bool shuttingDown{false};
};
}

int main(int argc, char* argv[]) {
  FLAGS_logtostderr = true;
  FLAGS_minloglevel = 0;

  google::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);
  google::InstallFailureSignalHandler();

  reactivesocket::StatsPrinter statsPrinter;

  EventBase eventBase;
  auto thread = std::thread([&eventBase]() { eventBase.loopForever(); });

  Callback callback(eventBase, statsPrinter);

  auto serverSocket = AsyncServerSocket::newSocket(&eventBase);

  eventBase.runInEventBaseThreadAndWait(
      [&callback, &eventBase, &serverSocket]() {
        folly::SocketAddress addr;
        addr.setFromLocalIpPort(FLAGS_address);

        serverSocket->setReusePortEnabled(true);
        serverSocket->bind(addr);
        serverSocket->addAcceptCallback(&callback, &eventBase);
        serverSocket->listen(10);
        serverSocket->startAccepting();

        LOG(INFO) << "server listening on ";
        for (auto i : serverSocket->getAddresses())
          LOG(INFO) << i.describe() << ' ';
      });

  std::string name;
  std::getline(std::cin, name);

  eventBase.runInEventBaseThreadAndWait([&callback]() { callback.shutdown(); });
  eventBase.terminateLoopSoon();

  thread.join();
}
<|endoftext|>


<commit_before><commit_msg>Update: system_io prototype<commit_after><|endoftext|>


<commit_before>/**
 * @file nearest_neighbor_rules_impl.hpp
 * @author Ryan Curtin
 *
 * Implementation of NearestNeighborRules.
 */
#ifndef __MLPACK_METHODS_NEIGHBOR_SEARCH_NEAREST_NEIGHBOR_RULES_IMPL_HPP
#define __MLPACK_METHODS_NEIGHBOR_SEARCH_NEAREST_NEIGHBOR_RULES_IMPL_HPP

// In case it hasn't been included yet.
#include "neighbor_search_rules.hpp"

namespace mlpack {
namespace neighbor {

template<typename SortPolicy, typename MetricType, typename TreeType>
NeighborSearchRules<SortPolicy, MetricType, TreeType>::NeighborSearchRules(
    const arma::mat& referenceSet,
    const arma::mat& querySet,
    arma::Mat<size_t>& neighbors,
    arma::mat& distances,
    MetricType& metric) :
    referenceSet(referenceSet),
    querySet(querySet),
    neighbors(neighbors),
    distances(distances),
    metric(metric)
{ /* Nothing left to do. */ }

template<typename SortPolicy, typename MetricType, typename TreeType>
inline force_inline // Absolutely MUST be inline so optimizations can happen.
double NeighborSearchRules<SortPolicy, MetricType, TreeType>::
BaseCase(const size_t queryIndex, const size_t referenceIndex)
{
  // If the datasets are the same, then this search is only using one dataset
  // and we should not return identical points.
  if ((&querySet == &referenceSet) && (queryIndex == referenceIndex))
    return 0.0;

  double distance = metric.Evaluate(querySet.unsafe_col(queryIndex),
                                    referenceSet.unsafe_col(referenceIndex));

  // If this distance is better than any of the current candidates, the
  // SortDistance() function will give us the position to insert it into.
  arma::vec queryDist = distances.unsafe_col(queryIndex);
  size_t insertPosition = SortPolicy::SortDistance(queryDist, distance);

  // SortDistance() returns (size_t() - 1) if we shouldn't add it.
  if (insertPosition != (size_t() - 1))
    InsertNeighbor(queryIndex, insertPosition, referenceIndex, distance);

  return distance;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Prescore(
    TreeType& queryNode,
    TreeType& referenceNode,
    TreeType& referenceChildNode,
    const double baseCaseResult) const
{
  const double distance = SortPolicy::BestNodeToNodeDistance(&queryNode,
      &referenceNode, &referenceChildNode, baseCaseResult);

  // Update our bound.
  queryNode.Stat().Bound() = CalculateBound(queryNode);
  const double bestDistance = queryNode.Stat().Bound();

  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::PrescoreQ(
    TreeType& queryNode,
    TreeType& queryChildNode,
    TreeType& referenceNode,
    const double baseCaseResult) const
{
  const double distance = SortPolicy::BestNodeToNodeDistance(&referenceNode,
      &queryNode, &queryChildNode, baseCaseResult);

  // Update our bound.
  queryNode.Stat().Bound() = CalculateBound(queryNode);
  const double bestDistance = queryNode.Stat().Bound();

  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Score(
    const size_t queryIndex,
    TreeType& referenceNode) const
{
  const arma::vec queryPoint = querySet.unsafe_col(queryIndex);
  const double distance = SortPolicy::BestPointToNodeDistance(queryPoint,
      &referenceNode);
  const double bestDistance = distances(distances.n_rows - 1, queryIndex);

  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Score(
    const size_t queryIndex,
    TreeType& referenceNode,
    const double baseCaseResult) const
{
  const arma::vec queryPoint = querySet.unsafe_col(queryIndex);
  const double distance = SortPolicy::BestPointToNodeDistance(queryPoint,
      &referenceNode, baseCaseResult);
  const double bestDistance = distances(distances.n_rows - 1, queryIndex);

  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Rescore(
    const size_t queryIndex,
    TreeType& /* referenceNode */,
    const double oldScore) const
{
  // If we are already pruning, still prune.
  if (oldScore == DBL_MAX)
    return oldScore;

  // Just check the score again against the distances.
  const double bestDistance = distances(distances.n_rows - 1, queryIndex);

  return (SortPolicy::IsBetter(oldScore, bestDistance)) ? oldScore : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Score(
    TreeType& queryNode,
    TreeType& referenceNode) const
{
  const double distance = SortPolicy::BestNodeToNodeDistance(&queryNode,
      &referenceNode);

  // Update our bound.
  queryNode.Stat().Bound() = CalculateBound(queryNode);
  const double bestDistance = queryNode.Stat().Bound();

  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Score(
    TreeType& queryNode,
    TreeType& referenceNode,
    const double baseCaseResult) const
{
  const double distance = SortPolicy::BestNodeToNodeDistance(&queryNode,
      &referenceNode, baseCaseResult);

  // Update our bound.
  queryNode.Stat().Bound() = CalculateBound(queryNode);
  const double bestDistance = queryNode.Stat().Bound();

  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Rescore(
    TreeType& queryNode,
    TreeType& /* referenceNode */,
    const double oldScore) const
{
  if (oldScore == DBL_MAX)
    return oldScore;

  // Update our bound.
  queryNode.Stat().Bound() = CalculateBound(queryNode);
  const double bestDistance = queryNode.Stat().Bound();

  return (SortPolicy::IsBetter(oldScore, bestDistance)) ? oldScore : DBL_MAX;
}
/*
template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::FinishNode(
    TreeType& queryNode) const
{
  // Find the bound of points contained in this node.
  double pointBound = SortPolicy::BestDistance();
  const double maxDescendantDistance = queryNode.FurthestDescendantDistance();

  for (size_t i = 0; i < queryNode.NumPoints(); ++i)
  {
    // The bound for this point is the k-th best distance plus the maximum
    // distance to a child of this node.
    const double bound = distances(distances.n_rows - 1, queryNode.Point(i)) +
        maxDescendantDistance;
    if (SortPolicy::IsBetter(pointBound, bound))
      pointBound = bound;
  }

  // Push bound to parent.
}
*/

// Calculate the bound for a given query node in its current state.
template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::
    CalculateBound(TreeType& queryNode) const
{
  double pointBound = SortPolicy::BestDistance();
  double childBound = SortPolicy::BestDistance();
  const double maxDescendantDistance = queryNode.FurthestDescendantDistance();

  // Find the bound of the points contained in this node.
  for (size_t i = 0; i < queryNode.NumPoints(); ++i)
  {
    // The bound for this point is the k-th best distance plus the maximum
    // distance to a child of this node.
    const double bound = distances(distances.n_rows - 1, queryNode.Point(i)) +
        maxDescendantDistance;
    if (SortPolicy::IsBetter(pointBound, bound))
      pointBound = bound;
  }

  // Find the bound of the children.
  for (size_t i = 0; i < queryNode.NumChildren(); ++i)
  {
    const double bound = queryNode.Child(i).Stat().Bound();
    if (SortPolicy::IsBetter(childBound, bound))
      childBound = bound;
  }

  // If the bound of the children is uninitialized
  // (SortPolicy::WorstDistance()), then maybe we can create a bound for the
  // children.  But this requires a point bound to exist.
  if (childBound == SortPolicy::WorstDistance() &&
      pointBound != SortPolicy::BestDistance()) // This could fail!
      // SortPolicy::BestDistance() could be a valid bound!
  {
    // Should we be considering queryNode.Stat().Bound() too?
    childBound = pointBound + maxDescendantDistance;
    Log::Debug << "Child bound is " << childBound << std::endl;
  }

  // Return the worse of the two bounds.
  if (SortPolicy::IsBetter(childBound, pointBound))
    return pointBound;
  else
    return childBound;
}

/**
 * Helper function to insert a point into the neighbors and distances matrices.
 *
 * @param queryIndex Index of point whose neighbors we are inserting into.
 * @param pos Position in list to insert into.
 * @param neighbor Index of reference point which is being inserted.
 * @param distance Distance from query point to reference point.
 */
template<typename SortPolicy, typename MetricType, typename TreeType>
void NeighborSearchRules<SortPolicy, MetricType, TreeType>::InsertNeighbor(
    const size_t queryIndex,
    const size_t pos,
    const size_t neighbor,
    const double distance)
{
  // We only memmove() if there is actually a need to shift something.
  if (pos < (distances.n_rows - 1))
  {
    int len = (distances.n_rows - 1) - pos;
    memmove(distances.colptr(queryIndex) + (pos + 1),
        distances.colptr(queryIndex) + pos,
        sizeof(double) * len);
    memmove(neighbors.colptr(queryIndex) + (pos + 1),
        neighbors.colptr(queryIndex) + pos,
        sizeof(size_t) * len);
  }

  // Now put the new information in the right index.
  distances(pos, queryIndex) = distance;
  neighbors(pos, queryIndex) = neighbor;
}

}; // namespace neighbor
}; // namespace mlpack

#endif // __MLPACK_METHODS_NEIGHBOR_SEARCH_NEAREST_NEIGHBOR_RULES_IMPL_HPP
<commit_msg>Better calculation of bound.  We could still optimize a little bit.  Debug output is for #243; this solves #264.<commit_after>/**
 * @file nearest_neighbor_rules_impl.hpp
 * @author Ryan Curtin
 *
 * Implementation of NearestNeighborRules.
 */
#ifndef __MLPACK_METHODS_NEIGHBOR_SEARCH_NEAREST_NEIGHBOR_RULES_IMPL_HPP
#define __MLPACK_METHODS_NEIGHBOR_SEARCH_NEAREST_NEIGHBOR_RULES_IMPL_HPP

// In case it hasn't been included yet.
#include "neighbor_search_rules.hpp"

namespace mlpack {
namespace neighbor {

template<typename SortPolicy, typename MetricType, typename TreeType>
NeighborSearchRules<SortPolicy, MetricType, TreeType>::NeighborSearchRules(
    const arma::mat& referenceSet,
    const arma::mat& querySet,
    arma::Mat<size_t>& neighbors,
    arma::mat& distances,
    MetricType& metric) :
    referenceSet(referenceSet),
    querySet(querySet),
    neighbors(neighbors),
    distances(distances),
    metric(metric)
{ /* Nothing left to do. */ }

template<typename SortPolicy, typename MetricType, typename TreeType>
inline force_inline // Absolutely MUST be inline so optimizations can happen.
double NeighborSearchRules<SortPolicy, MetricType, TreeType>::
BaseCase(const size_t queryIndex, const size_t referenceIndex)
{
  // If the datasets are the same, then this search is only using one dataset
  // and we should not return identical points.
  if ((&querySet == &referenceSet) && (queryIndex == referenceIndex))
    return 0.0;

  double distance = metric.Evaluate(querySet.unsafe_col(queryIndex),
                                    referenceSet.unsafe_col(referenceIndex));

  // If this distance is better than any of the current candidates, the
  // SortDistance() function will give us the position to insert it into.
  arma::vec queryDist = distances.unsafe_col(queryIndex);
  size_t insertPosition = SortPolicy::SortDistance(queryDist, distance);

  // SortDistance() returns (size_t() - 1) if we shouldn't add it.
  if (insertPosition != (size_t() - 1))
    InsertNeighbor(queryIndex, insertPosition, referenceIndex, distance);

  return distance;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Prescore(
    TreeType& queryNode,
    TreeType& referenceNode,
    TreeType& referenceChildNode,
    const double baseCaseResult) const
{
  const double distance = SortPolicy::BestNodeToNodeDistance(&queryNode,
      &referenceNode, &referenceChildNode, baseCaseResult);

  // Update our bound.
  queryNode.Stat().Bound() = CalculateBound(queryNode);
  const double bestDistance = queryNode.Stat().Bound();

  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::PrescoreQ(
    TreeType& queryNode,
    TreeType& queryChildNode,
    TreeType& referenceNode,
    const double baseCaseResult) const
{
  const double distance = SortPolicy::BestNodeToNodeDistance(&referenceNode,
      &queryNode, &queryChildNode, baseCaseResult);

  // Update our bound.
  queryNode.Stat().Bound() = CalculateBound(queryNode);
  const double bestDistance = queryNode.Stat().Bound();

  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Score(
    const size_t queryIndex,
    TreeType& referenceNode) const
{
  const arma::vec queryPoint = querySet.unsafe_col(queryIndex);
  const double distance = SortPolicy::BestPointToNodeDistance(queryPoint,
      &referenceNode);
  const double bestDistance = distances(distances.n_rows - 1, queryIndex);

  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Score(
    const size_t queryIndex,
    TreeType& referenceNode,
    const double baseCaseResult) const
{
  const arma::vec queryPoint = querySet.unsafe_col(queryIndex);
  const double distance = SortPolicy::BestPointToNodeDistance(queryPoint,
      &referenceNode, baseCaseResult);
  const double bestDistance = distances(distances.n_rows - 1, queryIndex);

  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Rescore(
    const size_t queryIndex,
    TreeType& /* referenceNode */,
    const double oldScore) const
{
  // If we are already pruning, still prune.
  if (oldScore == DBL_MAX)
    return oldScore;

  // Just check the score again against the distances.
  const double bestDistance = distances(distances.n_rows - 1, queryIndex);

  return (SortPolicy::IsBetter(oldScore, bestDistance)) ? oldScore : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Score(
    TreeType& queryNode,
    TreeType& referenceNode) const
{
  const double distance = SortPolicy::BestNodeToNodeDistance(&queryNode,
      &referenceNode);

  // Update our bound.
  queryNode.Stat().Bound() = CalculateBound(queryNode);
  const double bestDistance = queryNode.Stat().Bound();

  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Score(
    TreeType& queryNode,
    TreeType& referenceNode,
    const double baseCaseResult) const
{
  const double distance = SortPolicy::BestNodeToNodeDistance(&queryNode,
      &referenceNode, baseCaseResult);

  // Update our bound.
  queryNode.Stat().Bound() = CalculateBound(queryNode);
  const double bestDistance = queryNode.Stat().Bound();

  return (SortPolicy::IsBetter(distance, bestDistance)) ? distance : DBL_MAX;
}

template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::Rescore(
    TreeType& queryNode,
    TreeType& /* referenceNode */,
    const double oldScore) const
{
  if (oldScore == DBL_MAX)
    return oldScore;

  // Update our bound.
  queryNode.Stat().Bound() = CalculateBound(queryNode);
  const double bestDistance = queryNode.Stat().Bound();

  return (SortPolicy::IsBetter(oldScore, bestDistance)) ? oldScore : DBL_MAX;
}
/*
template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::FinishNode(
    TreeType& queryNode) const
{
  // Find the bound of points contained in this node.
  double pointBound = SortPolicy::BestDistance();
  const double maxDescendantDistance = queryNode.FurthestDescendantDistance();

  for (size_t i = 0; i < queryNode.NumPoints(); ++i)
  {
    // The bound for this point is the k-th best distance plus the maximum
    // distance to a child of this node.
    const double bound = distances(distances.n_rows - 1, queryNode.Point(i)) +
        maxDescendantDistance;
    if (SortPolicy::IsBetter(pointBound, bound))
      pointBound = bound;
  }

  // Push bound to parent.
}
*/

// Calculate the bound for a given query node in its current state.
template<typename SortPolicy, typename MetricType, typename TreeType>
inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::
    CalculateBound(TreeType& queryNode) const
{
  double pointBound = SortPolicy::BestDistance();
  double childBound = SortPolicy::BestDistance();
  const double maxDescendantDistance = queryNode.FurthestDescendantDistance();

  // Find the bound of the points contained in this node.
  for (size_t i = 0; i < queryNode.NumPoints(); ++i)
  {
    // The bound for this point is the k-th best distance plus the maximum
    // distance to a child of this node.
    const double bound = distances(distances.n_rows - 1, queryNode.Point(i)) +
        maxDescendantDistance;
    if (SortPolicy::IsBetter(pointBound, bound))
      pointBound = bound;
  }

  // Find the bound of the children.
  for (size_t i = 0; i < queryNode.NumChildren(); ++i)
  {
    const double bound = queryNode.Child(i).Stat().Bound();
    if (SortPolicy::IsBetter(childBound, bound))
      childBound = bound;
  }

  // If there are no points, then break; the bound must be the child bound.
  if (queryNode.NumPoints() == 0)
    return childBound;

  // If there are no children, then break; the bound must be the point bound.
  if (queryNode.NumChildren() == 0)
    return pointBound;

//  Log::Debug << "Point bound " << pointBound << std::endl;
//  Log::Debug << "Child bound " << childBound << std::endl;
//  Log::Debug << "Furthest descendant distance " << maxDescendantDistance <<
//      std::endl;

  // If the bound of the children is uninitialized
  // (SortPolicy::WorstDistance()), then maybe we can create a bound for the
  // children.  But this requires a point bound to exist.

  // It is possible that we could calculate a better bound for the children.
  if (pointBound != SortPolicy::WorstDistance())
  {
    const double pointChildBound = pointBound + maxDescendantDistance;
//    Log::Debug << "Point-child bound is " << pointChildBound << std::endl;

    if (SortPolicy::IsBetter(pointChildBound, childBound))
    {
      // The calculated bound is a tighter bound than the existing child bounds.
      // Update all of the child bounds to this new, tighter bound.
      for (size_t i = 0; i < queryNode.NumChildren(); ++i)
      {
//        Log::Debug << "Update child " << i << " bound from " <<
//            queryNode.Child(i).Stat().Bound() << " to " << pointChildBound <<
//            std::endl;
        if (SortPolicy::IsBetter(pointChildBound,
            queryNode.Child(i).Stat().Bound()))
          queryNode.Child(i).Stat().Bound() = pointChildBound;
//        else
//          Log::Debug << "Did not update child!\n";
      }

      childBound = pointChildBound;
    }
  }

  // Return the worse of the two bounds.
  if (SortPolicy::IsBetter(childBound, pointBound))
    return pointBound;
  else
    return childBound;
}

/**
 * Helper function to insert a point into the neighbors and distances matrices.
 *
 * @param queryIndex Index of point whose neighbors we are inserting into.
 * @param pos Position in list to insert into.
 * @param neighbor Index of reference point which is being inserted.
 * @param distance Distance from query point to reference point.
 */
template<typename SortPolicy, typename MetricType, typename TreeType>
void NeighborSearchRules<SortPolicy, MetricType, TreeType>::InsertNeighbor(
    const size_t queryIndex,
    const size_t pos,
    const size_t neighbor,
    const double distance)
{
  // We only memmove() if there is actually a need to shift something.
  if (pos < (distances.n_rows - 1))
  {
    int len = (distances.n_rows - 1) - pos;
    memmove(distances.colptr(queryIndex) + (pos + 1),
        distances.colptr(queryIndex) + pos,
        sizeof(double) * len);
    memmove(neighbors.colptr(queryIndex) + (pos + 1),
        neighbors.colptr(queryIndex) + pos,
        sizeof(size_t) * len);
  }

  // Now put the new information in the right index.
  distances(pos, queryIndex) = distance;
  neighbors(pos, queryIndex) = neighbor;
}

}; // namespace neighbor
}; // namespace mlpack

#endif // __MLPACK_METHODS_NEIGHBOR_SEARCH_NEAREST_NEIGHBOR_RULES_IMPL_HPP
<|endoftext|>


<commit_before>#ifndef itkGMMKCPointSetToPointSetMetric_hxx
#define itkGMMKCPointSetToPointSetMetric_hxx

#include "itkGMMKCPointSetToPointSetMetric.h"

namespace itk
{
/**
 * Constructor
 */
template <typename TFixedPointSet, typename TMovingPointSet>
GMMKCPointSetToPointSetMetric<TFixedPointSet, TMovingPointSet>::GMMKCPointSetToPointSetMetric()
{
}

/** Initialize the metric */
template< typename TFixedPointSet, typename TMovingPointSet >
void
GMMKCPointSetToPointSetMetric< TFixedPointSet, TMovingPointSet >
::Initialize(void)
throw (ExceptionObject)
{
  Superclass::Initialize();

  m_Gradient1.set_size(m_MovingPointSet->GetNumberOfPoints(), MovingPointSetDimension);
  m_Gradient2.set_size(m_MovingPointSet->GetNumberOfPoints(), MovingPointSetDimension);
}

/**
 * Get the match Measure
 */
template <typename TFixedPointSet, typename TMovingPointSet>
typename GMMKCPointSetToPointSetMetric<TFixedPointSet, TMovingPointSet>::MeasureType
GMMKCPointSetToPointSetMetric<TFixedPointSet, TMovingPointSet>::GetValue(const TransformParametersType & parameters) const
{
  itkExceptionMacro(<< "not implemented");
}
/**
 * Get the Derivative Measure
 */
template <typename TFixedPointSet, typename TMovingPointSet>
void GMMKCPointSetToPointSetMetric<TFixedPointSet, TMovingPointSet>::GetDerivative(const TransformParametersType & parameters, DerivativeType & derivative) const
{
  itkExceptionMacro(<< "not implemented");
}

/*
 * Get both the match Measure and theDerivative Measure
 */
template <typename TFixedPointSet, typename TMovingPointSet>
void GMMKCPointSetToPointSetMetric<TFixedPointSet, TMovingPointSet>::GetValueAndDerivative(const TransformParametersType & parameters, MeasureType & value, DerivativeType  & derivative) const
{
  m_Transform->SetParameters(parameters);

  if (derivative.size() != m_NumberOfParameters) {
    derivative.set_size(m_NumberOfParameters);
  }

  m_TransformedPointSet = MovingPointSetType::New();
  for (MovingPointIterator iter = m_MovingPointSet->GetPoints()->Begin(); iter != m_MovingPointSet->GetPoints()->End(); ++iter) {
    m_TransformedPointSet->SetPoint(iter.Index(), m_Transform->TransformPoint(iter.Value()));
  }

  double value1 = 0;
  double value2 = 0;

  GradientType gradient1;
  GradientType gradient2;

  LocalDerivativeType derivative1(m_NumberOfParameters);
  derivative1.Fill(NumericTraits<typename DerivativeType::ValueType>::ZeroValue());

  LocalDerivativeType derivative2(m_NumberOfParameters);
  derivative2.Fill(NumericTraits<typename DerivativeType::ValueType>::ZeroValue());

  for (MovingPointIterator movingIter1 = m_TransformedPointSet->GetPoints()->Begin(); movingIter1 != m_TransformedPointSet->GetPoints()->End(); ++movingIter1) {
    const typename MovingPointSetType::PointType transformedPoint1 = movingIter1.Value();

    //------------------------------------
    // compute gradient for the first part
    gradient1.Fill(0);

    for (FixedPointIterator fixedIter = m_FixedPointSet->GetPoints()->Begin(); fixedIter != m_FixedPointSet->GetPoints()->End(); ++fixedIter) {
      const typename FixedPointSetType::PointType fixedPoint = fixedIter.Value();

      double distance = 0;
      for (size_t dim = 0; dim < PointDimension; ++dim) {
        distance += pow(transformedPoint1[dim] / m_MovingPointSetScale - fixedPoint[dim] / m_FixedPointSetScale, 2);
      }

      value1 += exp(-distance);

      for (size_t dim = 0; dim < PointDimension; ++dim) {
        gradient1[dim] += (-2.0) * exp(-distance) * (transformedPoint1[dim] / m_MovingPointSetScale - fixedPoint[dim] / m_FixedPointSetScale) / m_MovingPointSetScale;
      }
    }

    //-------------------------------------
    // compute gradient for the second part
    gradient2.Fill(0);

    for (MovingPointIterator movingIter2 = m_TransformedPointSet->GetPoints()->Begin(); movingIter2 != m_TransformedPointSet->GetPoints()->End(); ++movingIter2) {
      const typename MovingPointSetType::PointType transformedPoint2 = movingIter2.Value();

      double distance = 0;
      for (size_t dim = 0; dim < PointDimension; ++dim) {
        distance += pow(transformedPoint1[dim] / m_MovingPointSetScale - transformedPoint2[dim] / m_MovingPointSetScale, 2);
      }

      value2 += exp(-distance);

      for (size_t dim = 0; dim < PointDimension; ++dim) {
        gradient2[dim] += (-2.0) * exp(-distance) * (transformedPoint1[dim] / m_MovingPointSetScale - transformedPoint2[dim] / m_MovingPointSetScale) / m_MovingPointSetScale;
      }
    }

    //-------------------------------------
    // compute derivatives
    m_Transform->ComputeJacobianWithRespectToParametersCachedTemporaries(m_MovingPointSet->GetPoint(movingIter1.Index()), m_Jacobian, m_JacobianCache);

    for (size_t par = 0; par < m_NumberOfParameters; par++) {
      for (size_t dim = 0; dim < PointDimension; dim++) {
        derivative1[par] += m_Jacobian(dim, par) * gradient1[dim];
        derivative2[par] += m_Jacobian(dim, par) * gradient2[dim];
      }
    }
  }

  const double factor = m_MovingPointSet->GetNumberOfPoints() * m_FixedPointSet->GetNumberOfPoints();
  const double ratio = value1 / value2;

  value = -value1 * ratio / factor;

  for (size_t par = 0; par < m_NumberOfParameters; par++) {
    derivative[par] = 2.0 * ratio * (derivative2[par] * ratio - derivative1[par]) / factor;
  }
}
}

#endif
<commit_msg>refactoring<commit_after>#ifndef itkGMMKCPointSetToPointSetMetric_hxx
#define itkGMMKCPointSetToPointSetMetric_hxx

#include "itkGMMKCPointSetToPointSetMetric.h"

namespace itk
{
/**
 * Constructor
 */
template <typename TFixedPointSet, typename TMovingPointSet>
GMMKCPointSetToPointSetMetric<TFixedPointSet, TMovingPointSet>::GMMKCPointSetToPointSetMetric()
{
}

/** Initialize the metric */
template< typename TFixedPointSet, typename TMovingPointSet >
void
GMMKCPointSetToPointSetMetric< TFixedPointSet, TMovingPointSet >
::Initialize(void)
throw (ExceptionObject)
{
  Superclass::Initialize();

  m_Gradient1.set_size(m_MovingPointSet->GetNumberOfPoints(), MovingPointSetDimension);
  m_Gradient2.set_size(m_MovingPointSet->GetNumberOfPoints(), MovingPointSetDimension);
}

/**
 * Get the match Measure
 */
template <typename TFixedPointSet, typename TMovingPointSet>
typename GMMKCPointSetToPointSetMetric<TFixedPointSet, TMovingPointSet>::MeasureType
GMMKCPointSetToPointSetMetric<TFixedPointSet, TMovingPointSet>::GetValue(const TransformParametersType & parameters) const
{
  itkExceptionMacro(<< "not implemented");
}
/**
 * Get the Derivative Measure
 */
template <typename TFixedPointSet, typename TMovingPointSet>
void GMMKCPointSetToPointSetMetric<TFixedPointSet, TMovingPointSet>::GetDerivative(const TransformParametersType & parameters, DerivativeType & derivative) const
{
  itkExceptionMacro(<< "not implemented");
}

/*
 * Get both the match Measure and theDerivative Measure
 */
template <typename TFixedPointSet, typename TMovingPointSet>
void GMMKCPointSetToPointSetMetric<TFixedPointSet, TMovingPointSet>::GetValueAndDerivative(const TransformParametersType & parameters, MeasureType & value, DerivativeType  & derivative) const
{
  m_Transform->SetParameters(parameters);

  if (derivative.size() != m_NumberOfParameters) {
    derivative.set_size(m_NumberOfParameters);
  }

  m_TransformedPointSet = MovingPointSetType::New();
  for (MovingPointIterator iter = m_MovingPointSet->GetPoints()->Begin(); iter != m_MovingPointSet->GetPoints()->End(); ++iter) {
    m_TransformedPointSet->SetPoint(iter.Index(), m_Transform->TransformPoint(iter.Value()));
  }

  double value1 = 0;
  double value2 = 0;

  GradientType gradient1;
  GradientType gradient2;

  LocalDerivativeType derivative1(m_NumberOfParameters);
  derivative1.Fill(NumericTraits<typename DerivativeType::ValueType>::ZeroValue());

  LocalDerivativeType derivative2(m_NumberOfParameters);
  derivative2.Fill(NumericTraits<typename DerivativeType::ValueType>::ZeroValue());

  for (MovingPointIterator movingIter1 = m_TransformedPointSet->GetPoints()->Begin(); movingIter1 != m_TransformedPointSet->GetPoints()->End(); ++movingIter1) {
    const typename MovingPointSetType::PointType transformedPoint1 = movingIter1.Value();

    //------------------------------------
    // compute gradient for the first part
    gradient1.Fill(0);

    for (FixedPointIterator fixedIter = m_FixedPointSet->GetPoints()->Begin(); fixedIter != m_FixedPointSet->GetPoints()->End(); ++fixedIter) {
      const typename FixedPointSetType::PointType fixedPoint = fixedIter.Value();

      double distance = 0;
      for (size_t dim = 0; dim < PointDimension; ++dim) {
        distance += pow(transformedPoint1[dim] / m_MovingPointSetScale - fixedPoint[dim] / m_FixedPointSetScale, 2);
      }

      value1 += exp(-distance);

      for (size_t dim = 0; dim < PointDimension; ++dim) {
        gradient1[dim] += (-2.0) * exp(-distance) * (transformedPoint1[dim] / m_MovingPointSetScale - fixedPoint[dim] / m_FixedPointSetScale) / m_MovingPointSetScale;
      }
    }

    //-------------------------------------
    // compute gradient for the second part
    gradient2.Fill(0);

    for (MovingPointIterator movingIter2 = m_TransformedPointSet->GetPoints()->Begin(); movingIter2 != m_TransformedPointSet->GetPoints()->End(); ++movingIter2) {
      const typename MovingPointSetType::PointType transformedPoint2 = movingIter2.Value();

      double distance = 0;
      for (size_t dim = 0; dim < PointDimension; ++dim) {
        distance += pow(transformedPoint1[dim] / m_MovingPointSetScale - transformedPoint2[dim] / m_MovingPointSetScale, 2);
      }

      value2 += exp(-distance);

      for (size_t dim = 0; dim < PointDimension; ++dim) {
        gradient2[dim] += (-2.0) * exp(-distance) * (transformedPoint1[dim] / m_MovingPointSetScale - transformedPoint2[dim] / m_MovingPointSetScale) / m_MovingPointSetScale;
      }
    }

    //-------------------------------------
    // compute derivatives
    m_Transform->ComputeJacobianWithRespectToParametersCachedTemporaries(m_MovingPointSet->GetPoint(movingIter1.Index()), m_Jacobian, m_JacobianCache);

    for (size_t par = 0; par < m_NumberOfParameters; par++) {
      for (size_t dim = 0; dim < PointDimension; dim++) {
        derivative1[par] += m_Jacobian(dim, par) * gradient1[dim];
        derivative2[par] += m_Jacobian(dim, par) * gradient2[dim];
      }
    }
  }

  const double factor = m_MovingPointSet->GetNumberOfPoints() * m_FixedPointSet->GetNumberOfPoints();
  const double ratio = value1 / value2;

  value = -value1 * ratio / factor;

  for (size_t par = 0; par < m_NumberOfParameters; par++) {
    derivative[par] = (-2.0) * (derivative1[par] - derivative2[par] * ratio) * ratio / factor;
  }
}
}

#endif
<|endoftext|>


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

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you under
the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

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

//==============================================================================
// BioSignalML data store exporter class
//==============================================================================

#include "bsmldatastoreexporter.h"
#include "biosignalml/biosignalml.h"
#include "biosignalml/data/hdf5.h"

//==============================================================================

#include "corecliutils.h"

//==============================================================================

#include <QApplication>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QUrl>

//==============================================================================

namespace OpenCOR {
namespace BSMLDataStore {

//==============================================================================

BioSignalMLExporter::BioSignalMLExporter(QMainWindow *pMainWindow, const QString &pId) :
    DataStore::DataStoreExporter(pId),
    mSaveDialog(new BioSignalMLSaveDialog(pMainWindow))
{
}

//==============================================================================

void BioSignalMLExporter::execute(DataStore::DataStore *pDataStore) const
{
    // Export the given data store to a BioSignalML file

    QString comment = "Generated by " + Core::version(qApp)
                    + " at " + QDateTime::currentDateTimeUtc().toString(Qt::ISODate)
                    + " from " + pDataStore->uri();

    mSaveDialog->setComment(comment);
    if (mSaveDialog->run()) {

        QString fileName = mSaveDialog->fileName();
        std::string rec_uri = QUrl::fromLocalFile(fileName).toString().toStdString();
        std::string base_units = pDataStore->uri().toStdString() + "/units#";

        bsml::HDF5::Recording *recording = nullptr;
        try {
            recording = new bsml::HDF5::Recording(rec_uri, fileName.toStdString(), true);
            recording->set_comment(comment.toStdString());
            recording->set_label(mSaveDialog->shortName().toStdString()) ;
            recording->set_description(mSaveDialog->description().toStdString()) ;
            recording->set_investigator(rdf::Literal(mSaveDialog->author().toStdString())) ;

            recording->add_prefix(rdf::Namespace("units", base_units)) ;

            DataStore::DataStoreVariable *voi = pDataStore->voi();
            auto clock = recording->new_clock(voi->uri().toStdString(),
                                              rdf::URI(base_units + voi->unit().toStdString()),
                                              voi->values(), voi->size());
            clock->set_label(voi->label().toStdString()) ;

            DataStore::DataStoreVariables variables = pDataStore->variables();
            auto variableBegin = variables.constBegin();
            auto variableEnd = variables.constEnd();

            std::vector<const std::string> uris;
            std::vector<const rdf::URI> units;
            for (auto variable = variableBegin; variable != variableEnd; ++variable) {
                uris.push_back((*variable)->uri().toStdString());
                units.push_back(rdf::URI(base_units + (*variable)->unit().toStdString()));
            }

            auto sigs = recording->new_signalarray(uris, units, clock) ;
            size_t nvars = variables.size();
            for (size_t i = 0 ;  i < nvars ;  ++i) {
                (*sigs)[i]->set_label(variables[i]->label().toStdString()) ;
            }

#define BUFFER_ROWS 50000
            double *data = new double[BUFFER_ROWS*nvars];
            double *dp = data;
            int rowcount = 0;

            for (qulonglong i = 0; i < pDataStore->size(); ++i) {
                for (auto variable = variableBegin; variable != variableEnd; ++variable)
                    *dp++ = (*variable)->value(i);
                ++rowcount;
                if (rowcount >= BUFFER_ROWS) {
                    sigs->extend(data, BUFFER_ROWS*nvars);
                    dp = data;
                    rowcount = 0;
                }

                qApp->processEvents();
//---GRY--- THE CALL TO qApp->processEvents() SHOULD BE REMOVED AND THE EXPORTER
//              BE SUCH THAT IT DOESN'T BLOCK THE MAIN THREAD (E.G. WHEN EXPORTING
//              LONG SIMULATIONS). MAYBE THIS COULD BE DONE BY MAKING THE EXPORTER
//              WORK IN ITS OWN THREAD?...
            }

            sigs->extend(data, rowcount*nvars);

            delete[] data;
        }

        catch (bsml::data::Exception e) {
            std::cerr << "EXCEPTION: " << e.what() << std::endl;
                                        // **** Need to bring up alert....
        }

        if (recording != nullptr) {
            recording->close();
            delete recording;
        }

    }

}

//==============================================================================

}   // namespace BSMLDataStore
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Use full URIs for signals.<commit_after>/*******************************************************************************

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you under
the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

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

//==============================================================================
// BioSignalML data store exporter class
//==============================================================================

#include "bsmldatastoreexporter.h"
#include "biosignalml/biosignalml.h"
#include "biosignalml/data/hdf5.h"

//==============================================================================

#include "corecliutils.h"

//==============================================================================

#include <QApplication>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QUrl>

//==============================================================================

namespace OpenCOR {
namespace BSMLDataStore {

//==============================================================================

BioSignalMLExporter::BioSignalMLExporter(QMainWindow *pMainWindow, const QString &pId) :
    DataStore::DataStoreExporter(pId),
    mSaveDialog(new BioSignalMLSaveDialog(pMainWindow))
{
}

//==============================================================================

void BioSignalMLExporter::execute(DataStore::DataStore *pDataStore) const
{
    // Export the given data store to a BioSignalML file

    QString comment = "Generated by " + Core::version(qApp)
                    + " at " + QDateTime::currentDateTimeUtc().toString(Qt::ISODate)
                    + " from " + pDataStore->uri();

    mSaveDialog->setComment(comment);
    if (mSaveDialog->run()) {

        QString fileName = mSaveDialog->fileName();
        std::string rec_uri = QUrl::fromLocalFile(fileName).toString().toStdString();
        std::string base_units = pDataStore->uri().toStdString() + "/units#";

        bsml::HDF5::Recording *recording = nullptr;
        try {
            recording = new bsml::HDF5::Recording(rec_uri, fileName.toStdString(), true);
            recording->set_comment(comment.toStdString());
            recording->set_label(mSaveDialog->shortName().toStdString()) ;
            recording->set_description(mSaveDialog->description().toStdString()) ;
            recording->set_investigator(rdf::Literal(mSaveDialog->author().toStdString())) ;

            recording->add_prefix(rdf::Namespace("units", base_units)) ;

            DataStore::DataStoreVariable *voi = pDataStore->voi();
            auto clock = recording->new_clock(voi->uri().toStdString(),
                                              rdf::URI(base_units + voi->unit().toStdString()),
                                              voi->values(), voi->size());
            clock->set_label(voi->label().toStdString()) ;

            DataStore::DataStoreVariables variables = pDataStore->variables();
            auto variableBegin = variables.constBegin();
            auto variableEnd = variables.constEnd();

            std::vector<const std::string> uris;
            std::vector<const rdf::URI> units;
            for (auto variable = variableBegin; variable != variableEnd; ++variable) {
                uris.push_back(rec_uri + "/signal/" + (*variable)->uri().toStdString());
                units.push_back(rdf::URI(base_units + (*variable)->unit().toStdString()));
            }

            auto sigs = recording->new_signalarray(uris, units, clock) ;
            size_t nvars = variables.size();
            for (size_t i = 0 ;  i < nvars ;  ++i) {
                (*sigs)[i]->set_label(variables[i]->label().toStdString()) ;
            }

#define BUFFER_ROWS 50000
            double *data = new double[BUFFER_ROWS*nvars];
            double *dp = data;
            int rowcount = 0;

            for (qulonglong i = 0; i < pDataStore->size(); ++i) {
                for (auto variable = variableBegin; variable != variableEnd; ++variable)
                    *dp++ = (*variable)->value(i);
                ++rowcount;
                if (rowcount >= BUFFER_ROWS) {
                    sigs->extend(data, BUFFER_ROWS*nvars);
                    dp = data;
                    rowcount = 0;
                }

                qApp->processEvents();
//---GRY--- THE CALL TO qApp->processEvents() SHOULD BE REMOVED AND THE EXPORTER
//              BE SUCH THAT IT DOESN'T BLOCK THE MAIN THREAD (E.G. WHEN EXPORTING
//              LONG SIMULATIONS). MAYBE THIS COULD BE DONE BY MAKING THE EXPORTER
//              WORK IN ITS OWN THREAD?...
            }

            sigs->extend(data, rowcount*nvars);

            delete[] data;
        }

        catch (bsml::data::Exception e) {
            std::cerr << "EXCEPTION: " << e.what() << std::endl;
                                        // **** Need to bring up alert....
        }

        if (recording != nullptr) {
            recording->close();
            delete recording;
        }

    }

}

//==============================================================================

}   // namespace BSMLDataStore
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


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

// ospcommon, which we use for a vector class
#include "pbrtParser/Scene.h"
// stl
#include <iostream>
#include <vector>
#include <sstream>
#include <set>

namespace pbrt {
  namespace semantic {

    using std::cout;
    using std::endl;

    bool endsWith(const std::string &s, const std::string &suffix)
    {
      return s.substr(s.size()-suffix.size(),suffix.size()) == suffix;
    }

    struct PBRTInfo {
      PBRTInfo(Scene::SP scene)
      {
        traverse(scene->world);
        numObjects.print("objects");
        numAreaLights.print("areaLights");
        numShapes.print("shapes");
        numTriangles.print("triangles");
        numQuads.print("quads");
        numDisks.print("disks");
        numSpheres.print("spheres");
        numCurves.print("curves");
        numCurveSegments.print("curve segments");
        numLights.print("lights");
        std::cout << "total num materials " << usedMaterials.size() << std::endl;
        for (auto mat : usedMaterials)
          std::cout << " - " << (mat ? mat->name : "<invalid material>") << std::endl;
        std::cout << "scene bounds " << scene->getBounds() << std::endl;
      }

      void traverse(Object::SP object)
      {
        const bool firstTime = (alreadyTraversed.find(object) == alreadyTraversed.end());
        alreadyTraversed.insert(object);

        numObjects.add(firstTime,1);
        // numLights.add(firstTime,object->lightSources.size());
        // numVolumes.add(firstTime,object->volumes.size());
        numShapes.add(firstTime,object->shapes.size());

        for (auto shape : object->shapes) {
          usedMaterials.insert(shape->material);
          if (shape->areaLight)
            numAreaLights.add(firstTime,1);
          if (TriangleMesh::SP mesh=std::dynamic_pointer_cast<TriangleMesh>(shape)){
            numTriangles.add(firstTime,mesh->index.size());
          } else if (QuadMesh::SP mesh=std::dynamic_pointer_cast<QuadMesh>(shape)){
            numQuads.add(firstTime,mesh->index.size());
          } else if (Sphere::SP sphere=std::dynamic_pointer_cast<Sphere>(shape)){
            numSpheres.add(firstTime,1);
          } else if (Disk::SP disk=std::dynamic_pointer_cast<Disk>(shape)){
            numDisks.add(firstTime,1);
          } else if (Curve::SP curves=std::dynamic_pointer_cast<Curve>(shape)){
            numCurves.add(firstTime,1);
          } else
            std::cout << "un-handled geometry type : " << shape->toString() << std::endl;
        }

        numInstances.add(firstTime,object->instances.size());
        for (auto inst : object->instances) {
          traverse(inst->object);
        }
      }

      struct Counter
      {
        void print(const std::string &name)
        {
          std::cout << "number of " << name << std::endl;
          std::cout << " - unique    : " << math::prettyNumber(unique) << std::endl;
          std::cout << " - instanced : " << math::prettyNumber(instanced) << std::endl;
        }
        void add(bool firstTime, size_t N) { instanced += N; if (firstTime) unique += N; }

        size_t unique = 0;
        size_t instanced = 0;
      };

      Counter numInstances;
      Counter numTriangles;
      Counter numQuads;
      Counter numSpheres;
      Counter numDisks;
      Counter numObjects;
      Counter numAreaLights;
      Counter numVertices;
      Counter numCurves;
      Counter numCurveSegments;
      Counter numShapes;
      Counter numLights;
      Counter numVolumes;

      std::set<Object::SP> alreadyTraversed;
      std::set<Material::SP> usedMaterials;
    };

    void pbrtInfo(int ac, char **av)
    {
      std::string fileName;
      bool parseOnly = false;
      for (int i=1;i<ac;i++) {
        const std::string arg = av[i];
        if (arg == "--lint" || arg == "-lint") {
          parseOnly = true;
        } else if (arg[0] == '-') {
          throw std::runtime_error("invalid argument '"+arg+"'");
        } else {
          fileName = arg;
        }
      }

      std::cout << "-------------------------------------------------------" << std::endl;
      std::cout << "pbrtinfo - printing info on pbrt file ..." << std::endl;
      std::cout << "-------------------------------------------------------" << std::endl;

      std::shared_ptr<Scene> scene;
      try {
        if (endsWith(fileName,".pbrt"))
          scene = importPBRT(fileName);
        else if (endsWith(fileName,".pbf"))
          scene = Scene::loadFrom(fileName);
        else
          throw std::runtime_error("un-recognized input file extension");

        std::cout << " => yay! parsing successful..." << std::endl;
        if (parseOnly) exit(0);
        PBRTInfo info(scene);
      } catch (std::runtime_error e) {
        std::cerr << "**** ERROR IN PARSING ****" << std::endl << e.what() << std::endl;
        std::cerr << "(this means that either there's something wrong with that PBRT file, or that the parser can't handle it)" << std::endl;
        exit(1);
      }
    }

    extern "C" int main(int ac, char **av)
    {
      pbrtInfo(ac,av);
      return 0;
    }

  } // ::pbrt::semantic
} // ::pbrt
<commit_msg>fixed null material outputs in pbrtInfo<commit_after>// ======================================================================== //
// Copyright 2015-2019 Ingo Wald                                            //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

// ospcommon, which we use for a vector class
#include "pbrtParser/Scene.h"
// stl
#include <iostream>
#include <vector>
#include <sstream>
#include <set>

namespace pbrt {
  namespace semantic {

    using std::cout;
    using std::endl;

    bool endsWith(const std::string &s, const std::string &suffix)
    {
      return s.substr(s.size()-suffix.size(),suffix.size()) == suffix;
    }

    struct PBRTInfo {
      PBRTInfo(Scene::SP scene)
      {
        traverse(scene->world);
        numObjects.print("objects");
        numAreaLights.print("areaLights");
        numShapes.print("shapes");
        numTriangles.print("triangles");
        numQuads.print("quads");
        numDisks.print("disks");
        numSpheres.print("spheres");
        numCurves.print("curves");
        numCurveSegments.print("curve segments");
        numLights.print("lights");
        std::cout << "total num materials " << usedMaterials.size() << std::endl;
        for (auto mat : usedMaterials)
          std::cout << " - " << (mat ? mat->name : "<null material> (ie, shape w/o material - possibly light source)") << std::endl;
        std::cout << "scene bounds " << scene->getBounds() << std::endl;
      }

      void traverse(Object::SP object)
      {
        const bool firstTime = (alreadyTraversed.find(object) == alreadyTraversed.end());
        alreadyTraversed.insert(object);

        numObjects.add(firstTime,1);
        // numLights.add(firstTime,object->lightSources.size());
        // numVolumes.add(firstTime,object->volumes.size());
        numShapes.add(firstTime,object->shapes.size());

        for (auto shape : object->shapes) {
          usedMaterials.insert(shape->material);
          if (shape->areaLight)
            numAreaLights.add(firstTime,1);
          if (TriangleMesh::SP mesh=std::dynamic_pointer_cast<TriangleMesh>(shape)){
            numTriangles.add(firstTime,mesh->index.size());
          } else if (QuadMesh::SP mesh=std::dynamic_pointer_cast<QuadMesh>(shape)){
            numQuads.add(firstTime,mesh->index.size());
          } else if (Sphere::SP sphere=std::dynamic_pointer_cast<Sphere>(shape)){
            numSpheres.add(firstTime,1);
          } else if (Disk::SP disk=std::dynamic_pointer_cast<Disk>(shape)){
            numDisks.add(firstTime,1);
          } else if (Curve::SP curves=std::dynamic_pointer_cast<Curve>(shape)){
            numCurves.add(firstTime,1);
          } else
            std::cout << "un-handled geometry type : " << shape->toString() << std::endl;
        }

        numInstances.add(firstTime,object->instances.size());
        for (auto inst : object->instances) {
          traverse(inst->object);
        }
      }

      struct Counter
      {
        void print(const std::string &name)
        {
          std::cout << "number of " << name << std::endl;
          std::cout << " - unique    : " << math::prettyNumber(unique) << std::endl;
          std::cout << " - instanced : " << math::prettyNumber(instanced) << std::endl;
        }
        void add(bool firstTime, size_t N) { instanced += N; if (firstTime) unique += N; }

        size_t unique = 0;
        size_t instanced = 0;
      };

      Counter numInstances;
      Counter numTriangles;
      Counter numQuads;
      Counter numSpheres;
      Counter numDisks;
      Counter numObjects;
      Counter numAreaLights;
      Counter numVertices;
      Counter numCurves;
      Counter numCurveSegments;
      Counter numShapes;
      Counter numLights;
      Counter numVolumes;

      std::set<Object::SP> alreadyTraversed;
      std::set<Material::SP> usedMaterials;
    };

    void pbrtInfo(int ac, char **av)
    {
      std::string fileName;
      bool parseOnly = false;
      for (int i=1;i<ac;i++) {
        const std::string arg = av[i];
        if (arg == "--lint" || arg == "-lint") {
          parseOnly = true;
        } else if (arg[0] == '-') {
          throw std::runtime_error("invalid argument '"+arg+"'");
        } else {
          fileName = arg;
        }
      }

      std::cout << "-------------------------------------------------------" << std::endl;
      std::cout << "pbrtinfo - printing info on pbrt file ..." << std::endl;
      std::cout << "-------------------------------------------------------" << std::endl;

      std::shared_ptr<Scene> scene;
      try {
        if (endsWith(fileName,".pbrt"))
          scene = importPBRT(fileName);
        else if (endsWith(fileName,".pbf"))
          scene = Scene::loadFrom(fileName);
        else
          throw std::runtime_error("un-recognized input file extension");

        std::cout << " => yay! parsing successful..." << std::endl;
        if (parseOnly) exit(0);
        PBRTInfo info(scene);
      } catch (std::runtime_error e) {
        std::cerr << "**** ERROR IN PARSING ****" << std::endl << e.what() << std::endl;
        std::cerr << "(this means that either there's something wrong with that PBRT file, or that the parser can't handle it)" << std::endl;
        exit(1);
      }
    }

    extern "C" int main(int ac, char **av)
    {
      pbrtInfo(ac,av);
      return 0;
    }

  } // ::pbrt::semantic
} // ::pbrt
<|endoftext|>