<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF 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.
 */

#include "ActiveMQConnectionTest.h"

#include <decaf/util/concurrent/Concurrent.h>
#include <decaf/util/concurrent/Mutex.h>
#include <decaf/lang/Thread.h>
#include <decaf/util/Properties.h>
#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/transport/mock/MockTransport.h>
#include <activemq/core/ActiveMQConnection.h>
#include <activemq/core/ActiveMQConnectionData.h>
#include <activemq/connector/stomp/StompConnector.h>
#include <activemq/connector/openwire/OpenWireConnector.h>
#include <activemq/transport/mock/MockTransportFactory.h>
#include <activemq/transport/TransportRegistry.h>
#include <activemq/connector/stomp/StompConsumerInfo.h>
#include <activemq/connector/stomp/StompProducerInfo.h>
#include <activemq/connector/stomp/StompTransactionInfo.h>
#include <activemq/connector/stomp/StompSessionInfo.h>
#include <activemq/connector/stomp/StompTopic.h>
#include <activemq/connector/stomp/commands/TextMessageCommand.h>
#include <activemq/util/Config.h>

using namespace activemq;
using namespace activemq::core;
using namespace decaf;
using namespace decaf::util;

////////////////////////////////////////////////////////////////////////////////
void ActiveMQConnectionTest::test1WithStomp()
{
    try
    {
        MyMessageListener listener;
        MyExceptionListener exListener;
        MyCommandListener cmdListener;
        MyDispatcher msgListener;
        std::string connectionId = "testConnectionId";
        decaf::util::Properties* properties =
            new decaf::util::Properties();
        transport::Transport* transport = NULL;

        // Default to Stomp
        properties->setProperty( "wireFormat", "stomp" );
        decaf::net::URI uri( "mock://mock?wireFormat=stomp" );

        transport::TransportFactory* factory =
            transport::TransportRegistry::getInstance().findFactory( "mock" );
        if( factory == NULL ){
            CPPUNIT_ASSERT( false );
        }

        // Create the transport.
        transport = factory->create( uri );
        if( transport == NULL ){
            CPPUNIT_ASSERT( false );
        }

        transport::mock::MockTransport* dTransport =
            dynamic_cast< transport::mock::MockTransport*>( transport );

        CPPUNIT_ASSERT( dTransport != NULL );

        dTransport->setCommandListener( &cmdListener );

        connector::stomp::StompConnector* connector =
            new connector::stomp::StompConnector(
                transport, *properties );

        connector->start();

        ActiveMQConnection connection(
            new ActiveMQConnectionData(
                connector, transport, properties) );

        // First - make sure exceptions are working.
        connection.setExceptionListener( &exListener );
        CPPUNIT_ASSERT( exListener.caughtOne == false );
        dTransport->fireException( exceptions::ActiveMQException( __FILE__, __LINE__, "test" ) );
        CPPUNIT_ASSERT( exListener.caughtOne == true );

        cms::Session* session1 = connection.createSession();
        cms::Session* session2 = connection.createSession();
        cms::Session* session3 = connection.createSession();

        CPPUNIT_ASSERT( session1 != NULL );
        CPPUNIT_ASSERT( session2 != NULL );
        CPPUNIT_ASSERT( session3 != NULL );

        connector::stomp::StompSessionInfo session;
        connector::stomp::StompConsumerInfo consumer;

        session.setSessionId( 1 );
        session.setConnectionId( "TEST:123" );
        session.setAckMode( cms::Session::AUTO_ACKNOWLEDGE );

        connector::stomp::StompTopic myTopic( "test" );
        consumer.setConsumerId( 1 );
        consumer.setSessionInfo( &session );
        consumer.setDestination( &myTopic );

        connection.addDispatcher( &consumer, &msgListener );

        connector::stomp::commands::TextMessageCommand* cmd =
            new connector::stomp::commands::TextMessageCommand;
        connector::stomp::StompTopic topic1( "test" );
        cmd->setCMSDestination( &topic1 );

        connector::ConsumerMessageListener* consumerListener =
            dynamic_cast< connector::ConsumerMessageListener* >(
                &connection );

        connection.start();

        CPPUNIT_ASSERT( consumerListener != NULL );

        consumerListener->onConsumerMessage( &consumer, cmd );

        CPPUNIT_ASSERT_EQUAL( 1, (int)msgListener.messages.size() );

        connection.removeDispatcher( &consumer );

        msgListener.messages.clear();
        consumerListener->onConsumerMessage( &consumer, cmd );

        CPPUNIT_ASSERT_EQUAL( 0, (int)msgListener.messages.size() );

        connection.addDispatcher( &consumer, &msgListener );

        connection.stop();
        consumerListener->onConsumerMessage( &consumer, cmd );
        connection.start();
        CPPUNIT_ASSERT_EQUAL( 1, (int)msgListener.messages.size() );

        delete cmd;
        cmd = new connector::stomp::commands::TextMessageCommand;

        connector::stomp::StompTopic topic2( "test" );
        cmd->setCMSDestination( &topic2 );

        consumerListener->onConsumerMessage( &consumer, cmd );
        CPPUNIT_ASSERT_EQUAL( 2, (int)msgListener.messages.size() );

        connection.removeDispatcher( &consumer );
        msgListener.messages.clear();

        session1->close();
        session2->close();
        session3->close();
        connection.close();

        exListener.caughtOne = false;
        consumerListener->onConsumerMessage( &consumer, cmd );
        CPPUNIT_ASSERT( exListener.caughtOne == true );

        delete cmd;

        delete session1;
        delete session2;
        delete session3;

    } catch( exceptions::ActiveMQException& ex ) {
        ex.printStackTrace();
        throw ex;
    }
}

////////////////////////////////////////////////////////////////////////////////
void ActiveMQConnectionTest::test2WithStomp()
{
    try
    {
        MyMessageListener listener;
        MyExceptionListener exListener;
        MyCommandListener cmdListener;
        MyDispatcher msgListener;
        std::string connectionId = "testConnectionId";
        decaf::util::Properties* properties =
            new decaf::util::Properties();
        transport::Transport* transport = NULL;

        // Default to Stomp
        properties->setProperty( "wireFormat", "stomp" );
        decaf::net::URI uri( "mock://mock?wireFormat=stomp" );

        transport::TransportFactory* factory =
            transport::TransportRegistry::getInstance().findFactory( "mock" );
        if( factory == NULL ){
            CPPUNIT_ASSERT( false );
        }

        // Create the transport.
        transport = factory->create( uri );
        if( transport == NULL ){
            CPPUNIT_ASSERT( false );
        }

        transport::mock::MockTransport* dTransport =
            dynamic_cast< transport::mock::MockTransport*>( transport );

        CPPUNIT_ASSERT( dTransport != NULL );

        dTransport->setCommandListener( &cmdListener );

        connector::stomp::StompConnector* connector =
            new connector::stomp::StompConnector(
                transport, *properties );

        connector->start();

        ActiveMQConnection connection(
            new ActiveMQConnectionData(
                connector, transport, properties) );

        connection.getClientID();
        connection.close();

        CPPUNIT_ASSERT( connection.getClientID() == "" );

    } catch( exceptions::ActiveMQException& ex ) {
        ex.printStackTrace();
        throw ex;
    }
}

////////////////////////////////////////////////////////////////////////////////
void ActiveMQConnectionTest::test2WithOpenwire()
{
    try
    {
        MyMessageListener listener;
        MyExceptionListener exListener;
        MyCommandListener cmdListener;
        MyDispatcher msgListener;
        std::string connectionId = "testConnectionId";
        decaf::util::Properties* properties =
            new decaf::util::Properties();
        transport::Transport* transport = NULL;

        // Default to Stomp
        properties->setProperty( "wireFormat", "openwire" );
        decaf::net::URI uri( "mock://mock?wireFormat=stomp" );

        transport::TransportFactory* factory =
            transport::TransportRegistry::getInstance().findFactory( "mock" );
        if( factory == NULL ){
            CPPUNIT_ASSERT( false );
        }

        // Create the transport.
        transport = factory->create( uri );
        if( transport == NULL ){
            CPPUNIT_ASSERT( false );
        }

        transport::mock::MockTransport* dTransport =
            dynamic_cast< transport::mock::MockTransport*>( transport );

        CPPUNIT_ASSERT( dTransport != NULL );

        dTransport->setCommandListener( &cmdListener );

        connector::Connector* connector =
            new connector::openwire::OpenWireConnector(
                transport, *properties );

        connector->start();

        ActiveMQConnection connection(
            new ActiveMQConnectionData(
                connector, transport, properties) );

        connection.getClientID();
        connection.close();

        CPPUNIT_ASSERT( connection.getClientID() == "" );

    } catch( exceptions::ActiveMQException& ex ) {
        ex.printStackTrace();
        throw ex;
    }
}
<commit_msg>https://issues.apache.org/activemq/browse/AMQCPP-100<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF 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.
 */

#include "ActiveMQConnectionTest.h"

#include <decaf/util/concurrent/Concurrent.h>
#include <decaf/util/concurrent/Mutex.h>
#include <decaf/lang/Thread.h>
#include <decaf/util/Properties.h>
#include <activemq/core/ActiveMQConnectionFactory.h>
#include <activemq/transport/mock/MockTransport.h>
#include <activemq/core/ActiveMQConnection.h>
#include <activemq/core/ActiveMQConnectionData.h>
#include <activemq/connector/stomp/StompConnector.h>
#include <activemq/connector/openwire/OpenWireConnector.h>
#include <activemq/transport/mock/MockTransportFactory.h>
#include <activemq/transport/TransportRegistry.h>
#include <activemq/connector/stomp/StompConsumerInfo.h>
#include <activemq/connector/stomp/StompProducerInfo.h>
#include <activemq/connector/stomp/StompTransactionInfo.h>
#include <activemq/connector/stomp/StompSessionInfo.h>
#include <activemq/connector/stomp/StompTopic.h>
#include <activemq/connector/stomp/commands/TextMessageCommand.h>
#include <activemq/util/Config.h>

using namespace activemq;
using namespace activemq::core;
using namespace decaf;
using namespace decaf::util;

////////////////////////////////////////////////////////////////////////////////
void ActiveMQConnectionTest::test1WithStomp()
{
    try
    {
        MyMessageListener listener;
        MyExceptionListener exListener;
        MyCommandListener cmdListener;
        MyDispatcher msgListener;
        std::string connectionId = "testConnectionId";
        decaf::util::Properties* properties =
            new decaf::util::Properties();
        transport::Transport* transport = NULL;

        // Default to Stomp
        properties->setProperty( "wireFormat", "stomp" );
        decaf::net::URI uri( "mock://mock?wireFormat=stomp" );

        transport::TransportFactory* factory =
            transport::TransportRegistry::getInstance().findFactory( "mock" );
        if( factory == NULL ){
            CPPUNIT_ASSERT( false );
        }

        // Create the transport.
        transport = factory->createComposite( uri );
        if( transport == NULL ){
            CPPUNIT_ASSERT( false );
        }

        transport::mock::MockTransport* dTransport =
            dynamic_cast< transport::mock::MockTransport*>( transport );

        CPPUNIT_ASSERT( dTransport != NULL );

        dTransport->setCommandListener( &cmdListener );

        connector::stomp::StompConnector* connector =
            new connector::stomp::StompConnector(
                transport, *properties );

        connector->start();

        ActiveMQConnection connection(
            new ActiveMQConnectionData(
                connector, transport, properties) );

        // First - make sure exceptions are working.
        connection.setExceptionListener( &exListener );
        CPPUNIT_ASSERT( exListener.caughtOne == false );
        dTransport->fireException( exceptions::ActiveMQException( __FILE__, __LINE__, "test" ) );
        CPPUNIT_ASSERT( exListener.caughtOne == true );

        cms::Session* session1 = connection.createSession();
        cms::Session* session2 = connection.createSession();
        cms::Session* session3 = connection.createSession();

        CPPUNIT_ASSERT( session1 != NULL );
        CPPUNIT_ASSERT( session2 != NULL );
        CPPUNIT_ASSERT( session3 != NULL );

        connector::stomp::StompSessionInfo session;
        connector::stomp::StompConsumerInfo consumer;

        session.setSessionId( 1 );
        session.setConnectionId( "TEST:123" );
        session.setAckMode( cms::Session::AUTO_ACKNOWLEDGE );

        connector::stomp::StompTopic myTopic( "test" );
        consumer.setConsumerId( 1 );
        consumer.setSessionInfo( &session );
        consumer.setDestination( &myTopic );

        connection.addDispatcher( &consumer, &msgListener );

        connector::stomp::commands::TextMessageCommand* cmd =
            new connector::stomp::commands::TextMessageCommand;
        connector::stomp::StompTopic topic1( "test" );
        cmd->setCMSDestination( &topic1 );

        connector::ConsumerMessageListener* consumerListener =
            dynamic_cast< connector::ConsumerMessageListener* >(
                &connection );

        connection.start();

        CPPUNIT_ASSERT( consumerListener != NULL );

        consumerListener->onConsumerMessage( &consumer, cmd );

        CPPUNIT_ASSERT_EQUAL( 1, (int)msgListener.messages.size() );

        connection.removeDispatcher( &consumer );

        msgListener.messages.clear();
        consumerListener->onConsumerMessage( &consumer, cmd );

        CPPUNIT_ASSERT_EQUAL( 0, (int)msgListener.messages.size() );

        connection.addDispatcher( &consumer, &msgListener );

        connection.stop();
        consumerListener->onConsumerMessage( &consumer, cmd );
        connection.start();
        CPPUNIT_ASSERT_EQUAL( 1, (int)msgListener.messages.size() );

        delete cmd;
        cmd = new connector::stomp::commands::TextMessageCommand;

        connector::stomp::StompTopic topic2( "test" );
        cmd->setCMSDestination( &topic2 );

        consumerListener->onConsumerMessage( &consumer, cmd );
        CPPUNIT_ASSERT_EQUAL( 2, (int)msgListener.messages.size() );

        connection.removeDispatcher( &consumer );
        msgListener.messages.clear();

        session1->close();
        session2->close();
        session3->close();
        connection.close();

        exListener.caughtOne = false;
        consumerListener->onConsumerMessage( &consumer, cmd );
        CPPUNIT_ASSERT( exListener.caughtOne == true );

        delete cmd;

        delete session1;
        delete session2;
        delete session3;

    } catch( exceptions::ActiveMQException& ex ) {
        ex.printStackTrace();
        throw ex;
    }
}

////////////////////////////////////////////////////////////////////////////////
void ActiveMQConnectionTest::test2WithStomp()
{
    try
    {
        MyMessageListener listener;
        MyExceptionListener exListener;
        MyCommandListener cmdListener;
        MyDispatcher msgListener;
        std::string connectionId = "testConnectionId";
        decaf::util::Properties* properties =
            new decaf::util::Properties();
        transport::Transport* transport = NULL;

        // Default to Stomp
        properties->setProperty( "wireFormat", "stomp" );
        decaf::net::URI uri( "mock://mock?wireFormat=stomp" );

        transport::TransportFactory* factory =
            transport::TransportRegistry::getInstance().findFactory( "mock" );
        if( factory == NULL ){
            CPPUNIT_ASSERT( false );
        }

        // Create the transport.
        transport = factory->createComposite( uri );
        if( transport == NULL ){
            CPPUNIT_ASSERT( false );
        }

        transport::mock::MockTransport* dTransport =
            dynamic_cast< transport::mock::MockTransport*>( transport );

        CPPUNIT_ASSERT( dTransport != NULL );

        dTransport->setCommandListener( &cmdListener );

        connector::stomp::StompConnector* connector =
            new connector::stomp::StompConnector(
                transport, *properties );

        connector->start();

        ActiveMQConnection connection(
            new ActiveMQConnectionData(
                connector, transport, properties) );

        connection.getClientID();
        connection.close();

        CPPUNIT_ASSERT( connection.getClientID() == "" );

    } catch( exceptions::ActiveMQException& ex ) {
        ex.printStackTrace();
        throw ex;
    }
}

////////////////////////////////////////////////////////////////////////////////
void ActiveMQConnectionTest::test2WithOpenwire()
{
    try
    {
        MyMessageListener listener;
        MyExceptionListener exListener;
        MyCommandListener cmdListener;
        MyDispatcher msgListener;
        std::string connectionId = "testConnectionId";
        decaf::util::Properties* properties =
            new decaf::util::Properties();
        transport::Transport* transport = NULL;

        // Default to Stomp
        properties->setProperty( "wireFormat", "openwire" );
        decaf::net::URI uri( "mock://mock?wireFormat=openwire" );

        transport::TransportFactory* factory =
            transport::TransportRegistry::getInstance().findFactory( "mock" );
        if( factory == NULL ){
            CPPUNIT_ASSERT( false );
        }

        // Create the transport.
        transport = factory->createComposite( uri );
        if( transport == NULL ){
            CPPUNIT_ASSERT( false );
        }

        transport::mock::MockTransport* dTransport =
            dynamic_cast< transport::mock::MockTransport*>( transport );

        CPPUNIT_ASSERT( dTransport != NULL );

        dTransport->setCommandListener( &cmdListener );

        connector::Connector* connector =
            new connector::openwire::OpenWireConnector(
                transport, *properties );

        connector->start();

        ActiveMQConnection connection(
            new ActiveMQConnectionData(
                connector, transport, properties) );

        connection.getClientID();
        connection.close();

        CPPUNIT_ASSERT( connection.getClientID() == "" );

    } catch( exceptions::ActiveMQException& ex ) {
        ex.printStackTrace();
        throw ex;
    }
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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.
 */

#include <set>

#include <gmock/gmock.h>

#include <process/clock.hpp>
#include <process/gtest.hpp>

#include <stout/gtest.hpp>
#include <stout/stringify.hpp>

#include "linux/perf.hpp"

using std::set;
using std::string;

using namespace process;

class PerfTest : public ::testing::Test {};

TEST_F(PerfTest, ROOT_Events)
{
  set<string> events;
  // Valid events.
  events.insert("cycles");
  events.insert("task-clock");
  EXPECT_TRUE(perf::valid(events));

  // Add an invalid event.
  events.insert("this-is-an-invalid-event");
  EXPECT_FALSE(perf::valid(events));
}

TEST_F(PerfTest, Parse)
{
  // uint64 and floats should be parsed.
  Try<hashmap<string, mesos::PerfStatistics> > parse =
    perf::parse("123,cycles\n0.123,task-clock");
  CHECK_SOME(parse);

  ASSERT_TRUE(parse.get().contains(""));
  mesos::PerfStatistics statistics = parse.get().get("").get();

  ASSERT_TRUE(statistics.has_cycles());
  EXPECT_EQ(123u, statistics.cycles());
  ASSERT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.123, statistics.task_clock());

  // Parse multiple cgroups.
  parse = perf::parse("123,cycles,cgroup1\n"
                      "456,cycles,cgroup2\n"
                      "0.456,task-clock,cgroup2\n"
                      "0.123,task-clock,cgroup1");
  CHECK_SOME(parse);
  EXPECT_FALSE(parse.get().contains(""));

  ASSERT_TRUE(parse.get().contains("cgroup1"));
  statistics = parse.get().get("cgroup1").get();

  ASSERT_TRUE(statistics.has_cycles());
  EXPECT_EQ(123u, statistics.cycles());
  ASSERT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.123, statistics.task_clock());

  ASSERT_TRUE(parse.get().contains("cgroup2"));
  statistics = parse.get().get("cgroup2").get();

  ASSERT_TRUE(statistics.has_cycles());
  EXPECT_EQ(456u, statistics.cycles());
  EXPECT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.456, statistics.task_clock());

  // Statistics reporting <not supported> should not appear.
  parse = perf::parse("<not supported>,cycles");
  CHECK_SOME(parse);

  ASSERT_TRUE(parse.get().contains(""));
  statistics = parse.get().get("").get();
  EXPECT_FALSE(statistics.has_cycles());

  // Statistics reporting <not counted> should be zero.
  parse = perf::parse("<not counted>,cycles\n<not counted>,task-clock");
  CHECK_SOME(parse);

  ASSERT_TRUE(parse.get().contains(""));
  statistics = parse.get().get("").get();

  EXPECT_TRUE(statistics.has_cycles());
  EXPECT_EQ(0u, statistics.cycles());
  EXPECT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.0, statistics.task_clock());

  // Check parsing fails.
  parse = perf::parse("1,cycles\ngarbage");
  EXPECT_ERROR(parse);

  parse = perf::parse("1,unknown-field");
  EXPECT_ERROR(parse);
}

TEST_F(PerfTest, ROOT_SampleInit)
{
  set<string> events;
  // Hardware event.
  events.insert("cycles");
  // Software event.
  events.insert("task-clock");

  // Sample init/launchd/systemd (pid 1).
  Future<mesos::PerfStatistics> statistics =
    perf::sample(events, 1, Seconds(1));
  AWAIT_READY(statistics);

  // Check the sample timestamp is within the last 5 seconds. This is generous
  // because there's the process reap delay in addition to the sampling
  // duration.
  ASSERT_TRUE(statistics.get().has_timestamp());
  EXPECT_GT(Seconds(5).secs(), Clock::now().secs() - statistics.get().timestamp());
  EXPECT_EQ(Seconds(1).secs(), statistics.get().duration());

  ASSERT_TRUE(statistics.get().has_cycles());
  EXPECT_LT(0u, statistics.get().cycles());

  ASSERT_TRUE(statistics.get().has_task_clock());
  EXPECT_LT(0.0, statistics.get().task_clock());
}
<commit_msg>Minor style fix.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF 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.
 */

#include <set>

#include <gmock/gmock.h>

#include <process/clock.hpp>
#include <process/gtest.hpp>

#include <stout/gtest.hpp>
#include <stout/stringify.hpp>

#include "linux/perf.hpp"

using std::set;
using std::string;

using namespace process;

class PerfTest : public ::testing::Test {};

TEST_F(PerfTest, ROOT_Events)
{
  set<string> events;
  // Valid events.
  events.insert("cycles");
  events.insert("task-clock");
  EXPECT_TRUE(perf::valid(events));

  // Add an invalid event.
  events.insert("this-is-an-invalid-event");
  EXPECT_FALSE(perf::valid(events));
}

TEST_F(PerfTest, Parse)
{
  // uint64 and floats should be parsed.
  Try<hashmap<string, mesos::PerfStatistics> > parse =
    perf::parse("123,cycles\n0.123,task-clock");
  CHECK_SOME(parse);

  ASSERT_TRUE(parse.get().contains(""));
  mesos::PerfStatistics statistics = parse.get().get("").get();

  ASSERT_TRUE(statistics.has_cycles());
  EXPECT_EQ(123u, statistics.cycles());
  ASSERT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.123, statistics.task_clock());

  // Parse multiple cgroups.
  parse = perf::parse("123,cycles,cgroup1\n"
                      "456,cycles,cgroup2\n"
                      "0.456,task-clock,cgroup2\n"
                      "0.123,task-clock,cgroup1");
  CHECK_SOME(parse);
  EXPECT_FALSE(parse.get().contains(""));

  ASSERT_TRUE(parse.get().contains("cgroup1"));
  statistics = parse.get().get("cgroup1").get();

  ASSERT_TRUE(statistics.has_cycles());
  EXPECT_EQ(123u, statistics.cycles());
  ASSERT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.123, statistics.task_clock());

  ASSERT_TRUE(parse.get().contains("cgroup2"));
  statistics = parse.get().get("cgroup2").get();

  ASSERT_TRUE(statistics.has_cycles());
  EXPECT_EQ(456u, statistics.cycles());
  EXPECT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.456, statistics.task_clock());

  // Statistics reporting <not supported> should not appear.
  parse = perf::parse("<not supported>,cycles");
  CHECK_SOME(parse);

  ASSERT_TRUE(parse.get().contains(""));
  statistics = parse.get().get("").get();
  EXPECT_FALSE(statistics.has_cycles());

  // Statistics reporting <not counted> should be zero.
  parse = perf::parse("<not counted>,cycles\n<not counted>,task-clock");
  CHECK_SOME(parse);

  ASSERT_TRUE(parse.get().contains(""));
  statistics = parse.get().get("").get();

  EXPECT_TRUE(statistics.has_cycles());
  EXPECT_EQ(0u, statistics.cycles());
  EXPECT_TRUE(statistics.has_task_clock());
  EXPECT_EQ(0.0, statistics.task_clock());

  // Check parsing fails.
  parse = perf::parse("1,cycles\ngarbage");
  EXPECT_ERROR(parse);

  parse = perf::parse("1,unknown-field");
  EXPECT_ERROR(parse);
}

TEST_F(PerfTest, ROOT_SampleInit)
{
  set<string> events;
  // Hardware event.
  events.insert("cycles");
  // Software event.
  events.insert("task-clock");

  // Sample init/launchd/systemd (pid 1).
  Future<mesos::PerfStatistics> statistics =
    perf::sample(events, 1, Seconds(1));
  AWAIT_READY(statistics);

  // Check the sample timestamp is within the last 5 seconds. This is generous
  // because there's the process reap delay in addition to the sampling
  // duration.
  ASSERT_TRUE(statistics.get().has_timestamp());
  EXPECT_GT(
      Seconds(5).secs(), Clock::now().secs() - statistics.get().timestamp());
  EXPECT_EQ(Seconds(1).secs(), statistics.get().duration());

  ASSERT_TRUE(statistics.get().has_cycles());
  EXPECT_LT(0u, statistics.get().cycles());

  ASSERT_TRUE(statistics.get().has_task_clock());
  EXPECT_LT(0.0, statistics.get().task_clock());
}
<|endoftext|>


<commit_before>#include "../test.h"
#include <cstdlib>

class StrdupTest : public TestBase {
public:
	StrdupTest() : TestBase("strdup") {
	}

    virtual void* Parse(const char* json) const {
    	return strdup(json);
    }

    virtual char* Stringify(void* userdata) const {
    	return strdup((char*)userdata);
    }

    virtual char* Prettify(void* userdata) const {
        return strdup((char*)userdata);
    }

    virtual void Free(void* userdata) const {
        free(userdata);
    }
};

REGISTER_TEST(StrdupTest);
<commit_msg>Implement strdup's statistics by strlen()<commit_after>#include "../test.h"
#include <cstdlib>

class StrdupTest : public TestBase {
public:
	StrdupTest() : TestBase("strdup") {
	}

    virtual void* Parse(const char* json) const {
    	return strdup(json);
    }

    virtual char* Stringify(void* userdata) const {
    	return strdup((char*)userdata);
    }

    virtual char* Prettify(void* userdata) const {
        return strdup((char*)userdata);
    }

    virtual Stat Statistics(void* userdata) const {
        Stat s;
        memset(&s, 0, sizeof(s));
        s.stringCount = 1;
        s.stringLength = strlen((char*)userdata);
        return s;
    }

    virtual void Free(void* userdata) const {
        free(userdata);
    }
};

REGISTER_TEST(StrdupTest);
<|endoftext|>


<commit_before>/*
  This is a tool shipped by 'Aleph - A Library for Exploring Persistent
  Homology'.

  It loads VTK files (structured grids) or TXT (1D functions) files and
  calculates the interlevel set persistence hierarchy described in:

    Hierarchies and Ranks for Persistence Pairs
    Bastian Rieck, Heike Leitte, and Filip Sadlo
    Proceedings of TopoInVis 2017, Japan

  The output of the tool is a list of nodes for the hierarchy, followed
  by a list of edges. Each node is identified by an ID, followed by its
  corresponding persistence pair entry. An edge consists of two node ID
  values, connected via "--".

  The following snippet gives a small demonstration:

    0: 0 infty
    1: 1 2
    2: 3 4

    0 -- 1
    0 -- 2

  This output may subsequently be used in an auxiliary Python script in
  order to analyse and compare different hierarchies.

  Please refer to file

    compare_interlevel_set_persistence_hierarchies.py

  for more information.

  Note that the extended persistence hierarchy referred to below is yet
  another name for the interlevel set persistence hierarchy.
*/

#include <aleph/persistenceDiagrams/Calculation.hh>
#include <aleph/persistenceDiagrams/PersistenceDiagram.hh>

#include <aleph/persistentHomology/ExtendedPersistenceHierarchy.hh>
#include <aleph/persistentHomology/PersistencePairing.hh>

#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>
#include <aleph/topology/UnionFind.hh>

#include <aleph/topology/filtrations/Data.hh>

#include <aleph/topology/io/Function.hh>
#include <aleph/topology/io/VTK.hh>

#include <aleph/utilities/Filesystem.hh>

#include <algorithm>
#include <functional>
#include <fstream>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>

// TODO: Replace this as soon as possible with a more modern option
// parser interface.
#include <getopt.h>

using DataType           = double;
using VertexType         = unsigned;
using Simplex            = aleph::topology::Simplex<DataType, VertexType>;
using SimplicialComplex  = aleph::topology::SimplicialComplex<Simplex>;
using PersistenceDiagram = aleph::PersistenceDiagram<DataType>;

void usage()
{
  std::cerr << "Usage: extended_persistence_hierarchy [--superlevels] [--sublevels] FILES\n"
            << "\n"
            << "Calculates the extended persistence hierarchy of a set of VTK files or 1D\n"
            << "functions stored in FILES. By default, a filtration based on the sublevel\n"
            << "sets is used. This may either be enforced or modified by using one of the\n"
            << "long options specified above.\n"
            << "\n"
            << "The hierarchy is written to STDOUT.\n"
            << "\n"
            << "Flags:\n"
            << "  -s: use sublevel set filtration\n"
            << "  -S: use superlevel set filtration\n"
            << "\n";
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] =
  {
    { "superlevels", no_argument, nullptr, 'S' },
    { "sublevels"  , no_argument, nullptr, 's' },
    { nullptr      , 0          , nullptr,  0  }
  };

  bool calculateSuperlevelSets = false;

  int option = 0;
  while( ( option = getopt_long( argc, argv, "Ss", commandLineOptions, nullptr ) ) != -1 )
  {
    switch( option )
    {
    case 'S':
      calculateSuperlevelSets = true;
      break;
    case 's':
      calculateSuperlevelSets = false;
      break;
    default:
      break;
    }
  }

  if( ( argc - optind ) < 1 )
  {
    usage();
    return -1;
  }

  std::vector<std::string> filenames;
  filenames.reserve( argc - optind );

  for( int i = optind; i < argc; i++ )
    filenames.push_back( argv[i] );

  std::vector<SimplicialComplex> simplicialComplexes;
  simplicialComplexes.reserve( filenames.size() );

  // Select a functor for calculating the weights when reading
  // a simplicial complex.
  auto functor = calculateSuperlevelSets
               ? [] ( DataType a, DataType b ) { return std::min(a,b); }
               : [] ( DataType a, DataType b ) { return std::max(a,b); };

  for( auto&& filename : filenames )
  {
    std::cerr << "* Reading '" << filename << "'...";

    if( aleph::utilities::extension( filename ) == ".vtk" )
    {
      SimplicialComplex K;

      aleph::topology::io::VTKStructuredGridReader reader;
      reader( filename, K, functor );

      if( calculateSuperlevelSets )
        K.sort( aleph::topology::filtrations::Data<Simplex, std::greater<DataType> >() );
      else
        K.sort( aleph::topology::filtrations::Data<Simplex, std::less<DataType> >() );

      simplicialComplexes.emplace_back( K );
    }
    else
    {
      auto complexes
        = aleph::topology::io::loadFunctions<SimplicialComplex>( filename,
                                                                 functor );

      for( auto&& K : complexes )
      {
        if( calculateSuperlevelSets )
          K.sort( aleph::topology::filtrations::Data<Simplex, std::greater<DataType> >() );
        else
          K.sort( aleph::topology::filtrations::Data<Simplex, std::less<DataType> >() );
      }

      simplicialComplexes.insert( simplicialComplexes.end(),
                                  complexes.begin(), complexes.end() );
    }

    std::cerr << "finished\n";
  }

  std::vector<PersistenceDiagram> persistenceDiagrams;
  persistenceDiagrams.reserve( simplicialComplexes.size() );

  for( auto&& K : simplicialComplexes )
  {
    aleph::ExtendedPersistenceHierarchy<Simplex> eph;
    auto ppe                = eph( K );   // persistence pairing & edges
    auto persistencePairing = ppe.first;  // persistence pairing
    auto edges              = ppe.second; // edges

    // Calculate the corresponding persistence diagram, clean it
    // perfunctorily, and finally sort it by increasing creation
    // threshold. Subsequently, we will check which diagrams are
    // unique.
    {
      auto diagrams = aleph::makePersistenceDiagrams( persistencePairing, K );
      auto diagram  = diagrams.front();

      diagram.removeDiagonal();

      std::sort( diagram.begin(), diagram.end(), [] ( const typename PersistenceDiagram::Point& a, const typename PersistenceDiagram::Point& b )
                                                 {
                                                   return a.x() < b.x() || ( a.x() == b.x() && a.y() < b.y() );
                                                 } );

      persistenceDiagrams.push_back( diagram );
    }

    // Enumerate all vertices in the hierarchy -------------------------

    std::set<VertexType> vertices;

    for( auto edge : edges )
    {
      vertices.insert( edge.first );
      vertices.insert( edge.second );
    }

    // Display nodes of the hierarchy ----------------------------------

    {
      unsigned index = 0;
      for( auto&& vertex : vertices )
      {
        auto itCreator = K.find( Simplex(vertex) );
        if( itCreator != K.end() )
        {
          auto itPair         = persistencePairing.find( static_cast<VertexType>( K.index( *itCreator ) ) );
          auto destroyerIndex = itPair->second;

          if( destroyerIndex < K.size() )
            std::cout << index << ": " << itCreator->data() << "\t" << K.at( destroyerIndex ).data() << "\n";
          else
            std::cout << index << ": " << itCreator->data() << "\t" << std::numeric_limits<DataType>::infinity() << "\n";
        }

        ++index;
      }

      std::cout << "\n";
    }

    // Display edges of the hierarchy ----------------------------------

    for( auto&& edge : edges )
    {
      auto uIndex = std::distance( vertices.begin(), vertices.find( edge.first ) );
      auto vIndex = std::distance( vertices.begin(), vertices.find( edge.second ) );

      std::cout << uIndex << " -- " << vIndex << "\n";
    }

    std::cout << "\n\n";
  }

  // Determine which persistence diagrams are unique among the
  // discovered ones...
  {
    std::vector<std::size_t> indices( persistenceDiagrams.size() );
    std::iota( indices.begin(), indices.end(), 0 );

    aleph::topology::UnionFind<std::size_t> uf( indices.begin(), indices.end() );

    for( std::size_t i = 0; i < persistenceDiagrams.size(); i++ )
    {
      auto&& D1 = persistenceDiagrams.at(i);

      for( std::size_t j = i+1; j < persistenceDiagrams.size(); j++ )
      {
        auto&& D2 = persistenceDiagrams.at(j);

        if( D1 == D2 )
          uf.merge( j, i );
      }
    }

    std::vector<std::size_t> roots;
    uf.roots( std::back_inserter( roots ) );

    std::ofstream out( "/tmp/classes.txt" );

    std::cerr << "* Out of " << persistenceDiagrams.size() << " persistence diagrams, there are " << roots.size() << " unique ones\n";

    unsigned C = 0;
    for( auto&& root : roots )
    {
      std::vector<std::size_t> indices;
      uf.get( root, std::back_inserter( indices ) );

      if( indices.size() > 1 )
      {
        std::cerr << "  Class " << C << ": " << indices.size() << "\n";

        C++; // ha ha

        for( auto&& index : indices )
          out << index << " ";

        out << "\n";
      }
    }
  }
}
<commit_msg>Fixed implicit conversion<commit_after>/*
  This is a tool shipped by 'Aleph - A Library for Exploring Persistent
  Homology'.

  It loads VTK files (structured grids) or TXT (1D functions) files and
  calculates the interlevel set persistence hierarchy described in:

    Hierarchies and Ranks for Persistence Pairs
    Bastian Rieck, Heike Leitte, and Filip Sadlo
    Proceedings of TopoInVis 2017, Japan

  The output of the tool is a list of nodes for the hierarchy, followed
  by a list of edges. Each node is identified by an ID, followed by its
  corresponding persistence pair entry. An edge consists of two node ID
  values, connected via "--".

  The following snippet gives a small demonstration:

    0: 0 infty
    1: 1 2
    2: 3 4

    0 -- 1
    0 -- 2

  This output may subsequently be used in an auxiliary Python script in
  order to analyse and compare different hierarchies.

  Please refer to file

    compare_interlevel_set_persistence_hierarchies.py

  for more information.

  Note that the extended persistence hierarchy referred to below is yet
  another name for the interlevel set persistence hierarchy.
*/

#include <aleph/persistenceDiagrams/Calculation.hh>
#include <aleph/persistenceDiagrams/PersistenceDiagram.hh>

#include <aleph/persistentHomology/ExtendedPersistenceHierarchy.hh>
#include <aleph/persistentHomology/PersistencePairing.hh>

#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>
#include <aleph/topology/UnionFind.hh>

#include <aleph/topology/filtrations/Data.hh>

#include <aleph/topology/io/Function.hh>
#include <aleph/topology/io/VTK.hh>

#include <aleph/utilities/Filesystem.hh>

#include <algorithm>
#include <functional>
#include <fstream>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>

// TODO: Replace this as soon as possible with a more modern option
// parser interface.
#include <getopt.h>

using DataType           = double;
using VertexType         = unsigned;
using Simplex            = aleph::topology::Simplex<DataType, VertexType>;
using SimplicialComplex  = aleph::topology::SimplicialComplex<Simplex>;
using PersistenceDiagram = aleph::PersistenceDiagram<DataType>;

void usage()
{
  std::cerr << "Usage: extended_persistence_hierarchy [--superlevels] [--sublevels] FILES\n"
            << "\n"
            << "Calculates the extended persistence hierarchy of a set of VTK files or 1D\n"
            << "functions stored in FILES. By default, a filtration based on the sublevel\n"
            << "sets is used. This may either be enforced or modified by using one of the\n"
            << "long options specified above.\n"
            << "\n"
            << "The hierarchy is written to STDOUT.\n"
            << "\n"
            << "Flags:\n"
            << "  -s: use sublevel set filtration\n"
            << "  -S: use superlevel set filtration\n"
            << "\n";
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] =
  {
    { "superlevels", no_argument, nullptr, 'S' },
    { "sublevels"  , no_argument, nullptr, 's' },
    { nullptr      , 0          , nullptr,  0  }
  };

  bool calculateSuperlevelSets = false;

  int option = 0;
  while( ( option = getopt_long( argc, argv, "Ss", commandLineOptions, nullptr ) ) != -1 )
  {
    switch( option )
    {
    case 'S':
      calculateSuperlevelSets = true;
      break;
    case 's':
      calculateSuperlevelSets = false;
      break;
    default:
      break;
    }
  }

  if( ( argc - optind ) < 1 )
  {
    usage();
    return -1;
  }

  std::vector<std::string> filenames;
  filenames.reserve( std::size_t( argc - optind ) );

  for( int i = optind; i < argc; i++ )
    filenames.push_back( argv[i] );

  std::vector<SimplicialComplex> simplicialComplexes;
  simplicialComplexes.reserve( filenames.size() );

  // Select a functor for calculating the weights when reading
  // a simplicial complex.
  auto functor = calculateSuperlevelSets
               ? [] ( DataType a, DataType b ) { return std::min(a,b); }
               : [] ( DataType a, DataType b ) { return std::max(a,b); };

  for( auto&& filename : filenames )
  {
    std::cerr << "* Reading '" << filename << "'...";

    if( aleph::utilities::extension( filename ) == ".vtk" )
    {
      SimplicialComplex K;

      aleph::topology::io::VTKStructuredGridReader reader;
      reader( filename, K, functor );

      if( calculateSuperlevelSets )
        K.sort( aleph::topology::filtrations::Data<Simplex, std::greater<DataType> >() );
      else
        K.sort( aleph::topology::filtrations::Data<Simplex, std::less<DataType> >() );

      simplicialComplexes.emplace_back( K );
    }
    else
    {
      auto complexes
        = aleph::topology::io::loadFunctions<SimplicialComplex>( filename,
                                                                 functor );

      for( auto&& K : complexes )
      {
        if( calculateSuperlevelSets )
          K.sort( aleph::topology::filtrations::Data<Simplex, std::greater<DataType> >() );
        else
          K.sort( aleph::topology::filtrations::Data<Simplex, std::less<DataType> >() );
      }

      simplicialComplexes.insert( simplicialComplexes.end(),
                                  complexes.begin(), complexes.end() );
    }

    std::cerr << "finished\n";
  }

  std::vector<PersistenceDiagram> persistenceDiagrams;
  persistenceDiagrams.reserve( simplicialComplexes.size() );

  for( auto&& K : simplicialComplexes )
  {
    aleph::ExtendedPersistenceHierarchy<Simplex> eph;
    auto ppe                = eph( K );   // persistence pairing & edges
    auto persistencePairing = ppe.first;  // persistence pairing
    auto edges              = ppe.second; // edges

    // Calculate the corresponding persistence diagram, clean it
    // perfunctorily, and finally sort it by increasing creation
    // threshold. Subsequently, we will check which diagrams are
    // unique.
    {
      auto diagrams = aleph::makePersistenceDiagrams( persistencePairing, K );
      auto diagram  = diagrams.front();

      diagram.removeDiagonal();

      std::sort( diagram.begin(), diagram.end(), [] ( const typename PersistenceDiagram::Point& a, const typename PersistenceDiagram::Point& b )
                                                 {
                                                   return a.x() < b.x() || ( a.x() == b.x() && a.y() < b.y() );
                                                 } );

      persistenceDiagrams.push_back( diagram );
    }

    // Enumerate all vertices in the hierarchy -------------------------

    std::set<VertexType> vertices;

    for( auto edge : edges )
    {
      vertices.insert( edge.first );
      vertices.insert( edge.second );
    }

    // Display nodes of the hierarchy ----------------------------------

    {
      unsigned index = 0;
      for( auto&& vertex : vertices )
      {
        auto itCreator = K.find( Simplex(vertex) );
        if( itCreator != K.end() )
        {
          auto itPair         = persistencePairing.find( static_cast<VertexType>( K.index( *itCreator ) ) );
          auto destroyerIndex = itPair->second;

          if( destroyerIndex < K.size() )
            std::cout << index << ": " << itCreator->data() << "\t" << K.at( destroyerIndex ).data() << "\n";
          else
            std::cout << index << ": " << itCreator->data() << "\t" << std::numeric_limits<DataType>::infinity() << "\n";
        }

        ++index;
      }

      std::cout << "\n";
    }

    // Display edges of the hierarchy ----------------------------------

    for( auto&& edge : edges )
    {
      auto uIndex = std::distance( vertices.begin(), vertices.find( edge.first ) );
      auto vIndex = std::distance( vertices.begin(), vertices.find( edge.second ) );

      std::cout << uIndex << " -- " << vIndex << "\n";
    }

    std::cout << "\n\n";
  }

  // Determine which persistence diagrams are unique among the
  // discovered ones...
  {
    std::vector<std::size_t> indices( persistenceDiagrams.size() );
    std::iota( indices.begin(), indices.end(), 0 );

    aleph::topology::UnionFind<std::size_t> uf( indices.begin(), indices.end() );

    for( std::size_t i = 0; i < persistenceDiagrams.size(); i++ )
    {
      auto&& D1 = persistenceDiagrams.at(i);

      for( std::size_t j = i+1; j < persistenceDiagrams.size(); j++ )
      {
        auto&& D2 = persistenceDiagrams.at(j);

        if( D1 == D2 )
          uf.merge( j, i );
      }
    }

    std::vector<std::size_t> roots;
    uf.roots( std::back_inserter( roots ) );

    std::ofstream out( "/tmp/classes.txt" );

    std::cerr << "* Out of " << persistenceDiagrams.size() << " persistence diagrams, there are " << roots.size() << " unique ones\n";

    unsigned C = 0;
    for( auto&& root : roots )
    {
      std::vector<std::size_t> indices;
      uf.get( root, std::back_inserter( indices ) );

      if( indices.size() > 1 )
      {
        std::cerr << "  Class " << C << ": " << indices.size() << "\n";

        C++; // ha ha

        for( auto&& index : indices )
          out << index << " ";

        out << "\n";
      }
    }
  }
}
<|endoftext|>


<commit_before>/* <x0/mod_vhost_basic.cpp>
 *
 * This file is part of the x0 web server project and is released under LGPL-3.
 *
 * (c) 2009 Chrisitan Parpart <trapni@gentoo.org>
 */

#include <x0/server.hpp>
#include <x0/request.hpp>
#include <x0/response.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/signal.hpp>
#include <boost/bind.hpp>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

/**
 * \ingroup modules
 * \brief provides a basic config-file based virtual hosting facility.
 *
 *

 * -- example configuration
 *
 * BindAddress = '0::0';             -- default bind address
 * Listen = 80;                      -- default listening port
 * DefaultHost = 'www.example.com';  -- default vhost to choose when we receive an unknown Host-request-header.
 *
 * Hosts = {
 *     ['www.example.com'] = {
 *         ServerAliases = { 'www.example.net', 'example.com', 'example.net' };
 *         DocumentRoot = '/var/www/example.com/htdocs';
 *     };
 *     ['localhost:8080'] = {
 *         DocumentRoot = '/var/www/example.com/htdocs';
 *         BindAddress = 'localhost';
 *     };
 * };
 *

 */
class vhost_basic_plugin :
	public x0::plugin
{
private:
	boost::signals::connection c;

	struct vhost_config
	{
		std::string docroot;
	};

	struct server_config
	{
		std::string default_hostid;
		std::map<std::string, vhost_config *> mappings;
	};

public:
	vhost_basic_plugin(x0::server& srv, const std::string& name) :
		x0::plugin(srv, name)
	{
		c = server_.resolve_document_root.connect(boost::bind(&vhost_basic_plugin::resolve_document_root, this, _1));
	}

	~vhost_basic_plugin()
	{
		server_.resolve_document_root.disconnect(c);
	}

	virtual void configure()
	{
		auto hosts = server_.config()["Hosts"].keys<std::string>();
		if (hosts.empty())
			return;

		std::string default_bind("0::0");
		server_.config().load("BindAddress", default_bind);

		server_config& srvcfg = server_.create_context<server_config>(this);

		server_.config().load("DefaultHost", srvcfg.default_hostid);

		for (auto i = hosts.begin(), e = hosts.end(); i != e; ++i)
		{
			std::string hostid = x0::make_hostid(*i);
			int port = x0::extract_port_from_hostid(hostid);

			auto aliases = server_.config()["Hosts"][hostid]["ServerAliases"].as<std::vector<std::string>>();
			std::string docroot = server_.config()["Hosts"][hostid]["DocumentRoot"].as<std::string>();
			std::string bind = server_.config()["Hosts"][hostid]["BindAddress"].get<std::string>(default_bind);

//			server_.log(x0::severity::debug, "port=%d: hostid[%s]: docroot[%s], alias-count=%d",
//				port, hostid.c_str(), docroot.c_str(), aliases.size());

			vhost_config& cfg = server_.create_context<vhost_config>(this, hostid);
			cfg.docroot = docroot;

			srvcfg.mappings.insert({ {hostid, &cfg} });
			for (auto k = aliases.begin(), m = aliases.end(); k != m; ++k)
			{
				std::string hid(x0::make_hostid(*k, port));

				auto f = srvcfg.mappings.find(hid);
				if (f == srvcfg.mappings.end())
				{
					srvcfg.mappings[hid] = &cfg;

					int aport = x0::extract_port_from_hostid(hid);
					server_.setup_listener(aport, bind);
				}
				else
				{
					server_.log(x0::severity::warn, "Server alias '%s' already in use.", hid.c_str());
				}
			}

			server_.setup_listener(port, bind);
		}
	}

private:
	void resolve_document_root(x0::request& in)
	{
		try
		{
			static std::string hostkey("Host");
			std::string hostid(x0::make_hostid(in.header(hostkey)));

			server_config& srvcfg = server_.context<server_config>(this);
			auto i = srvcfg.mappings.find(hostid);
			if (i != srvcfg.mappings.end())
			{
				in.document_root = i->second->docroot;
				server_.log(x0::severity::debug, "vhost_basic[%s]: resolved to %s", hostid.c_str(), in.document_root.c_str());
			}
			else
			{
				in.document_root = server_.context<vhost_config>(this, hostid).docroot;
			}
		}
		catch (const x0::host_not_found&)
		{
			try
			{
				// resolve to default host's document root
				std::string default_hostid(server_.context<server_config>(this).default_hostid);
				in.document_root = server_.context<vhost_config>(this, default_hostid).docroot;
				// XXX we could instead auto-redirect them.
			}
			catch (...) {}
		}
	}
};

X0_EXPORT_PLUGIN(vhost_basic);
<commit_msg>vhost_basic: added support for vhost context linking<commit_after>/* <x0/mod_vhost_basic.cpp>
 *
 * This file is part of the x0 web server project and is released under LGPL-3.
 *
 * (c) 2009 Chrisitan Parpart <trapni@gentoo.org>
 */

#include <x0/server.hpp>
#include <x0/request.hpp>
#include <x0/response.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/signal.hpp>
#include <boost/bind.hpp>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

/**
 * \ingroup modules
 * \brief provides a basic config-file based virtual hosting facility.
 *
 *

 * -- example configuration
 *
 * BindAddress = '0::0';             -- default bind address
 * Listen = 80;                      -- default listening port
 * DefaultHost = 'www.example.com';  -- default vhost to choose when we receive an unknown Host-request-header.
 *
 * Hosts = {
 *     ['www.example.com'] = {
 *         ServerAliases = { 'www.example.net', 'example.com', 'example.net' };
 *         DocumentRoot = '/var/www/example.com/htdocs';
 *     };
 *     ['localhost:8080'] = {
 *         DocumentRoot = '/var/www/example.com/htdocs';
 *         BindAddress = 'localhost';
 *     };
 * };
 *

 */
class vhost_basic_plugin :
	public x0::plugin
{
private:
	boost::signals::connection c;

	struct vhost_config
	{
		std::string docroot;
	};

	struct server_config
	{
		std::string default_hostid;
		std::map<std::string, vhost_config *> mappings;
	};

public:
	vhost_basic_plugin(x0::server& srv, const std::string& name) :
		x0::plugin(srv, name)
	{
		c = server_.resolve_document_root.connect(boost::bind(&vhost_basic_plugin::resolve_document_root, this, _1));
	}

	~vhost_basic_plugin()
	{
		server_.resolve_document_root.disconnect(c);
	}

	virtual void configure()
	{
		auto hosts = server_.config()["Hosts"].keys<std::string>();
		if (hosts.empty())
			return;

		std::string default_bind("0::0");
		server_.config().load("BindAddress", default_bind);

		server_config& srvcfg = server_.create_context<server_config>(this);

		server_.config().load("DefaultHost", srvcfg.default_hostid);

		for (auto i = hosts.begin(), e = hosts.end(); i != e; ++i)
		{
			std::string hostid = x0::make_hostid(*i);
			int port = x0::extract_port_from_hostid(hostid);

			auto aliases = server_.config()["Hosts"][hostid]["ServerAliases"].as<std::vector<std::string>>();
			std::string docroot = server_.config()["Hosts"][hostid]["DocumentRoot"].as<std::string>();
			std::string bind = server_.config()["Hosts"][hostid]["BindAddress"].get<std::string>(default_bind);

//			server_.log(x0::severity::debug, "port=%d: hostid[%s]: docroot[%s], alias-count=%d",
//				port, hostid.c_str(), docroot.c_str(), aliases.size());

			vhost_config& cfg = server_.create_context<vhost_config>(this, hostid);
			cfg.docroot = docroot;

			srvcfg.mappings.insert({ {hostid, &cfg} });
			for (auto k = aliases.begin(), m = aliases.end(); k != m; ++k)
			{
				std::string hid(x0::make_hostid(*k, port));

				auto f = srvcfg.mappings.find(hid);
				if (f == srvcfg.mappings.end())
				{
					srvcfg.mappings[hid] = &cfg;
					server_.link_context(hostid, hid);

					int aport = x0::extract_port_from_hostid(hid);
					server_.setup_listener(aport, bind);
					//server_.log(x0::severity::debug, "Server alias '%s' (for bind '%s' on port %d) added.", hid.c_str(), bind.c_str(), aport);
				}
				else
				{
					char msg[1024];
					snprintf(msg, sizeof(msg), "Server alias '%s' already in use.", hid.c_str());
					throw std::runtime_error(msg);
				}
			}

			server_.setup_listener(port, bind);
		}
	}

private:
	void resolve_document_root(x0::request& in)
	{
		try
		{
			static std::string hostkey("Host");
			std::string hostid(x0::make_hostid(in.header(hostkey)));

			server_config& srvcfg = server_.context<server_config>(this);
			auto i = srvcfg.mappings.find(hostid);
			if (i != srvcfg.mappings.end())
			{
				in.document_root = i->second->docroot;
				server_.log(x0::severity::debug, "vhost_basic[%s]: resolved to %s", hostid.c_str(), in.document_root.c_str());
			}
			else
			{
				in.document_root = server_.context<vhost_config>(this, hostid).docroot;
			}
		}
		catch (const x0::host_not_found&)
		{
			try
			{
				// resolve to default host's document root
				std::string default_hostid(server_.context<server_config>(this).default_hostid);
				in.document_root = server_.context<vhost_config>(this, default_hostid).docroot;
				// XXX we could instead auto-redirect them.
			}
			catch (...) {}
		}
	}
};

X0_EXPORT_PLUGIN(vhost_basic);
<|endoftext|>


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

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

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

******************************************************************************/
#include "OperatorPython.h"
#include "vtkPython.h"

#include <QPointer>
#include <QtDebug>

#include "DataSource.h"
#include "EditOperatorWidget.h"
#include "OperatorResult.h"
#include "pqPythonSyntaxHighlighter.h"

#include "vtkDataObject.h"
#include "vtkNew.h"
#include "vtkPythonInterpreter.h"
#include "vtkPythonUtil.h"
#include "vtkSMParaViewPipelineController.h"
#include "vtkSMProxy.h"
#include "vtkSMProxyManager.h"
#include "vtkSMSessionProxyManager.h"
#include "vtkSMSourceProxy.h"
#include "vtkSmartPyObject.h"
#include "vtkTrivialProducer.h"
#include <sstream>

#include "vtk_jsoncpp.h"

#include "ui_EditPythonOperatorWidget.h"

namespace {

bool CheckForError()
{
  PyObject* exception = PyErr_Occurred();
  if (exception) {
    PyErr_Print();
    PyErr_Clear();
    return true;
  }
  return false;
}

class EditPythonOperatorWidget : public tomviz::EditOperatorWidget
{
  Q_OBJECT
  typedef tomviz::EditOperatorWidget Superclass;

public:
  EditPythonOperatorWidget(QWidget* p, tomviz::OperatorPython* o)
    : Superclass(p), Op(o), Ui()
  {
    this->Ui.setupUi(this);
    this->Ui.name->setText(o->label());
    if (!o->script().isEmpty()) {
      this->Ui.script->setPlainText(o->script());
    }
    new pqPythonSyntaxHighlighter(this->Ui.script, this);
  }
  void applyChangesToOperator() override
  {
    if (this->Op) {
      this->Op->setLabel(this->Ui.name->text());
      this->Op->setScript(this->Ui.script->toPlainText());
    }
  }

private:
  QPointer<tomviz::OperatorPython> Op;
  Ui::EditPythonOperatorWidget Ui;
};

#include "OperatorPython.moc"
}

namespace tomviz {

class OperatorPython::OPInternals
{
public:
  vtkSmartPyObject OperatorModule;
  vtkSmartPyObject Code;
  vtkSmartPyObject TransformMethod;
};

OperatorPython::OperatorPython(QObject* parentObject)
  : Superclass(parentObject), Internals(new OperatorPython::OPInternals()),
    Label("Python Operator")
{
  vtkPythonInterpreter::Initialize();
  this->Internals->OperatorModule.TakeReference(
    PyImport_ImportModule("tomviz.utils"));
  if (!this->Internals->OperatorModule) {
    qCritical() << "Failed to import tomviz.utils module.";
    CheckForError();
  }
}

OperatorPython::~OperatorPython()
{
}

void OperatorPython::setLabel(const QString& txt)
{
  this->Label = txt;
  emit labelModified();
}

QIcon OperatorPython::icon() const
{
  return QIcon(":/pqWidgets/Icons/pqProgrammableFilter24.png");
}

void OperatorPython::setJSONDescription(const QString& str)
{
  if (this->jsonDescription == str) {
    return;
  }

  Json::Value root;
  Json::Reader reader;
  bool parsingSuccessful = reader.parse(str.toLatin1().data(), root);
  if (!parsingSuccessful) {
    qCritical() << "Failed to parse operator JSON";
    qCritical() << str;
    return;
  }

  // Get the label for the operator
  Json::Value labelNode = root["label"];
  if (!labelNode.isNull()) {
    setLabel(labelNode.asCString());
  }

  m_resultNames.clear();
  m_childDataSourceNamesAndLabels.clear();

  // Get the number of results
  Json::Value resultsNode = root["results"];
  if (!resultsNode.isNull()) {
    Json::Value::ArrayIndex numResults = resultsNode.size();
    setNumberOfResults(numResults);

    for (Json::Value::ArrayIndex i = 0; i < numResults; ++i) {
      OperatorResult* oa = resultAt(i);
      if (!oa) {
        Q_ASSERT(oa != nullptr);
      }
      Json::Value nameValue = resultsNode[i]["name"];
      if (!nameValue.isNull()) {
        oa->setName(nameValue.asCString());
        m_resultNames.append(nameValue.asCString());
      }
      Json::Value labelValue = resultsNode[i]["label"];
      if (!labelValue.isNull()) {
        oa->setLabel(labelValue.asCString());
      }
    }
  }

  // Get child dataset information
  Json::Value childDatasetNode = root["children"];
  if (!childDatasetNode.isNull()) {
    Json::Value::ArrayIndex size = childDatasetNode.size();
    if (size != 1) {
      qCritical() << "Only one child dataset is supported for now. Found"
                  << size << " but only the first will be used";
    }
    if (size > 0) {
      setHasChildDataSource(true);
      Json::Value nameValue = childDatasetNode[0]["name"];
      Json::Value labelValue = childDatasetNode[0]["label"];
      if (!nameValue.isNull() && !labelValue.isNull()) {
        QPair<QString, QString> nameLabelPair(nameValue.asCString(),
                                              labelValue.asCString());
        m_childDataSourceNamesAndLabels.append(nameLabelPair);
      } else if (nameValue.isNull()) {
        qCritical() << "No name given for child DataSet";
      } else if (labelValue.isNull()) {
        qCritical() << "No label given for child DataSet";
      }
    }
  }
}

const QString& OperatorPython::JSONDescription() const
{
  return this->jsonDescription;
}

void OperatorPython::setScript(const QString& str)
{
  if (this->Script != str) {
    this->Script = str;
    this->Internals->Code.TakeReference(nullptr);
    this->Internals->TransformMethod.TakeReference(nullptr);

    this->Internals->Code.TakeReference(Py_CompileString(
      this->Script.toLatin1().data(), this->label().toLatin1().data(),
      Py_file_input /*Py_eval_input*/));
    if (!this->Internals->Code) {
      CheckForError();
      qCritical(
        "Invalid script. Please check the traceback message for details");
      return;
    }

    vtkSmartPyObject module;
    module.TakeReference(PyImport_ExecCodeModule(
      QString("tomviz_%1").arg(this->label()).toLatin1().data(),
      this->Internals->Code));
    if (!module) {
      CheckForError();
      qCritical("Failed to create module.");
      return;
    }

    this->Internals->TransformMethod.TakeReference(
      PyObject_GetAttrString(module, "transform_scalars"));
    if (!this->Internals->TransformMethod) {
      CheckForError();
      qWarning("Script doesn't have any 'transform_scalars' function.");
      return;
    }
    CheckForError();
    emit this->transformModified();
  }
}

bool OperatorPython::applyTransform(vtkDataObject* data)
{
  if (this->Script.isEmpty()) {
    return true;
  }
  if (!this->Internals->OperatorModule || !this->Internals->TransformMethod) {
    return true;
  }

  Q_ASSERT(data);

  vtkSmartPyObject pydata(vtkPythonUtil::GetObjectFromPointer(data));
  vtkSmartPyObject args(PyTuple_New(1));
  PyTuple_SET_ITEM(args.GetPointer(), 0, pydata.ReleaseReference());

  vtkSmartPyObject result;
  result.TakeReference(
    PyObject_Call(this->Internals->TransformMethod, args, nullptr));
  if (!result) {
    qCritical("Failed to execute the script.");
    CheckForError();
    return false;
  }

  // Look for additional outputs from the filter returned in a dictionary
  PyObject* outputDict = result.GetPointer();
  if (PyDict_Check(outputDict)) {
    bool errorEncountered = false;

    // Results (tables, etc.)
    for (int i = 0; i < m_resultNames.size(); ++i) {
      const char* name = m_resultNames[i].toLatin1().data();
      PyObject* pyDataObject = PyDict_GetItemString(outputDict, name);
      if (!pyDataObject) {
        errorEncountered = true;
        qCritical() << "No result named" << m_resultNames[i]
                    << "defined in output dictionary.\n";
        continue;
      }
      vtkObjectBase* vtkobject =
        vtkPythonUtil::GetPointerFromObject(pyDataObject, "vtkDataObject");
      vtkDataObject* dataObject = vtkDataObject::SafeDownCast(vtkobject);
      if (dataObject) {
        bool resultWasSet = setResult(name, dataObject);
        if (!resultWasSet) {
          qCritical() << "Could not set result '" << name << "'";
          continue;
        }
      } else {
        qCritical() << "Result named '" << name << "' is not a vtkDataObject";
        continue;
      }
    }

    // Segmentations, reconstructions, etc.
    for (int i = 0; i < m_childDataSourceNamesAndLabels.size(); ++i) {
      QPair<QString, QString> nameLabelPair =
        m_childDataSourceNamesAndLabels[i];
      const char* name = nameLabelPair.first.toLatin1().data();
      const char* label = nameLabelPair.second.toLatin1().data();
      PyObject* child = PyDict_GetItemString(outputDict, name);
      if (!child) {
        errorEncountered = true;
        qCritical() << "No child data source named '"
                    << nameLabelPair.first << "' defined in output dictionary.\n";
        continue;
      }

      vtkObjectBase* vtkobject =
        vtkPythonUtil::GetPointerFromObject(child, "vtkDataObject");
      vtkDataObject* childData = vtkDataObject::SafeDownCast(vtkobject);
      if (childData) {
        vtkSMProxyManager* proxyManager = vtkSMProxyManager::GetProxyManager();
        vtkSMSessionProxyManager* sessionProxyManager =
          proxyManager->GetActiveSessionProxyManager();

        vtkSmartPointer<vtkSMProxy> producerProxy;
        producerProxy.TakeReference(
          sessionProxyManager->NewProxy("sources", "TrivialProducer"));
        producerProxy->UpdateVTKObjects();

        vtkTrivialProducer* producer = vtkTrivialProducer::SafeDownCast(
          producerProxy->GetClientSideObject());
        if (!producer) {
          qWarning() << "Could not get TrivialProducer from proxy";
          return false;
        }

        producer->SetOutput(childData);

        DataSource* childDS =
          new DataSource(vtkSMSourceProxy::SafeDownCast(producerProxy),
                         DataSource::Volume, this);
        childDS->setFilename(label);
        setChildDataSource(childDS);
      }
    }

    if (errorEncountered) {
      PyObject* objectRepr = PyObject_Repr(outputDict);
      const char* objectReprString = PyString_AsString(objectRepr);
      qCritical() << "Dictionary return from Python script is:\n"
                  << objectReprString;

    }
  }

  return CheckForError() == false;
}

Operator* OperatorPython::clone() const
{
  OperatorPython* newClone = new OperatorPython();
  newClone->setLabel(this->label());
  newClone->setScript(this->script());
  newClone->setJSONDescription(this->JSONDescription());
  return newClone;
}

bool OperatorPython::serialize(pugi::xml_node& ns) const
{
  ns.append_attribute("label").set_value(this->label().toLatin1().data());
  ns.append_attribute("script").set_value(this->script().toLatin1().data());
  return true;
}

bool OperatorPython::deserialize(const pugi::xml_node& ns)
{
  this->setLabel(ns.attribute("label").as_string());
  this->setScript(ns.attribute("script").as_string());
  return true;
}

EditOperatorWidget* OperatorPython::getEditorContents(QWidget* p)
{
  return new EditPythonOperatorWidget(p, this);
}
}
<commit_msg>Fix problems with invalid pointers<commit_after>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

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

******************************************************************************/
#include "OperatorPython.h"
#include "vtkPython.h"

#include <QPointer>
#include <QtDebug>

#include "DataSource.h"
#include "EditOperatorWidget.h"
#include "OperatorResult.h"
#include "pqPythonSyntaxHighlighter.h"

#include "vtkDataObject.h"
#include "vtkNew.h"
#include "vtkPythonInterpreter.h"
#include "vtkPythonUtil.h"
#include "vtkSMParaViewPipelineController.h"
#include "vtkSMProxy.h"
#include "vtkSMProxyManager.h"
#include "vtkSMSessionProxyManager.h"
#include "vtkSMSourceProxy.h"
#include "vtkSmartPyObject.h"
#include "vtkTrivialProducer.h"
#include <sstream>

#include "vtk_jsoncpp.h"

#include "ui_EditPythonOperatorWidget.h"

namespace {

bool CheckForError()
{
  PyObject* exception = PyErr_Occurred();
  if (exception) {
    PyErr_Print();
    PyErr_Clear();
    return true;
  }
  return false;
}

class EditPythonOperatorWidget : public tomviz::EditOperatorWidget
{
  Q_OBJECT
  typedef tomviz::EditOperatorWidget Superclass;

public:
  EditPythonOperatorWidget(QWidget* p, tomviz::OperatorPython* o)
    : Superclass(p), Op(o), Ui()
  {
    this->Ui.setupUi(this);
    this->Ui.name->setText(o->label());
    if (!o->script().isEmpty()) {
      this->Ui.script->setPlainText(o->script());
    }
    new pqPythonSyntaxHighlighter(this->Ui.script, this);
  }
  void applyChangesToOperator() override
  {
    if (this->Op) {
      this->Op->setLabel(this->Ui.name->text());
      this->Op->setScript(this->Ui.script->toPlainText());
    }
  }

private:
  QPointer<tomviz::OperatorPython> Op;
  Ui::EditPythonOperatorWidget Ui;
};

#include "OperatorPython.moc"
}

namespace tomviz {

class OperatorPython::OPInternals
{
public:
  vtkSmartPyObject OperatorModule;
  vtkSmartPyObject Code;
  vtkSmartPyObject TransformMethod;
};

OperatorPython::OperatorPython(QObject* parentObject)
  : Superclass(parentObject), Internals(new OperatorPython::OPInternals()),
    Label("Python Operator")
{
  vtkPythonInterpreter::Initialize();
  this->Internals->OperatorModule.TakeReference(
    PyImport_ImportModule("tomviz.utils"));
  if (!this->Internals->OperatorModule) {
    qCritical() << "Failed to import tomviz.utils module.";
    CheckForError();
  }
}

OperatorPython::~OperatorPython()
{
}

void OperatorPython::setLabel(const QString& txt)
{
  this->Label = txt;
  emit labelModified();
}

QIcon OperatorPython::icon() const
{
  return QIcon(":/pqWidgets/Icons/pqProgrammableFilter24.png");
}

void OperatorPython::setJSONDescription(const QString& str)
{
  if (this->jsonDescription == str) {
    return;
  }

  Json::Value root;
  Json::Reader reader;
  bool parsingSuccessful = reader.parse(str.toLatin1().data(), root);
  if (!parsingSuccessful) {
    qCritical() << "Failed to parse operator JSON";
    qCritical() << str;
    return;
  }

  // Get the label for the operator
  Json::Value labelNode = root["label"];
  if (!labelNode.isNull()) {
    setLabel(labelNode.asCString());
  }

  m_resultNames.clear();
  m_childDataSourceNamesAndLabels.clear();

  // Get the number of results
  Json::Value resultsNode = root["results"];
  if (!resultsNode.isNull()) {
    Json::Value::ArrayIndex numResults = resultsNode.size();
    setNumberOfResults(numResults);

    for (Json::Value::ArrayIndex i = 0; i < numResults; ++i) {
      OperatorResult* oa = resultAt(i);
      if (!oa) {
        Q_ASSERT(oa != nullptr);
      }
      Json::Value nameValue = resultsNode[i]["name"];
      if (!nameValue.isNull()) {
        oa->setName(nameValue.asCString());
        m_resultNames.append(nameValue.asCString());
      }
      Json::Value labelValue = resultsNode[i]["label"];
      if (!labelValue.isNull()) {
        oa->setLabel(labelValue.asCString());
      }
    }
  }

  // Get child dataset information
  Json::Value childDatasetNode = root["children"];
  if (!childDatasetNode.isNull()) {
    Json::Value::ArrayIndex size = childDatasetNode.size();
    if (size != 1) {
      qCritical() << "Only one child dataset is supported for now. Found"
                  << size << " but only the first will be used";
    }
    if (size > 0) {
      setHasChildDataSource(true);
      Json::Value nameValue = childDatasetNode[0]["name"];
      Json::Value labelValue = childDatasetNode[0]["label"];
      if (!nameValue.isNull() && !labelValue.isNull()) {
        QPair<QString, QString> nameLabelPair(QString(nameValue.asCString()),
                                              QString(labelValue.asCString()));
        m_childDataSourceNamesAndLabels.append(nameLabelPair);
      } else if (nameValue.isNull()) {
        qCritical() << "No name given for child DataSet";
      } else if (labelValue.isNull()) {
        qCritical() << "No label given for child DataSet";
      }
    }
  }
}

const QString& OperatorPython::JSONDescription() const
{
  return this->jsonDescription;
}

void OperatorPython::setScript(const QString& str)
{
  if (this->Script != str) {
    this->Script = str;
    this->Internals->Code.TakeReference(nullptr);
    this->Internals->TransformMethod.TakeReference(nullptr);

    this->Internals->Code.TakeReference(Py_CompileString(
      this->Script.toLatin1().data(), this->label().toLatin1().data(),
      Py_file_input /*Py_eval_input*/));
    if (!this->Internals->Code) {
      CheckForError();
      qCritical(
        "Invalid script. Please check the traceback message for details");
      return;
    }

    vtkSmartPyObject module;
    module.TakeReference(PyImport_ExecCodeModule(
      QString("tomviz_%1").arg(this->label()).toLatin1().data(),
      this->Internals->Code));
    if (!module) {
      CheckForError();
      qCritical("Failed to create module.");
      return;
    }

    this->Internals->TransformMethod.TakeReference(
      PyObject_GetAttrString(module, "transform_scalars"));
    if (!this->Internals->TransformMethod) {
      CheckForError();
      qWarning("Script doesn't have any 'transform_scalars' function.");
      return;
    }
    CheckForError();
    emit this->transformModified();
  }
}

bool OperatorPython::applyTransform(vtkDataObject* data)
{
  if (this->Script.isEmpty()) {
    return true;
  }
  if (!this->Internals->OperatorModule || !this->Internals->TransformMethod) {
    return true;
  }

  Q_ASSERT(data);

  vtkSmartPyObject pydata(vtkPythonUtil::GetObjectFromPointer(data));
  vtkSmartPyObject args(PyTuple_New(1));
  PyTuple_SET_ITEM(args.GetPointer(), 0, pydata.ReleaseReference());

  vtkSmartPyObject result;
  result.TakeReference(
    PyObject_Call(this->Internals->TransformMethod, args, nullptr));
  if (!result) {
    qCritical("Failed to execute the script.");
    CheckForError();
    return false;
  }

  // Look for additional outputs from the filter returned in a dictionary
  PyObject* outputDict = result.GetPointer();
  if (PyDict_Check(outputDict)) {
    bool errorEncountered = false;

    // Results (tables, etc.)
    for (int i = 0; i < m_resultNames.size(); ++i) {
      const char* name = m_resultNames[i].toLatin1().data();
      PyObject* pyDataObject = PyDict_GetItemString(outputDict, name);
      if (!pyDataObject) {
        errorEncountered = true;
        qCritical() << "No result named" << m_resultNames[i]
                    << "defined in output dictionary.\n";
        continue;
      }
      vtkObjectBase* vtkobject =
        vtkPythonUtil::GetPointerFromObject(pyDataObject, "vtkDataObject");
      vtkDataObject* dataObject = vtkDataObject::SafeDownCast(vtkobject);
      if (dataObject) {
        bool resultWasSet = setResult(name, dataObject);
        if (!resultWasSet) {
          qCritical() << "Could not set result '" << name << "'";
          continue;
        }
      } else {
        qCritical() << "Result named '" << name << "' is not a vtkDataObject";
        continue;
      }
    }

    // Segmentations, reconstructions, etc.
    for (int i = 0; i < m_childDataSourceNamesAndLabels.size(); ++i) {
      QPair<QString, QString> nameLabelPair =
        m_childDataSourceNamesAndLabels[i];
      QString name(nameLabelPair.first);
      QString label(nameLabelPair.second);
      PyObject* child = PyDict_GetItemString(outputDict, name.toLatin1().data());
      if (!child) {
        errorEncountered = true;
        qCritical() << "No child data source named '"
                    << name << "' defined in output dictionary.\n";
        continue;
      }

      vtkObjectBase* vtkobject =
        vtkPythonUtil::GetPointerFromObject(child, "vtkDataObject");
      vtkDataObject* childData = vtkDataObject::SafeDownCast(vtkobject);
      if (childData) {
        vtkSMProxyManager* proxyManager = vtkSMProxyManager::GetProxyManager();
        vtkSMSessionProxyManager* sessionProxyManager =
          proxyManager->GetActiveSessionProxyManager();

        vtkSmartPointer<vtkSMProxy> producerProxy;
        producerProxy.TakeReference(
          sessionProxyManager->NewProxy("sources", "TrivialProducer"));
        producerProxy->UpdateVTKObjects();

        vtkTrivialProducer* producer = vtkTrivialProducer::SafeDownCast(
          producerProxy->GetClientSideObject());
        if (!producer) {
          qWarning() << "Could not get TrivialProducer from proxy";
          return false;
        }

        producer->SetOutput(childData);

        DataSource* childDS =
          new DataSource(vtkSMSourceProxy::SafeDownCast(producerProxy),
                         DataSource::Volume, this);
        childDS->setFilename(label.toLatin1().data());
        setChildDataSource(childDS);
      }
    }

    if (errorEncountered) {
      PyObject* objectRepr = PyObject_Repr(outputDict);
      const char* objectReprString = PyString_AsString(objectRepr);
      qCritical() << "Dictionary return from Python script is:\n"
                  << objectReprString;

    }
  }

  return CheckForError() == false;
}

Operator* OperatorPython::clone() const
{
  OperatorPython* newClone = new OperatorPython();
  newClone->setLabel(this->label());
  newClone->setScript(this->script());
  newClone->setJSONDescription(this->JSONDescription());
  return newClone;
}

bool OperatorPython::serialize(pugi::xml_node& ns) const
{
  ns.append_attribute("label").set_value(this->label().toLatin1().data());
  ns.append_attribute("script").set_value(this->script().toLatin1().data());
  return true;
}

bool OperatorPython::deserialize(const pugi::xml_node& ns)
{
  this->setLabel(ns.attribute("label").as_string());
  this->setScript(ns.attribute("script").as_string());
  return true;
}

EditOperatorWidget* OperatorPython::getEditorContents(QWidget* p)
{
  return new EditPythonOperatorWidget(p, this);
}
}
<|endoftext|>


<commit_before>#include "RadioCalibrationWindow.h"

RadioCalibrationWindow::RadioCalibrationWindow(QWidget *parent) :
        QWidget(parent, Qt::Window),
        radio(new RadioCalibrationData())
{
    QGridLayout *grid = new QGridLayout();

    aileron = new AirfoilServoCalibrator(AirfoilServoCalibrator::AILERON);
    grid->addWidget(aileron, 0, 0, 1, 1, Qt::AlignTop);

    elevator = new AirfoilServoCalibrator(AirfoilServoCalibrator::ELEVATOR);
    grid->addWidget(elevator, 0, 1, 1, 1, Qt::AlignTop);

    rudder = new AirfoilServoCalibrator(AirfoilServoCalibrator::RUDDER);
    grid->addWidget(rudder, 0, 2, 1, 1, Qt::AlignTop);

    gyro = new SwitchCalibrator(tr("Gyro Mode/Gain"));
    grid->addWidget(gyro, 0, 3, 1, 1, Qt::AlignTop);

    pitch = new CurveCalibrator(tr("Collective Pitch"));
    grid->addWidget(pitch, 1, 0, 1, 2);

    throttle = new CurveCalibrator(tr("Throttle"));
    grid->addWidget(throttle, 1, 2, 1, 2);

    /* Buttons for loading/transmitting calibration data */
    QHBoxLayout *hbox = new QHBoxLayout();
    QPushButton *load = new QPushButton(tr("Load File"));
    QPushButton *save = new QPushButton(tr("Save File"));
    QPushButton *transmit = new QPushButton(tr("Transmit to UAV"));
    QPushButton *get = new QPushButton(tr("Get from UAV"));
    hbox->addWidget(load);
    hbox->addWidget(save);
    hbox->addWidget(transmit);
    hbox->addWidget(get);
    grid->addLayout(hbox, 2, 0, 1, 4);
    this->setLayout(grid);

    connect(load, SIGNAL(clicked()), this, SLOT(loadFile()));
    connect(save, SIGNAL(clicked()), this, SLOT(saveFile()));
    connect(transmit, SIGNAL(clicked()), this, SLOT(send()));
    connect(get, SIGNAL(clicked()), this, SLOT(request()));

    connect(aileron, SIGNAL(setpointChanged(int,float)), radio, SLOT(setAileron(int,float)));

    setUASId(0);
}

void RadioCalibrationWindow::setChannel(int ch, float raw, float normalized)
{
    /** this expects a particular channel to function mapping
       \todo allow run-time channel mapping
       */
    switch (ch)
    {
    case 0:
        aileron->channelChanged(raw);
        break;
    case 1:
        elevator->channelChanged(raw);
        break;
    case 2:
        throttle->channelChanged(raw);
        break;
    case 3:
        rudder->channelChanged(raw);
        break;
    case 4:
        gyro->channelChanged(raw);
        break;
    case 5:
        pitch->channelChanged(raw);
        break;

    }
}

void RadioCalibrationWindow::saveFile()
{
    qDebug() << __FILE__ << __LINE__ << "SAVE TO FILE";
}

void RadioCalibrationWindow::loadFile()
{
    qDebug() << __FILE__ << __LINE__ << "LOAD FROM FILE";
}

void RadioCalibrationWindow::send()
{
    qDebug() << __FILE__ << __LINE__ << "uasId = " << uasId;
#ifdef MAVLINK_ENABLED_UALBERTA_MESSAGES
    UAS *uas = dynamic_cast<UAS*>(UASManager::instance()->getUASForId(uasId));
    if (uas)
    {
        mavlink_message_t msg;
        mavlink_msg_radio_calibration_pack(uasId, 0, &msg,
                                           (*radio)[RadioCalibrationData::AILERON],
                                           (*radio)[RadioCalibrationData::ELEVATOR],
                                           (*radio)[RadioCalibrationData::RUDDER],
                                           (*radio)[RadioCalibrationData::GYRO],
                                           (*radio)[RadioCalibrationData::PITCH],
                                           (*radio)[RadioCalibrationData::THROTTLE]);
        uas->sendMessage(msg);
    }
#endif
}

void RadioCalibrationWindow::request()
{
    qDebug() << __FILE__ << __LINE__ << "READ FROM UAV";
    UAS *uas = dynamic_cast<UAS*>(UASManager::instance()->getUASForId(uasId));
    if (uas)
    {
        mavlink_message_t msg;
        mavlink_msg_action_pack(uasId, 0, &msg, 0, 0, ::MAV_ACTION_CALIBRATE_RC);
        uas->sendMessage(msg);
    }
}

void RadioCalibrationWindow::receive(const QPointer<RadioCalibrationData>& radio)
{
    if (radio)
    {
        if (this->radio)
            delete this->radio;
        this->radio = new RadioCalibrationData(*radio);

        aileron->set((*radio)(RadioCalibrationData::AILERON));
        elevator->set((*radio)(RadioCalibrationData::ELEVATOR));
        rudder->set((*radio)(RadioCalibrationData::RUDDER));
        gyro->set((*radio)(RadioCalibrationData::GYRO));
        pitch->set((*radio)(RadioCalibrationData::PITCH));
        throttle->set((*radio)(RadioCalibrationData::THROTTLE));
    }
}
<commit_msg>added connects for rest of channels<commit_after>#include "RadioCalibrationWindow.h"

RadioCalibrationWindow::RadioCalibrationWindow(QWidget *parent) :
        QWidget(parent, Qt::Window),
        radio(new RadioCalibrationData())
{
    QGridLayout *grid = new QGridLayout();

    aileron = new AirfoilServoCalibrator(AirfoilServoCalibrator::AILERON);
    grid->addWidget(aileron, 0, 0, 1, 1, Qt::AlignTop);

    elevator = new AirfoilServoCalibrator(AirfoilServoCalibrator::ELEVATOR);
    grid->addWidget(elevator, 0, 1, 1, 1, Qt::AlignTop);

    rudder = new AirfoilServoCalibrator(AirfoilServoCalibrator::RUDDER);
    grid->addWidget(rudder, 0, 2, 1, 1, Qt::AlignTop);

    gyro = new SwitchCalibrator(tr("Gyro Mode/Gain"));
    grid->addWidget(gyro, 0, 3, 1, 1, Qt::AlignTop);

    pitch = new CurveCalibrator(tr("Collective Pitch"));
    grid->addWidget(pitch, 1, 0, 1, 2);

    throttle = new CurveCalibrator(tr("Throttle"));
    grid->addWidget(throttle, 1, 2, 1, 2);

    /* Buttons for loading/transmitting calibration data */
    QHBoxLayout *hbox = new QHBoxLayout();
    QPushButton *load = new QPushButton(tr("Load File"));
    QPushButton *save = new QPushButton(tr("Save File"));
    QPushButton *transmit = new QPushButton(tr("Transmit to UAV"));
    QPushButton *get = new QPushButton(tr("Get from UAV"));
    hbox->addWidget(load);
    hbox->addWidget(save);
    hbox->addWidget(transmit);
    hbox->addWidget(get);
    grid->addLayout(hbox, 2, 0, 1, 4);
    this->setLayout(grid);

    connect(load, SIGNAL(clicked()), this, SLOT(loadFile()));
    connect(save, SIGNAL(clicked()), this, SLOT(saveFile()));
    connect(transmit, SIGNAL(clicked()), this, SLOT(send()));
    connect(get, SIGNAL(clicked()), this, SLOT(request()));

    connect(aileron, SIGNAL(setpointChanged(int,float)), radio, SLOT(setAileron(int,float)));
    connect(elevator, SIGNAL(setpointChanged(int,float)), radio, SLOT(setElevator(int,float)));
    connect(rudder, SIGNAL(setpointChanged(int,float)), radio, SLOT(setRudder(int,float)));
    connect(gyro, SIGNAL(setpointChanged(int,float)), radio, SLOT(setGyro(int,float)));
    connect(pitch, SIGNAL(setpointChanged(int,float)), radio, SLOT(setPitch(int,float)));
    connect(throttle, SIGNAL(setpointChanged(int,float)), radio, SLOT(setThrottle(int,float)));
    setUASId(0);
}

void RadioCalibrationWindow::setChannel(int ch, float raw, float normalized)
{
    /** this expects a particular channel to function mapping
       \todo allow run-time channel mapping
       */
    switch (ch)
    {
    case 0:
        aileron->channelChanged(raw);
        break;
    case 1:
        elevator->channelChanged(raw);
        break;
    case 2:
        throttle->channelChanged(raw);
        break;
    case 3:
        rudder->channelChanged(raw);
        break;
    case 4:
        gyro->channelChanged(raw);
        break;
    case 5:
        pitch->channelChanged(raw);
        break;

    }
}

void RadioCalibrationWindow::saveFile()
{
    qDebug() << __FILE__ << __LINE__ << "SAVE TO FILE";
}

void RadioCalibrationWindow::loadFile()
{
    qDebug() << __FILE__ << __LINE__ << "LOAD FROM FILE";
}

void RadioCalibrationWindow::send()
{
    qDebug() << __FILE__ << __LINE__ << "uasId = " << uasId;
#ifdef MAVLINK_ENABLED_UALBERTA_MESSAGES
    UAS *uas = dynamic_cast<UAS*>(UASManager::instance()->getUASForId(uasId));
    if (uas)
    {
        mavlink_message_t msg;
        mavlink_msg_radio_calibration_pack(uasId, 0, &msg,
                                           (*radio)[RadioCalibrationData::AILERON],
                                           (*radio)[RadioCalibrationData::ELEVATOR],
                                           (*radio)[RadioCalibrationData::RUDDER],
                                           (*radio)[RadioCalibrationData::GYRO],
                                           (*radio)[RadioCalibrationData::PITCH],
                                           (*radio)[RadioCalibrationData::THROTTLE]);
        uas->sendMessage(msg);
    }
#endif
}

void RadioCalibrationWindow::request()
{
    qDebug() << __FILE__ << __LINE__ << "READ FROM UAV";
    UAS *uas = dynamic_cast<UAS*>(UASManager::instance()->getUASForId(uasId));
    if (uas)
    {
        mavlink_message_t msg;
        mavlink_msg_action_pack(uasId, 0, &msg, 0, 0, ::MAV_ACTION_CALIBRATE_RC);
        uas->sendMessage(msg);
    }
}

void RadioCalibrationWindow::receive(const QPointer<RadioCalibrationData>& radio)
{
    if (radio)
    {
        if (this->radio)
            delete this->radio;
        this->radio = new RadioCalibrationData(*radio);

        aileron->set((*radio)(RadioCalibrationData::AILERON));
        elevator->set((*radio)(RadioCalibrationData::ELEVATOR));
        rudder->set((*radio)(RadioCalibrationData::RUDDER));
        gyro->set((*radio)(RadioCalibrationData::GYRO));
        pitch->set((*radio)(RadioCalibrationData::PITCH));
        throttle->set((*radio)(RadioCalibrationData::THROTTLE));
    }
}
<|endoftext|>