<commit_before>/*
 * Copyright (c) 2018 jmjatlanta and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

// below are for random bytes for htlc
#include <vector>
#include <random>
#include <climits>
#include <algorithm>
#include <functional>
// for htlc timeout
#include <chrono>
#include <thread>

#include <boost/test/unit_test.hpp>

#include <boost/container/flat_set.hpp>

#include <fc/optional.hpp>

#include <graphene/chain/protocol/htlc.hpp>

#include <graphene/chain/database.hpp>
#include <graphene/chain/hardfork.hpp>

#include <graphene/chain/balance_object.hpp>
#include <graphene/chain/htlc_object.hpp>
#include <graphene/chain/market_object.hpp>

#include <graphene/app/api.hpp>

#include "../common/database_fixture.hpp"

using namespace graphene::chain;
using namespace graphene::chain::test;

BOOST_FIXTURE_TEST_SUITE( htlc_tests, database_fixture )

void generate_random_preimage(uint16_t key_size, std::vector<unsigned char>& vec)
{
	std::independent_bits_engine<std::default_random_engine, CHAR_BIT, unsigned char> rbe;
	std::generate(begin(vec), end(vec), std::ref(rbe));
	return;
}

std::vector<unsigned char> hash_it(std::vector<unsigned char> preimage)
{
	fc::sha256 hash = fc::sha256::hash(preimage);
	std::vector<unsigned char> ret_val(hash.data_size());
	char* data = hash.data();
	for(size_t i = 0; i < hash.data_size(); i++)
	{
		ret_val[i] = data[i];
	}
	return ret_val;
}

BOOST_AUTO_TEST_CASE( htlc_expires )
{
   ACTORS((alice)(bob));

   int64_t init_balance(100000);

   transfer( committee_account, alice_id, graphene::chain::asset(init_balance) );

   uint16_t key_size = 256;
   std::vector<unsigned char> pre_image(256);
   generate_random_preimage(key_size, pre_image);
   std::vector<unsigned char> key_hash = hash_it(pre_image);

   graphene::chain::htlc_id_type alice_htlc_id;
   // cler everything out
   generate_block();
   trx.clear();
   // Alice puts a contract on the blockchain
   {
      graphene::chain::htlc_create_operation create_operation;

      create_operation.amount = graphene::chain::asset( 10000 );
      create_operation.destination = bob_id;
      create_operation.epoch = fc::time_point::now() + fc::seconds(3);
      create_operation.key_hash = key_hash;
      create_operation.key_size = key_size;
      create_operation.source = alice_id;
      trx.operations.push_back(create_operation);
      sign(trx, alice_private_key);
      try
      {
    	  PUSH_TX(db, trx, ~0);
      } catch (fc::exception& ex)
      {
    	  BOOST_FAIL( ex.to_detail_string(fc::log_level(fc::log_level::all)) );
      }
      trx.clear();
      graphene::chain::signed_block blk = generate_block();
      // can we assume that alice's transaction will be the only one in this block?
      processed_transaction alice_trx = blk.transactions[0];
      alice_htlc_id = alice_trx.operation_results[0].get<object_id_type>();
   }

   // verify funds on hold (make sure this can cover fees)
   BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 90000 );

   // make sure Alice can't get it back before the timeout
   {
      graphene::chain::htlc_update_operation update_operation;
      update_operation.update_issuer = alice_id;
      update_operation.htlc_id = alice_htlc_id;
      trx.operations.push_back(update_operation);
      sign(trx, alice_private_key);
      try
      {
          PUSH_TX(db, trx, ~0);
          BOOST_FAIL("Should not allow Alice to reclaim funds before timeout");
      } catch (fc::exception& ex)
      {
    	  // this should happen
      }
      generate_block();
      trx.clear();
   }

   // make sure Alice can't spend it.
   // make sure Bob (or anyone) can see the details of the transaction
   // let it expire (wait for timeout)
   std::this_thread::sleep_for(std::chrono::seconds(4));
   // send an update operation to reclaim the funds
   {
      graphene::chain::htlc_update_operation update_operation;
      update_operation.update_issuer = alice_id;
      update_operation.htlc_id = alice_htlc_id;
      trx.operations.push_back(update_operation);
      sign(trx, alice_private_key);
      try
      {
          PUSH_TX(db, trx, ~0);
      } catch (fc::exception& ex)
      {
          BOOST_FAIL(ex.to_detail_string(fc::log_level(fc::log_level::all)));
      }
      generate_block();
      trx.clear();
   }
   // verify funds return (what about fees?)
   BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 100000 );
   // verify Bob cannot execute the contract after the fact
}

BOOST_AUTO_TEST_CASE( htlc_fulfilled )
{
	   ACTORS((alice)(bob));

	   int64_t init_balance(100000);

	   transfer( committee_account, alice_id, graphene::chain::asset(init_balance) );

	   uint16_t key_size = 256;
	   std::vector<unsigned char> pre_image(256);
	   generate_random_preimage(key_size, pre_image);
	   std::vector<unsigned char> key_hash = hash_it(pre_image);

	   graphene::chain::htlc_id_type alice_htlc_id;
	   // cler everything out
	   generate_block();
	   trx.clear();
	   // Alice puts a contract on the blockchain
	   {
	      graphene::chain::htlc_create_operation create_operation;

	      create_operation.amount = graphene::chain::asset( 10000 );
	      create_operation.destination = bob_id;
	      create_operation.epoch = fc::time_point::now() + fc::seconds(3);
	      create_operation.key_hash = key_hash;
	      create_operation.key_size = key_size;
	      create_operation.source = alice_id;
	      trx.operations.push_back(create_operation);
	      sign(trx, alice_private_key);
	      try
	      {
	    	  PUSH_TX(db, trx, ~0);
	      } catch (fc::exception& ex)
	      {
	    	  BOOST_FAIL( ex.to_detail_string(fc::log_level(fc::log_level::all)) );
	      }
	      trx.clear();
	      graphene::chain::signed_block blk = generate_block();
	      // can we assume that alice's transaction will be the only one in this block?
	      processed_transaction alice_trx = blk.transactions[0];
	      alice_htlc_id = alice_trx.operation_results[0].get<object_id_type>();
	   }

	   // verify funds on hold (make sure this can cover fees)
	   BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 90000 );

	   // make sure Alice can't get it back before the timeout
	   {
	      graphene::chain::htlc_update_operation update_operation;
	      update_operation.update_issuer = alice_id;
	      update_operation.htlc_id = alice_htlc_id;
	      trx.operations.push_back(update_operation);
	      sign(trx, alice_private_key);
	      try
	      {
	          PUSH_TX(db, trx, ~0);
	          BOOST_FAIL("Should not allow Alice to reclaim funds before timeout");
	      } catch (fc::exception& ex)
	      {
	    	  // this should happen
	      }
	      generate_block();
	      trx.clear();
	   }

	   // balance should not have changed
	   BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 90000 );
	   // make sure Bob (or anyone) can see the details of the transaction
	   // send an update operation to claim the funds
	   {
	      graphene::chain::htlc_update_operation update_operation;
	      update_operation.update_issuer = bob_id;
	      update_operation.htlc_id = alice_htlc_id;
	      update_operation.preimage = pre_image;
	      trx.operations.push_back(update_operation);
	      sign(trx, bob_private_key);
	      try
	      {
	          PUSH_TX(db, trx, ~0);
	      } catch (fc::exception& ex)
	      {
	          BOOST_FAIL(ex.to_detail_string(fc::log_level(fc::log_level::all)));
	      }
	      generate_block();
	      trx.clear();
	   }
	   // verify Alice cannot execute the contract after the fact
	   {
	      graphene::chain::htlc_update_operation update_operation;
	      update_operation.update_issuer = alice_id;
	      update_operation.htlc_id = alice_htlc_id;
	      trx.operations.push_back(update_operation);
	      sign(trx, alice_private_key);
	      try
	      {
	          PUSH_TX(db, trx, ~0);
	          BOOST_FAIL("Should not allow Alice to reclaim funds after Bob already claimed them.");
	      } catch (fc::exception& ex)
	      {
	    	  // this should happen
	      }
	      generate_block();
	      trx.clear();
	   }
	   // verify funds end up in Bob's account
	   BOOST_CHECK_EQUAL( get_balance(bob_id,   graphene::chain::asset_id_type()), 10000 );
	   BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 90000 );
}

BOOST_AUTO_TEST_CASE( other_peoples_money )
{
   ACTORS((alice)(bob));

   int64_t init_balance(100000);

   transfer( committee_account, alice_id, graphene::chain::asset(init_balance) );

   uint16_t key_size = 256;
   std::vector<unsigned char> pre_image(256);
   generate_random_preimage(key_size, pre_image);
   std::vector<unsigned char> key_hash = hash_it(pre_image);

   graphene::chain::htlc_id_type alice_htlc_id;
   // cler everything out
   generate_block();
   trx.clear();
   // Bob attempts to put a contract on the blockchain using Alice's funds
   {
      graphene::chain::htlc_create_operation create_operation;
      create_operation.amount = graphene::chain::asset( 10000 );
      create_operation.destination = bob_id;
      create_operation.epoch = fc::time_point::now() + fc::seconds(3);
      create_operation.key_hash = key_hash;
      create_operation.key_size = key_size;
      create_operation.source = alice_id;
      trx.operations.push_back(create_operation);
      sign(trx, bob_private_key);
      try
      {
    	  PUSH_TX(db, trx, database::skip_nothing);
    	  BOOST_FAIL( "Bob stole money from Alice!" );
      } catch (fc::exception& ex)
      {
         // this is supposed to happen
         //BOOST_TEST_MESSAGE("This is the error thrown (expected):");
         //BOOST_TEST_MESSAGE(ex.to_detail_string(fc::log_level(fc::log_level::all)));
      }
      trx.clear();
   }
   // now try the same but with Alice's signature (should work)
   {
      graphene::chain::htlc_create_operation create_operation;
      create_operation.amount = graphene::chain::asset( 10000 );
      create_operation.destination = bob_id;
      create_operation.epoch = fc::time_point::now() + fc::seconds(3);
      create_operation.key_hash = key_hash;
      create_operation.key_size = key_size;
      create_operation.source = alice_id;
      trx.operations.push_back(create_operation);
      sign(trx, alice_private_key);
      try
      {
         PUSH_TX(db, trx, database::skip_nothing);
      } catch (fc::exception& ex)
      {
    	   BOOST_FAIL( "Alice cannot create a contract!" );
      }
      trx.clear();
   }
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Test cleanup. Hardfork protection still needed.<commit_after>/*
 * Copyright (c) 2018 jmjatlanta and contributors.
 *
 * The MIT License
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

// below are for random bytes for htlc
#include <vector>
#include <random>
#include <climits>
#include <algorithm>
#include <functional>
// for htlc timeout
#include <chrono>
#include <thread>

#include <boost/test/unit_test.hpp>

#include <boost/container/flat_set.hpp>

#include <fc/optional.hpp>

#include <graphene/chain/protocol/htlc.hpp>

#include <graphene/chain/database.hpp>
#include <graphene/chain/hardfork.hpp>

#include <graphene/chain/balance_object.hpp>
#include <graphene/chain/htlc_object.hpp>
#include <graphene/chain/market_object.hpp>

#include <graphene/app/api.hpp>

#include "../common/database_fixture.hpp"

using namespace graphene::chain;
using namespace graphene::chain::test;

BOOST_FIXTURE_TEST_SUITE( htlc_tests, database_fixture )

void generate_random_preimage(uint16_t key_size, std::vector<unsigned char>& vec)
{
	std::independent_bits_engine<std::default_random_engine, CHAR_BIT, unsigned char> rbe;
	std::generate(begin(vec), end(vec), std::ref(rbe));
	return;
}

std::vector<unsigned char> hash_it(std::vector<unsigned char> preimage)
{
   // convert the preimage to a char array
   unsigned char char_array[preimage.size()];
   for(unsigned int i = 0; i < preimage.size(); ++i)
      char_array[i] = preimage[i];
	fc::sha256 hash = fc::sha256::hash((char*)char_array, preimage.size());
	std::vector<unsigned char> ret_val(hash.data_size());
	char* data = hash.data();
	for(size_t i = 0; i < hash.data_size(); i++)
	{
		ret_val[i] = data[i];
	}
	return ret_val;
}

void set_committee_parameters(database_fixture* db_fixture)
{
   // set the committee parameters
   db_fixture->db.modify(db_fixture->db.get_global_properties(), [](global_property_object& p) {
      graphene::chain::committee_updatable_parameters params;
      params.htlc_max_preimage_size = 1024;
      params.htlc_max_timeout_secs = 60 * 60 * 24 * 28;
      p.parameters.extensions.value.committee_updatable_options = params;
   });
}

BOOST_AUTO_TEST_CASE( htlc_expires )
{
   set_committee_parameters(this);

   ACTORS((alice)(bob));

   int64_t init_balance(100000);

   transfer( committee_account, alice_id, graphene::chain::asset(init_balance) );

   uint16_t key_size = 256;
   std::vector<unsigned char> pre_image(256);
   generate_random_preimage(key_size, pre_image);
   std::vector<unsigned char> key_hash = hash_it(pre_image);

   graphene::chain::htlc_id_type alice_htlc_id;
   // cler everything out
   generate_block();
   trx.clear();
   fc::time_point_sec expiration = db.head_block_time() + fc::seconds(60);
   // Alice puts a contract on the blockchain
   {
      graphene::chain::htlc_create_operation create_operation;

      create_operation.amount = graphene::chain::asset( 10000 );
      create_operation.destination = bob_id;
      create_operation.epoch = expiration;
      create_operation.key_hash = key_hash;
      create_operation.hash_type = graphene::chain::hash_algorithm::sha256;
      create_operation.key_size = key_size;
      create_operation.source = alice_id;
      trx.operations.push_back(create_operation);
      sign(trx, alice_private_key);
      try
      {
    	  PUSH_TX(db, trx, ~0);
      } catch (fc::exception& ex)
      {
    	  BOOST_FAIL( ex.to_detail_string(fc::log_level(fc::log_level::all)) );
      }
      trx.clear();
      graphene::chain::signed_block blk = generate_block();
      // can we assume that alice's transaction will be the only one in this block?
      processed_transaction alice_trx = blk.transactions[0];
      alice_htlc_id = alice_trx.operation_results[0].get<object_id_type>();
      generate_block();
   }

   // verify funds on hold (TODO: make sure this can cover fees)
   BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 90000 );

   // make sure Bob (or anyone) can see the details of the transaction
   graphene::app::database_api db_api(db);
   optional<graphene::chain::htlc_object> htlc = db_api.get_htlc(fc::json::to_pretty_string(alice_htlc_id));
   BOOST_CHECK(htlc);

   // let it expire (wait for timeout)
   generate_blocks(expiration + fc::seconds(120) );
   // verify funds return (what about fees?)
   BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 100000 );
   // verify Bob cannot execute the contract after the fact
}

BOOST_AUTO_TEST_CASE( htlc_fulfilled )
{
   set_committee_parameters(this);

   ACTORS((alice)(bob));

   int64_t init_balance(100000);

   transfer( committee_account, alice_id, graphene::chain::asset(init_balance) );

   uint16_t key_size = 256;
   std::vector<unsigned char> pre_image(key_size);
   generate_random_preimage(key_size, pre_image);
   std::vector<unsigned char> key_hash = hash_it(pre_image);

   graphene::chain::htlc_id_type alice_htlc_id;
   // cler everything out
   generate_block();
   trx.clear();
   // Alice puts a contract on the blockchain
   {
      graphene::chain::htlc_create_operation create_operation;

      create_operation.amount = graphene::chain::asset( 10000 );
      create_operation.destination = bob_id;
      create_operation.epoch = db.head_block_time() + fc::seconds(10);
      create_operation.key_hash = key_hash;
      create_operation.hash_type = graphene::chain::hash_algorithm::sha256;
      create_operation.key_size = key_size;
      create_operation.source = alice_id;
      trx.operations.push_back(create_operation);
      sign(trx, alice_private_key);
      try
      {
         PUSH_TX(db, trx, ~0);
      } catch (fc::exception& ex)
      {
         BOOST_FAIL( ex.to_detail_string(fc::log_level(fc::log_level::all)) );
      }
      trx.clear();
      graphene::chain::signed_block blk = generate_block();
      // can we assume that alice's transaction will be the only one in this block?
      processed_transaction alice_trx = blk.transactions[0];
      alice_htlc_id = alice_trx.operation_results[0].get<object_id_type>();
   }

   // verify funds on hold (make sure this can cover fees)
   BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 90000 );

   // TODO: make sure Bob (or anyone) can see the details of the transaction

   // send an update operation to claim the funds
   {
      graphene::chain::htlc_update_operation update_operation;
      update_operation.update_issuer = bob_id;
      update_operation.htlc_id = alice_htlc_id;
      update_operation.preimage = pre_image;
      trx.operations.push_back(update_operation);
      sign(trx, bob_private_key);
      try
      {
            PUSH_TX(db, trx, ~0);
      } catch (fc::exception& ex)
      {
            BOOST_FAIL(ex.to_detail_string(fc::log_level(fc::log_level::all)));
      }
      generate_block();
      trx.clear();
   }
   // verify Alice cannot execute the contract after the fact
   {
      graphene::chain::htlc_update_operation update_operation;
      update_operation.update_issuer = alice_id;
      update_operation.htlc_id = alice_htlc_id;
      trx.operations.push_back(update_operation);
      sign(trx, alice_private_key);
      try
      {
            PUSH_TX(db, trx, ~0);
            BOOST_FAIL("Should not allow Alice to reclaim funds after Bob already claimed them.");
      } catch (fc::exception& ex)
      {
         // this should happen
      }
      generate_block();
      trx.clear();
   }
   // verify funds end up in Bob's account
   BOOST_CHECK_EQUAL( get_balance(bob_id,   graphene::chain::asset_id_type()), 10000 );
   BOOST_CHECK_EQUAL( get_balance(alice_id, graphene::chain::asset_id_type()), 90000 );
}

BOOST_AUTO_TEST_CASE( other_peoples_money )
{
   set_committee_parameters(this);

   ACTORS((alice)(bob));

   int64_t init_balance(100000);

   transfer( committee_account, alice_id, graphene::chain::asset(init_balance) );

   uint16_t key_size = 256;
   std::vector<unsigned char> pre_image(256);
   generate_random_preimage(key_size, pre_image);
   std::vector<unsigned char> key_hash = hash_it(pre_image);

   graphene::chain::htlc_id_type alice_htlc_id;
   // cler everything out
   generate_block();
   trx.clear();
   // Bob attempts to put a contract on the blockchain using Alice's funds
   {
      graphene::chain::htlc_create_operation create_operation;
      create_operation.amount = graphene::chain::asset( 10000 );
      create_operation.destination = bob_id;
      create_operation.epoch = db.head_block_time() + fc::seconds(3);
      create_operation.key_hash = key_hash;
      create_operation.key_size = key_size;
      create_operation.source = alice_id;
      trx.operations.push_back(create_operation);
      sign(trx, bob_private_key);
      try
      {
    	  PUSH_TX(db, trx, database::skip_nothing);
    	  BOOST_FAIL( "Bob stole money from Alice!" );
      } catch (fc::exception& ex)
      {
         // this is supposed to happen
         //BOOST_TEST_MESSAGE("This is the error thrown (expected):");
         //BOOST_TEST_MESSAGE(ex.to_detail_string(fc::log_level(fc::log_level::all)));
      }
      trx.clear();
   }
   // now try the same but with Alice's signature (should work)
   {
      graphene::chain::htlc_create_operation create_operation;
      create_operation.amount = graphene::chain::asset( 10000 );
      create_operation.destination = bob_id;
      create_operation.epoch = db.head_block_time() + fc::seconds(3);
      create_operation.key_hash = key_hash;
      create_operation.hash_type = graphene::chain::hash_algorithm::sha256;
      create_operation.key_size = key_size;
      create_operation.source = alice_id;
      trx.operations.push_back(create_operation);
      sign(trx, alice_private_key);
      try
      {
         PUSH_TX(db, trx, database::skip_nothing);
      } catch (fc::exception& ex)
      {
    	   BOOST_FAIL( "Alice cannot create a contract!" );
      }
      trx.clear();
   }
}

BOOST_AUTO_TEST_CASE( set_htlc_params )
{ try {
   set_committee_parameters(this);

   BOOST_TEST_MESSAGE( "Creating a proposal to change the max_preimage_size to 2048" );
   {
      proposal_create_operation cop = proposal_create_operation::committee_proposal(db.get_global_properties().parameters, db.head_block_time());
      cop.fee_paying_account = GRAPHENE_TEMP_ACCOUNT;
      cop.expiration_time = db.head_block_time() + *cop.review_period_seconds + 10;
      committee_member_update_global_parameters_operation uop;
      graphene::chain::committee_updatable_parameters new_params;
      new_params.htlc_max_preimage_size = 2048;
      new_params.htlc_max_timeout_secs = 60 * 60 * 24 * 28;
      uop.new_parameters.extensions.value.committee_updatable_options = new_params;
      cop.proposed_ops.emplace_back(uop);
      trx.operations.push_back(cop);
      db.push_transaction(trx);
   }
   BOOST_TEST_MESSAGE( "Updating proposal by signing with the committee_member private key" );
   {
      proposal_update_operation uop;
      uop.fee_paying_account = GRAPHENE_TEMP_ACCOUNT;
      uop.active_approvals_to_add = {get_account("init0").get_id(), get_account("init1").get_id(),
                                     get_account("init2").get_id(), get_account("init3").get_id(),
                                     get_account("init4").get_id(), get_account("init5").get_id(),
                                     get_account("init6").get_id(), get_account("init7").get_id()};
      trx.operations.push_back(uop);
      sign( trx, init_account_priv_key );
      db.push_transaction(trx);
      BOOST_CHECK(proposal_id_type()(db).is_authorized_to_execute(db));
   }
   BOOST_TEST_MESSAGE( "Verifying that the parameters didn't change immediately" );

   BOOST_CHECK_EQUAL(db.get_global_properties().parameters.extensions.value.committee_updatable_options->htlc_max_preimage_size, 1024u);

   BOOST_TEST_MESSAGE( "Generating blocks until proposal expires" );
   generate_blocks(proposal_id_type()(db).expiration_time + 5);
   BOOST_TEST_MESSAGE( "Verify that the parameters still have not changed" );
   BOOST_CHECK_EQUAL(db.get_global_properties().parameters.extensions.value.committee_updatable_options->htlc_max_preimage_size, 1024u);

   BOOST_TEST_MESSAGE( "Generating blocks until next maintenance interval" );
   generate_blocks(db.get_dynamic_global_properties().next_maintenance_time);
   generate_block();   // get the maintenance skip slots out of the way

   BOOST_TEST_MESSAGE( "Verify that the change has been implemented" );
   BOOST_CHECK_EQUAL(db.get_global_properties().parameters.extensions.value.committee_updatable_options->htlc_max_preimage_size, 2048u);
} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2015, Hazelcast, Inc. All Rights Reserved.
 *
 * 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.
 */
//
// Created by sancar koyunlu on 6/3/13.
#include "hazelcast/util/Thread.h"
#include "hazelcast/client/spi/PartitionService.h"
#include "hazelcast/client/spi/ClusterService.h"
#include "hazelcast/client/spi/LifecycleService.h"
#include "hazelcast/client/spi/InvocationService.h"
#include "hazelcast/client/serialization/pimpl/SerializationService.h"
#include "hazelcast/client/spi/ClientContext.h"
#include "hazelcast/client/exception/IllegalStateException.h"
#include "hazelcast/client/connection/CallFuture.h"
#include "hazelcast/client/protocol/codec/ClientGetPartitionsCodec.h"

#include <climits>

#include <vector>

namespace hazelcast {
    namespace client {
        namespace spi {
            PartitionService::PartitionService(spi::ClientContext& clientContext)
            : clientContext(clientContext)
            , updating(false)
            , partitionCount(0) {

            }

            bool PartitionService::start() {
                // No need to hold the lock here since it is called by the LifeCycleService start in initialization only
                // from only one thread.
                if (!getInitialPartitions()) {
                    return false;
                }
                util::Thread *partitionListener = new util::Thread("hz.partitionListener", PartitionService::staticRunListener, this);
                partitionListenerThread.reset(partitionListener);
                return true;
            }

            void PartitionService::shutdown() {
                util::LockGuard lg(lock);
                if (partitionListenerThread.get() != NULL) {
                    partitionListenerThread->cancel();
                    partitionListenerThread->join();
                }
            }

            boost::shared_ptr<Address> PartitionService::getPartitionOwner(int partitionId) {
                // TODO: Use Read/Write Lock instead, it is read most of the time
                util::LockGuard lg(lock);
                std::map<int, boost::shared_ptr<Address> >::iterator it = partitions->find(partitionId);
                if (partitions->end() != it) {
                    return it->second;
                } else {
                    return boost::shared_ptr<Address>();
                }
            }

            int PartitionService::getPartitionId(const serialization::pimpl::Data& key) {
                const int pc = partitionCount;
                int hash = key.getPartitionHash();
                return (hash == INT_MIN) ? 0 : abs(hash) % pc;
            }

            void PartitionService::staticRunListener(util::ThreadArgs& args) {
                PartitionService *partitionService = (PartitionService *)args.arg0;
                partitionService->runListener(args.currentThread);
            }

            void PartitionService::runListener(util::Thread *currentThread) {
                while (clientContext.getLifecycleService().isRunning()) {
                    try {
                        currentThread->interruptibleSleep(10);
                        if (!clientContext.getLifecycleService().isRunning()) {
                            break;
                        }
                        refreshPartitions();
                    } catch (exception::IException& e) {
                        util::ILogger::getLogger().warning(std::string("PartitionService::runListener") + e.what());
                    }
                }
            }

            std::auto_ptr<protocol::ClientMessage> PartitionService::getPartitionsFrom(const Address& address) {
                std::auto_ptr<protocol::ClientMessage> responseMessage;
                try {
                    std::auto_ptr<protocol::ClientMessage> requestMessage = protocol::codec::ClientGetPartitionsCodec::RequestParameters::encode();

                    connection::CallFuture future = clientContext.getInvocationService().invokeOnTarget(
                            requestMessage, address);

                    responseMessage = future.get();

                } catch (exception::IOException& e) {
                    util::ILogger::getLogger().severe(std::string("Error while fetching cluster partition table => ") + e.what());
                }
                return responseMessage;
            }

            std::auto_ptr<protocol::ClientMessage> PartitionService::getPartitionsFrom() {
                std::auto_ptr<protocol::ClientMessage> responseMessage;
                try {
                    std::auto_ptr<protocol::ClientMessage> requestMessage = protocol::codec::ClientGetPartitionsCodec::RequestParameters::encode();

                    connection::CallFuture future = clientContext.getInvocationService().invokeOnRandomTarget(
                            requestMessage);

                    responseMessage = future.get();

                } catch (exception::IOException& e) {
                    util::ILogger::getLogger().severe(std::string("Error while fetching cluster partition table => ") + e.what());
                }
                return responseMessage;
            }

            bool PartitionService::processPartitionResponse(protocol::ClientMessage &response) {
                protocol::codec::ClientGetPartitionsCodec::ResponseParameters result =
                        protocol::codec::ClientGetPartitionsCodec::ResponseParameters::decode(response);

                std::auto_ptr<std::map<int, boost::shared_ptr<Address> > > newPartitions(new std::map<int, boost::shared_ptr<Address> >());
                for (std::vector<std::pair<Address, std::vector<int32_t > > >::const_iterator it = result.partitions.begin();
                     it != result.partitions.end(); ++it) {
                    boost::shared_ptr<Address> addr(new Address(it->first));
                    for (std::vector<int32_t>::const_iterator partIt = it->second.begin(); partIt != it->second.end(); ++partIt) {
                        (*newPartitions)[*partIt] = addr;
                    }
                }

                int newPartionCount = (int)newPartitions->size();
                if (newPartionCount > 0) {
                    util::LockGuard lg(lock);

                    partitions = newPartitions;

                    partitionCount = newPartionCount;

                    return true;
                } else {
                    return false;
                }
            }

            bool PartitionService::getInitialPartitions() {
                bool result = false;
                std::vector<Member> memberList = clientContext.getClusterService().getMemberList();
                for (std::vector<Member>::iterator it = memberList.begin(); it < memberList.end(); ++it) {
                    const Address &target = (*it).getAddress();
                    std::auto_ptr<protocol::ClientMessage> response = getPartitionsFrom(target);
                    if (response.get() != NULL) {
                        result = processPartitionResponse(*response);

                        if (result) {
                            break;
                        }
                    }
                }

                if (!result) {
                    util::ILogger::getLogger().severe("PartitionService::getInitialPartitions Cannot get initial partitions!");
                } else {
                    util::ILogger::getLogger().finest("PartitionService::getInitialPartitions Got " +
                                                              util::IOUtil::to_string<int>(partitionCount) +
                                                              " initial partitions successfully.");
                }
                return result;
            }

            // TODO: Implement using executor as done in java (especially when the separate owner connection implementation is changed)
            void PartitionService::refreshPartitions() {
                if (updating.compareAndSet(false, true)) {
                    try {
                        std::auto_ptr<protocol::ClientMessage> partitionResponse;
                        std::auto_ptr<Address> ptr = clientContext.getClusterService().getMasterAddress();
                        if (ptr.get() == NULL) {
                            partitionResponse = getPartitionsFrom();
                        } else {
                            partitionResponse = getPartitionsFrom(*ptr.get());
                        }
                        if (partitionResponse.get() != NULL) {
                            processPartitionResponse(*partitionResponse);
                        }
                    } catch (hazelcast::client::exception::IException& e) {
                        util::ILogger::getLogger().finest(std::string("Exception in partitionService::refreshPartitions ") + e.what());
                    } catch (...) {
                        util::ILogger::getLogger().finest(std::string("Unkown exception in partitionService::refreshPartitions "));
                        throw;
                    }
                    updating = false;
                }
            }

            void PartitionService::wakeup() {
                if (NULL != partitionListenerThread.get()) {
                    partitionListenerThread->wakeup();
                }
            }
        }
    }
}

<commit_msg>Removed the lock usage in PartitionService shutdown, since it was causing deadlock in Windows environment maintenance nightly builds.<commit_after>/*
 * Copyright (c) 2008-2015, Hazelcast, Inc. All Rights Reserved.
 *
 * 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.
 */
//
// Created by sancar koyunlu on 6/3/13.
#include "hazelcast/util/Thread.h"
#include "hazelcast/client/spi/PartitionService.h"
#include "hazelcast/client/spi/ClusterService.h"
#include "hazelcast/client/spi/LifecycleService.h"
#include "hazelcast/client/spi/InvocationService.h"
#include "hazelcast/client/serialization/pimpl/SerializationService.h"
#include "hazelcast/client/spi/ClientContext.h"
#include "hazelcast/client/exception/IllegalStateException.h"
#include "hazelcast/client/connection/CallFuture.h"
#include "hazelcast/client/protocol/codec/ClientGetPartitionsCodec.h"

#include <climits>

#include <vector>

namespace hazelcast {
    namespace client {
        namespace spi {
            PartitionService::PartitionService(spi::ClientContext& clientContext)
            : clientContext(clientContext)
            , updating(false)
            , partitionCount(0) {

            }

            bool PartitionService::start() {
                // No need to hold the lock here since it is called by the LifeCycleService start in initialization only
                // from only one thread.
                if (!getInitialPartitions()) {
                    return false;
                }
                util::Thread *partitionListener = new util::Thread("hz.partitionListener", PartitionService::staticRunListener, this);
                partitionListenerThread.reset(partitionListener);
                return true;
            }

            void PartitionService::shutdown() {
                // Do not take the lock here since it may be needed by the partition listener thread to cancel and
                // the join to succeed and if the lock is already taken it causes a deadlock.
                if (partitionListenerThread.get() != NULL) {
                    partitionListenerThread->cancel();
                    partitionListenerThread->join();
                }
            }

            boost::shared_ptr<Address> PartitionService::getPartitionOwner(int partitionId) {
                // TODO: Use Read/Write Lock instead, it is read most of the time
                util::LockGuard lg(lock);
                std::map<int, boost::shared_ptr<Address> >::iterator it = partitions->find(partitionId);
                if (partitions->end() != it) {
                    return it->second;
                } else {
                    return boost::shared_ptr<Address>();
                }
            }

            int PartitionService::getPartitionId(const serialization::pimpl::Data& key) {
                const int pc = partitionCount;
                int hash = key.getPartitionHash();
                return (hash == INT_MIN) ? 0 : abs(hash) % pc;
            }

            void PartitionService::staticRunListener(util::ThreadArgs& args) {
                PartitionService *partitionService = (PartitionService *)args.arg0;
                partitionService->runListener(args.currentThread);
            }

            void PartitionService::runListener(util::Thread *currentThread) {
                while (clientContext.getLifecycleService().isRunning()) {
                    try {
                        currentThread->interruptibleSleep(10);
                        if (!clientContext.getLifecycleService().isRunning()) {
                            break;
                        }
                        refreshPartitions();
                    } catch (exception::IException& e) {
                        util::ILogger::getLogger().warning(std::string("PartitionService::runListener") + e.what());
                    }
                }
            }

            std::auto_ptr<protocol::ClientMessage> PartitionService::getPartitionsFrom(const Address& address) {
                std::auto_ptr<protocol::ClientMessage> responseMessage;
                try {
                    std::auto_ptr<protocol::ClientMessage> requestMessage = protocol::codec::ClientGetPartitionsCodec::RequestParameters::encode();

                    connection::CallFuture future = clientContext.getInvocationService().invokeOnTarget(
                            requestMessage, address);

                    responseMessage = future.get();

                } catch (exception::IOException& e) {
                    util::ILogger::getLogger().severe(std::string("Error while fetching cluster partition table => ") + e.what());
                }
                return responseMessage;
            }

            std::auto_ptr<protocol::ClientMessage> PartitionService::getPartitionsFrom() {
                std::auto_ptr<protocol::ClientMessage> responseMessage;
                try {
                    std::auto_ptr<protocol::ClientMessage> requestMessage = protocol::codec::ClientGetPartitionsCodec::RequestParameters::encode();

                    connection::CallFuture future = clientContext.getInvocationService().invokeOnRandomTarget(
                            requestMessage);

                    responseMessage = future.get();

                } catch (exception::IOException& e) {
                    util::ILogger::getLogger().severe(std::string("Error while fetching cluster partition table => ") + e.what());
                }
                return responseMessage;
            }

            bool PartitionService::processPartitionResponse(protocol::ClientMessage &response) {
                protocol::codec::ClientGetPartitionsCodec::ResponseParameters result =
                        protocol::codec::ClientGetPartitionsCodec::ResponseParameters::decode(response);

                std::auto_ptr<std::map<int, boost::shared_ptr<Address> > > newPartitions(new std::map<int, boost::shared_ptr<Address> >());
                for (std::vector<std::pair<Address, std::vector<int32_t > > >::const_iterator it = result.partitions.begin();
                     it != result.partitions.end(); ++it) {
                    boost::shared_ptr<Address> addr(new Address(it->first));
                    for (std::vector<int32_t>::const_iterator partIt = it->second.begin(); partIt != it->second.end(); ++partIt) {
                        (*newPartitions)[*partIt] = addr;
                    }
                }

                int newPartionCount = (int)newPartitions->size();
                if (newPartionCount > 0) {
                    util::LockGuard lg(lock);

                    partitions = newPartitions;

                    partitionCount = newPartionCount;

                    return true;
                } else {
                    return false;
                }
            }

            bool PartitionService::getInitialPartitions() {
                bool result = false;
                std::vector<Member> memberList = clientContext.getClusterService().getMemberList();
                for (std::vector<Member>::iterator it = memberList.begin(); it < memberList.end(); ++it) {
                    const Address &target = (*it).getAddress();
                    std::auto_ptr<protocol::ClientMessage> response = getPartitionsFrom(target);
                    if (response.get() != NULL) {
                        result = processPartitionResponse(*response);

                        if (result) {
                            break;
                        }
                    }
                }

                if (!result) {
                    util::ILogger::getLogger().severe("PartitionService::getInitialPartitions Cannot get initial partitions!");
                } else {
                    util::ILogger::getLogger().finest("PartitionService::getInitialPartitions Got " +
                                                              util::IOUtil::to_string<int>(partitionCount) +
                                                              " initial partitions successfully.");
                }
                return result;
            }

            // TODO: Implement using executor as done in java (especially when the separate owner connection implementation is changed)
            void PartitionService::refreshPartitions() {
                if (updating.compareAndSet(false, true)) {
                    try {
                        std::auto_ptr<protocol::ClientMessage> partitionResponse;
                        std::auto_ptr<Address> ptr = clientContext.getClusterService().getMasterAddress();
                        if (ptr.get() == NULL) {
                            partitionResponse = getPartitionsFrom();
                        } else {
                            partitionResponse = getPartitionsFrom(*ptr.get());
                        }
                        if (partitionResponse.get() != NULL) {
                            processPartitionResponse(*partitionResponse);
                        }
                    } catch (hazelcast::client::exception::IException& e) {
                        util::ILogger::getLogger().finest(std::string("Exception in partitionService::refreshPartitions ") + e.what());
                    } catch (...) {
                        util::ILogger::getLogger().finest(std::string("Unkown exception in partitionService::refreshPartitions "));
                        throw;
                    }
                    updating = false;
                }
            }

            void PartitionService::wakeup() {
                if (NULL != partitionListenerThread.get()) {
                    partitionListenerThread->wakeup();
                }
            }
        }
    }
}

<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_ARR_FUNCTOR_COUPLED_ODE_SYSTEM_CVODE_HPP
#define STAN_MATH_PRIM_ARR_FUNCTOR_COUPLED_ODE_SYSTEM_CVODE_HPP

#include <stan/math/prim/arr/functor/coupled_ode_system.hpp>

#include <cvode/cvode.h>
#include <nvector/nvector_serial.h>
#include <cvode/cvode_dense.h>
#include <cvode/cvode_band.h>

namespace stan {
  namespace math {

    // Noop error handler to silence CVode error output
    extern "C"
    void silent_err_handler(int error_code, const char *module,
                            const char *function, char *msg, void *eh_data) {
    }

    /**
     * Base template class for a coupled ordinary differential equation
     * system, which adds sensitivities to the base system, with additional
     * structure supporting CVode.
     *
     * This template class declaration should not be instantiated
     * directly --- it is just here to serve as a base for its
     * specializations, some of which are defined in namespace
     * stan::agrad.
     *
     * @tparam F the functor for the base ode system
     * @tparam T1 type of the initial state
     * @tparam T2 type of the parameters
     */
    template <typename F, typename T1, typename T2>
    class coupled_ode_system_cvode: public coupled_ode_system<F, T1, T2> {
    private:
      void* cvode_mem_;
      vector<double> state_;
      N_Vector cvode_state_;

    public:
      typedef coupled_ode_system_cvode<F, T1, T2> ode;

      coupled_ode_system_cvode::~coupled_ode_system_cvode() {
        N_VDestroy_Serial(cvode_state_);
        CVodeFree(&cvode_mem_);
      }

      void check_flag(int flag, std::string func_name) {
        std::ostringstream ss;
        ss << func_name << " failed with error flag " << flag;
        throw std::runtime_error(ss.str());
      }

      // Establish all CVode preliminaries that
      // do not depend on the system size
      void instantiate_cvode_mem(double rel_tol,
                                 double abs_tol,
                                 long int max_num_steps,
                                 double init_step = 0
                                 long int max_err_test_fails = 20,
                                 long int max_conv_fails = 50) {
        // Instantiate CVode memory
        cvode_mem_ = CVodeCreate(CV_BDF, CV_NEWTON);
        if (cvode_mem == 0)
          throw std::runtime_error("CVodeCreate failed to allocate memory");

        // Forward CVode errors to noop error handler
        CVodeSetErrHandlerFn(cvode_mem_, silent_err_handler, 0);

        // Assign pointer to this as user data
        check_flag(CVodeSetUserData(cvode_mem, (void*)(this)),
                   "CVodeSetUserData");

        // Initialize solver parameters
        check_flag(CVodeSStolerances(cvode_mem, rel_tol, abs_tol),
                   "CVodeSStolerances");

        check_flag(CVodeSetMaxNumSteps(cvode_mem, max_num_steps),
                   "CVodeSetMaxNumSteps");

        check_flag(CVodeSetInitStep(cvode_mem, init_step),
                   "CVodeSetInitStep");

        check_flag(CVodeSetMaxErrTestFails(cvode_mem, max_err_test_fails),
                   "CVodeSetMaxErrTestFails");

        check_flag(CVodeSetMaxConvFails(cvode_mem, max_conv_fails),
                   "CVodeSetMaxConvFails");
      }

      // Forward the CVode array-based call to the ODE RHS
      // to the Stan vector-based call
      void operator()(const double y[], double dy_dy[], double t) {
        std::vector<double> y_(&y[0], &y[N_]);
        std::vector<double> dy_dt_;
        (*this)(y_, dy_dt_, t);
        std::copy(dy_dt_.begin(), dy_dt_.end(), &dy_dy[0]);
      }

      // Static wrapper for CVode callback
      static int ode_rhs(double t, N_Vector y, N_Vector ydot, void* f_data) {
        static_cast<ode*>(f_data)->operator()(NV_DATA_S(y), NV_DATA_S(ydot), t);
      }
      /*
      static int ode_rhs(double t, N_Vector y, N_Vector ydot, void* f_data) {
        coupled_ode_system_cvode<F, T1, T2>* explicit_ode
          = static_cast<coupled_ode_system_cvode<F, T1, T2>*>(f_data);
        return explicit_ode->operator()(NV_DATA_S(y), NV_DATA_S(ydot), t);
      }*/

      void integrate_times(const std::vector<double>& ts,
                           std::vector<std::vector<double> >
                             y_coupled(ts_vec.size())) {
        check_flag(CVodeInit(cvode_mem_, &ode::ode_rhs, ts[0], cvode_state_),
                   "CVodeInit");
        y_coupled[0] = state_;
        for (int n = 1; n < ts.size(); ++n) {
          if (ts[n] != ts[n - 1])
            check_flag(CVode(cvode_mem_, ts[n], cvode_state_,
                             &(ts[n - 1]), CV_NORMAL),
                       "CVode");
          y_coupled[n] = state_;
        }
      }
    };

    /**
     * The coupled ode system for known initial values and known
     * parameters.  No sensitivities are needed and CVode uses
     * the full Jacobian to solve the system.
     *
     * @tparam F type of system function for the base ODE system.
     */
    template <typename F>
    class coupled_ode_system_cvode<F, double, double>:
      public coupled_ode_system<F, double, double> {
    public:
      // Static wrapper for CVode callback
      int dense_jacobian(long int N,
                         realtype t, N_Vector y, N_Vector fy,
                         DlsMat J, void *J_data,
                         N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) {
        ode* explicit_ode = static_cast<ode*>(J_data);
        return explicit_ode->dense_jacobian(NV_DATA_S(y), J->cols, t);
      }
      /**
       * Construct the coupled ODE system from the base system
       * function, initial state, parameters, data and a stream for
       * messages.
       *
       * @param[in] f base ode system functor.
       * @param[in] y0 initial state of the base ode.
       * @param[in] theta parameters of the base ode.
       * @param[in] x  real data.
       * @param[in] x_int integer data.
       * @param[in] max_num_steps Maximum number of solver steps.
       * @param[in] rel_tol Relative tolerance of solver.
       * @param[in] abs_tol Absolute tolerance of solver.
       * @param[in, out] msgs print stream.
       */
      coupled_ode_system_cvode(const F& f,
                               const std::vector<double>& y0,
                               const std::vector<double>& theta,
                               const std::vector<double>& x,
                               const std::vector<int>& x_int,
                               double rel_tol,
                               double abs_tol,
                               long int max_num_steps,
                               std::ostream* msgs)
        : coupled_ode_system(f, y0, theta, x, x_int, msgs),
          cvode_mem_(NULL),
          state_(size()),
          cvode_state_(size(), &state_[0]) {
        instantiate_cvode_mem(rel_tol, abs_tol, max_num_steps);
        check_flag(CVDense(cvode_mem_, size()), "CVDense");
        check_flag(CVDlsSetDenseJacFn(cvode_mem_, &ode::dense_jacobian),
                   "CVDlsSetDenseJacFn");
      }

      /**
       * Calculates the derivative of the coupled ode system with
       * respect to the specified state at the specified time using
       * the system state function.
       *
       * The derivative vector created is the same length as the
       * length as the state vector.
       *
       * @param[in] y current state of the coupled ode.
       * @param[out] dy_dt populated with derivatives of the coupled
       * system evaluated at specified state and time.
       * @param[in] t time.
       * @throw exception if the system function does not return
       * a derivative vector of the same size as the state vector.
       */
      void operator()(const double y[], double dy_dy[], double t) {
        std::vector<double> y_(&y[0], &y[size()]);
        std::vector<double> dy_dt_;
        (*this)(y_, dy_dt_, t);
        std::copy(dy_dt_.begin(), dy_dt_.end(), &dy_dy[0]);
      }

      // J[j][i] = d(ydot[i])/d(y[j])
      // J always initialized to zero by CVode
      void dense_jacobian(const double y[], double *J[], double t) {
        // compute Jacobian here!
      }

    };

  }  // math
}  // stan

/*
// J_data is a pointer to the ODE functor
extern "C"
int banded_jacobian(long int N, long int m_upper, long int m_lower,
                    realtype t, N_Vector y, N_Vector fy,
                    DlsMat J, void *J_data,
                    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) {
  ode* explicit_ode = (ode*)J_data;
  return explicit_ode->banded_jacobian(t, NV_DATA_S(y), J->cols, J->s_mu);
}

int banded_jacobian(const double y[], double* J[], long int s_mu,
                    double t)

                    flag = CVBand(cvode_mem, n_total_state, n_state - 1, n_state - 1);
                    if (flag < 0) {
                      std::ostringstream ss;
                      ss << "CVBand failed with error flag " << flag;
                      throw std::runtime_error(ss.str());
                    }

                    flag = CVDlsSetBandJacFn(cvode_mem, banded_jacobian);
                    if (flag < 0) {
                      std::ostringstream ss;
                      ss << "CVDlsSetBandJacFn failed with error flag " << flag;
                      throw std::runtime_error(ss.str());
                    }

*/
#endif
<commit_msg>Small tweaks to prototype<commit_after>#ifndef STAN_MATH_PRIM_ARR_FUNCTOR_COUPLED_ODE_SYSTEM_CVODE_HPP
#define STAN_MATH_PRIM_ARR_FUNCTOR_COUPLED_ODE_SYSTEM_CVODE_HPP

#include <stan/math/prim/arr/functor/coupled_ode_system.hpp>

#include <cvode/cvode.h>
#include <nvector/nvector_serial.h>
#include <cvode/cvode_dense.h>
#include <cvode/cvode_band.h>

namespace stan {
  namespace math {

    // Noop error handler to silence CVode error output
    extern "C"
    void silent_err_handler(int error_code, const char *module,
                            const char *function, char *msg, void *eh_data) {
    }

    /**
     * Base template class for a coupled ordinary differential equation
     * system, which adds sensitivities to the base system, with additional
     * structure supporting CVode.
     *
     * This template class declaration should not be instantiated
     * directly --- it is just here to serve as a base for its
     * specializations, some of which are defined in namespace
     * stan::agrad.
     *
     * @tparam F the functor for the base ode system
     * @tparam T1 type of the initial state
     * @tparam T2 type of the parameters
     */
    template <typename F, typename T1, typename T2>
    class coupled_ode_system_cvode: public coupled_ode_system<F, T1, T2> {
    private:
      void* cvode_mem_;
      vector<double> state_;
      N_Vector cvode_state_;

    public:
      typedef coupled_ode_system_cvode<F, T1, T2> ode;

      coupled_ode_system_cvode::~coupled_ode_system_cvode() {
        N_VDestroy_Serial(cvode_state_);
        CVodeFree(&cvode_mem_);
      }

      void check_flag(int flag, std::string func_name) {
        if (flag < 0) {
          std::ostringstream ss;
          ss << func_name << " failed with error flag " << flag;
          throw std::runtime_error(ss.str());
        }
      }

      // Establish all CVode preliminaries that
      // do not depend on the system size
      void instantiate_cvode_mem(double rel_tol,
                                 double abs_tol,
                                 long int max_num_steps,
                                 double init_step = 0
                                 long int max_err_test_fails = 20,
                                 long int max_conv_fails = 50) {
        // Instantiate CVode memory
        cvode_mem_ = CVodeCreate(CV_BDF, CV_NEWTON);
        if (cvode_mem == 0)
          throw std::runtime_error("CVodeCreate failed to allocate memory");

        // Forward CVode errors to noop error handler
        CVodeSetErrHandlerFn(cvode_mem_, silent_err_handler, 0);

        // Assign pointer to this as user data
        check_flag(CVodeSetUserData(cvode_mem, (void*)(this)),
                   "CVodeSetUserData");

        // Initialize solver parameters
        check_flag(CVodeSStolerances(cvode_mem, rel_tol, abs_tol),
                   "CVodeSStolerances");

        check_flag(CVodeSetMaxNumSteps(cvode_mem, max_num_steps),
                   "CVodeSetMaxNumSteps");

        check_flag(CVodeSetInitStep(cvode_mem, init_step),
                   "CVodeSetInitStep");

        check_flag(CVodeSetMaxErrTestFails(cvode_mem, max_err_test_fails),
                   "CVodeSetMaxErrTestFails");

        check_flag(CVodeSetMaxConvFails(cvode_mem, max_conv_fails),
                   "CVodeSetMaxConvFails");
      }

      // Forward the CVode array-based call to the ODE RHS
      // to the Stan vector-based call
      void operator()(const double y[], double dy_dy[], double t) {
        std::vector<double> y_(&y[0], &y[N_]);
        std::vector<double> dy_dt_;
        (*this)(y_, dy_dt_, t);
        std::copy(dy_dt_.begin(), dy_dt_.end(), &dy_dy[0]);
      }

      // Static wrapper for CVode callback
      static int ode_rhs(double t, N_Vector y, N_Vector ydot, void* f_data) {
        static_cast<ode*>(f_data)->operator()(NV_DATA_S(y), NV_DATA_S(ydot), t);
      }
      /*
      static int ode_rhs(double t, N_Vector y, N_Vector ydot, void* f_data) {
        coupled_ode_system_cvode<F, T1, T2>* explicit_ode
          = static_cast<coupled_ode_system_cvode<F, T1, T2>*>(f_data);
        return explicit_ode->operator()(NV_DATA_S(y), NV_DATA_S(ydot), t);
      }*/

      void integrate_times(const std::vector<double>& ts,
                           std::vector<std::vector<double> >
                             y_coupled(ts_vec.size())) {
        check_flag(CVodeInit(cvode_mem_, &ode::ode_rhs, ts[0], cvode_state_),
                   "CVodeInit");
        y_coupled[0] = state_;
        for (int n = 1; n < ts.size(); ++n) {
          if (ts[n] != ts[n - 1])
            check_flag(CVode(cvode_mem_, ts[n], cvode_state_,
                             &(ts[n - 1]), CV_NORMAL),
                       "CVode");
          y_coupled[n] = state_;
        }
      }
    };

    /**
     * The coupled ode system for known initial values and known
     * parameters.  No sensitivities are needed and CVode uses
     * the full Jacobian to solve the system.
     *
     * @tparam F type of system function for the base ODE system.
     */
    template <typename F>
    class coupled_ode_system_cvode<F, double, double>:
      public coupled_ode_system<F, double, double> {
    public:
      // Static wrapper for CVode callback
      static int dense_jacobian(long int N,
                         realtype t, N_Vector y, N_Vector fy,
                         DlsMat J, void *J_data,
                         N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) {
        ode* explicit_ode = static_cast<ode*>(J_data);
        return explicit_ode->dense_jacobian(NV_DATA_S(y), J->cols, t);
      }
      /**
       * Construct the coupled ODE system from the base system
       * function, initial state, parameters, data and a stream for
       * messages.
       *
       * @param[in] f base ode system functor.
       * @param[in] y0 initial state of the base ode.
       * @param[in] theta parameters of the base ode.
       * @param[in] x  real data.
       * @param[in] x_int integer data.
       * @param[in] max_num_steps Maximum number of solver steps.
       * @param[in] rel_tol Relative tolerance of solver.
       * @param[in] abs_tol Absolute tolerance of solver.
       * @param[in, out] msgs print stream.
       */
      coupled_ode_system_cvode(const F& f,
                               const std::vector<double>& y0,
                               const std::vector<double>& theta,
                               const std::vector<double>& x,
                               const std::vector<int>& x_int,
                               double rel_tol,
                               double abs_tol,
                               long int max_num_steps,
                               std::ostream* msgs)
        : coupled_ode_system(f, y0, theta, x, x_int, msgs),
          cvode_mem_(NULL),
          state_(size()),
          cvode_state_(size(), &state_[0]) {
        instantiate_cvode_mem(rel_tol, abs_tol, max_num_steps);
        check_flag(CVDense(cvode_mem_, size()), "CVDense");
        check_flag(CVDlsSetDenseJacFn(cvode_mem_, &ode::dense_jacobian),
                   "CVDlsSetDenseJacFn");
      }

      /**
       * Calculates the derivative of the coupled ode system with
       * respect to the specified state at the specified time using
       * the system state function.
       *
       * The derivative vector created is the same length as the
       * length as the state vector.
       *
       * @param[in] y current state of the coupled ode.
       * @param[out] dy_dt populated with derivatives of the coupled
       * system evaluated at specified state and time.
       * @param[in] t time.
       * @throw exception if the system function does not return
       * a derivative vector of the same size as the state vector.
       */
      void operator()(const double y[], double dy_dy[], double t) {
        std::vector<double> y_(&y[0], &y[size()]);
        std::vector<double> dy_dt_;
        (*this)(y_, dy_dt_, t);
        std::copy(dy_dt_.begin(), dy_dt_.end(), &dy_dy[0]);
      }

      // J[j][i] = d(ydot[i])/d(y[j])
      // J always initialized to zero by CVode
      void dense_jacobian(const double y[], double *J[], double t) {
        // compute Jacobian here!

        /**
         * Populates the derivative vector with derivatives of the
         * coupled ODE system state with respect to time evaluated at the
         * specified state and specified time.
         *
         * @param[in]  y the current state of the coupled ode system,
         * of size size().
         * @param[in, out] dy_dt populate with the derivatives of the
         * coupled system evaluated at the specified state and time.
         * @param[in] t time.
         * @throw exception if the base system does not return a
         * derivative vector of the same size as the state vector.
         */
        void operator()(const std::vector<double>& y,
                        std::vector<double>& dy_dt,
                        double t) {
                using std::vector;
                using stan::math::var;

                vector<double> y_base(y.begin(), y.begin()+N_);
                for (size_t n = 0; n < N_; n++)
                  y_base[n] += y0_dbl_[n];

                dy_dt = f_(t, y_base, theta_dbl_, x_, x_int_, msgs_);
                stan::math::check_equal("coupled_ode_system",
                                                  "dy_dt", dy_dt.size(), N_);

                vector<double> coupled_sys(N_ * (N_ + M_));
                vector<var> theta_temp;
                vector<var> y_temp;
                vector<var> dy_dt_temp;
                vector<double> grad;
                vector<var> vars;

                for (size_t i = 0; i < N_; i++) {
                  theta_temp.clear();
                  y_temp.clear();
                  dy_dt_temp.clear();
                  grad.clear();
                  vars.clear();
                  try {
                    stan::math::start_nested();

                    for (size_t j = 0; j < N_; j++) {
                      y_temp.push_back(y[j] + y0_dbl_[j]);
                      vars.push_back(y_temp[j]);
                    }

                    for (size_t j = 0; j < M_; j++) {
                      theta_temp.push_back(theta_dbl_[j]);
                      vars.push_back(theta_temp[j]);
                    }

                    dy_dt_temp = f_(t, y_temp, theta_temp, x_, x_int_, msgs_);
                    dy_dt_temp[i].grad(vars, grad);

                    for (size_t j = 0; j < N_+M_; j++) {
                      // orders derivatives by equation (i.e. if there are 2 eqns
                      // (y1, y2) and 2 parameters (a, b), dy_dt will be ordered as:
                      // dy1_dt, dy2_dt, dy1_da, dy2_da, dy1_db, dy2_db
                      double temp_deriv = grad[j];
                      for (size_t k = 0; k < N_; k++)
                        temp_deriv += y[N_ + N_ * j + k] * grad[k];

                      coupled_sys[i + j * N_] = temp_deriv;
                    }
                  } catch (const std::exception& e) {
                    stan::math::recover_memory_nested();
                    throw;
                  }
                  stan::math::recover_memory_nested();
                }
                dy_dt.insert(dy_dt.end(), coupled_sys.begin(), coupled_sys.end());
              }

      }

    };

  }  // math
}  // stan

/*
// J_data is a pointer to the ODE functor
extern "C"
int banded_jacobian(long int N, long int m_upper, long int m_lower,
                    realtype t, N_Vector y, N_Vector fy,
                    DlsMat J, void *J_data,
                    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) {
  ode* explicit_ode = (ode*)J_data;
  return explicit_ode->banded_jacobian(t, NV_DATA_S(y), J->cols, J->s_mu);
}

int banded_jacobian(const double y[], double* J[], long int s_mu,
                    double t)

                    flag = CVBand(cvode_mem, n_total_state, n_state - 1, n_state - 1);
                    if (flag < 0) {
                      std::ostringstream ss;
                      ss << "CVBand failed with error flag " << flag;
                      throw std::runtime_error(ss.str());
                    }

                    flag = CVDlsSetBandJacFn(cvode_mem, banded_jacobian);
                    if (flag < 0) {
                      std::ostringstream ss;
                      ss << "CVDlsSetBandJacFn failed with error flag " << flag;
                      throw std::runtime_error(ss.str());
                    }

*/
#endif
<|endoftext|>


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

#include "NebulaTemplate.h"

using namespace std;

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int NebulaTemplate::load_configuration()
{
    char * error = 0;
    int    rc;

    string      aname;
    Attribute * attr;

    map<string, Attribute *>::iterator  iter, j;

    set_conf_default();

    rc = parse(conf_file.c_str(), &error);

    if ( rc != 0 && error != 0)
    {
        cout << "\nError while parsing configuration file:\n" << error << endl;

        free(error);

        return -1;
    }

    for(iter=conf_default.begin();iter!=conf_default.end();)
    {
        aname = iter->first;
        attr  = iter->second;

        j = attributes.find(aname);

        if ( j == attributes.end() )
        {
            attributes.insert(make_pair(aname,attr));
            iter++;
        }
        else
        {
            delete iter->second;
            conf_default.erase(iter++);
        }
    }

    return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

const char * OpenNebulaTemplate::conf_name="oned.conf";

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void OpenNebulaTemplate::set_conf_default()
{
    SingleAttribute *   attribute;
    VectorAttribute *   vattribute;
    string              value;

    // MANAGER_TIMER
    value = "15";

    attribute = new SingleAttribute("MANAGER_TIMER",value);
    conf_default.insert(make_pair(attribute->name(),attribute));
/*
#*******************************************************************************
# Daemon configuration attributes
#-------------------------------------------------------------------------------
#  HOST_MONITORING_INTERVAL
#  HOST_PER_INTERVAL
#  VM_POLLING_INTERVAL
#  VM_PER_INTERVAL
#  VM_DIR
#  PORT
#  DB
#  VNC_BASE_PORT
#  SCRIPTS_REMOTE_DIR
#*******************************************************************************
*/
    // MONITOR_INTERVAL
    value = "600";

    attribute = new SingleAttribute("HOST_MONITORING_INTERVAL",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    // HOST_PER_INTERVAL
    value = "15";

    attribute = new SingleAttribute("HOST_PER_INTERVAL",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    // POLL_INTERVAL
    value = "600";

    attribute = new SingleAttribute("VM_POLLING_INTERVAL",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    // VM_PER_INTERVAL
    value = "5";

    attribute = new SingleAttribute("VM_PER_INTERVAL",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //VM_DIR
    attribute = new SingleAttribute("VM_DIR",var_location);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //XML-RPC Server PORT
    value = "2633";

    attribute = new SingleAttribute("PORT",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //DB CONFIGURATION
    map<string,string> vvalue;
    vvalue.insert(make_pair("BACKEND","sqlite"));

    vattribute = new VectorAttribute("DB",vvalue);
    conf_default.insert(make_pair(attribute->name(),vattribute));

    //VNC_BASE_PORT
    value = "5900";

    attribute = new SingleAttribute("VNC_BASE_PORT",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //XML-RPC Server PORT
    value = "2633";

    attribute = new SingleAttribute("PORT",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //SCRIPTS_REMOTE_DIR
    value = "/var/tmp/one";

    attribute = new SingleAttribute("SCRIPTS_REMOTE_DIR",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

/*
#*******************************************************************************
# Physical Networks configuration
#*******************************************************************************
#  NETWORK_SIZE
#  MAC_PREFIX
#*******************************************************************************
*/
    //MAC_PREFIX
    value = "02:00";

    attribute = new SingleAttribute("MAC_PREFIX",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //NETWORK_SIZE
    value = "254";

    attribute = new SingleAttribute("NETWORK_SIZE",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

/*
#*******************************************************************************
# Image Repository Configuration
#*******************************************************************************
#  DEFAULT_IMAGE_TYPE
#  DEFAULT_DEVICE_PREFIX
#*******************************************************************************
*/
    //SYSTEM_DS
    vvalue.clear();
    vvalue.insert(make_pair("BASE_PATH","/var/lib/one/system_ds"));
    vvalue.insert(make_pair("TYPE","shared"));

    vattribute = new VectorAttribute("SYSTEM_DS",vvalue);
    conf_default.insert(make_pair(attribute->name(),vattribute));

    //DEFAULT_IMAGE_TYPE
    value = "OS";

    attribute = new SingleAttribute("DEFAULT_IMAGE_TYPE",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //DEFAULT_DEVICE_PREFIX
    value = "hd";

    attribute = new SingleAttribute("DEFAULT_DEVICE_PREFIX",value);
    conf_default.insert(make_pair(attribute->name(),attribute));
/*

#*******************************************************************************
# Auth Manager Configuration
#*******************************************************************************
# SESSION_EXPIRATION_TIME
# ENABLE_OTHER_PERMISSIONS
#*******************************************************************************
*/
    // SESSION_EXPIRATION_TIME
    value = "0";

    attribute = new SingleAttribute("SESSION_EXPIRATION_TIME",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    // ENABLE_OTHER_PERMISSIONS
    value = "YES";

    attribute = new SingleAttribute("ENABLE_OTHER_PERMISSIONS",value);
    conf_default.insert(make_pair(attribute->name(),attribute));
}

<commit_msg>Feature #1112: Fix default configuration for vector attributes<commit_after>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org)             */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

#include "NebulaTemplate.h"

using namespace std;

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

int NebulaTemplate::load_configuration()
{
    char * error = 0;
    int    rc;

    string      aname;
    Attribute * attr;

    map<string, Attribute *>::iterator  iter, j;

    set_conf_default();

    rc = parse(conf_file.c_str(), &error);

    if ( rc != 0 && error != 0)
    {
        cout << "\nError while parsing configuration file:\n" << error << endl;

        free(error);

        return -1;
    }

    for(iter=conf_default.begin();iter!=conf_default.end();)
    {
        aname = iter->first;
        attr  = iter->second;

        j = attributes.find(aname);

        if ( j == attributes.end() )
        {
            attributes.insert(make_pair(aname,attr));
            iter++;
        }
        else
        {
            delete iter->second;
            conf_default.erase(iter++);
        }
    }

    return 0;
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

const char * OpenNebulaTemplate::conf_name="oned.conf";

/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */

void OpenNebulaTemplate::set_conf_default()
{
    SingleAttribute *   attribute;
    VectorAttribute *   vattribute;
    string              value;

    // MANAGER_TIMER
    value = "15";

    attribute = new SingleAttribute("MANAGER_TIMER",value);
    conf_default.insert(make_pair(attribute->name(),attribute));
/*
#*******************************************************************************
# Daemon configuration attributes
#-------------------------------------------------------------------------------
#  HOST_MONITORING_INTERVAL
#  HOST_PER_INTERVAL
#  VM_POLLING_INTERVAL
#  VM_PER_INTERVAL
#  VM_DIR
#  PORT
#  DB
#  VNC_BASE_PORT
#  SCRIPTS_REMOTE_DIR
#*******************************************************************************
*/
    // MONITOR_INTERVAL
    value = "600";

    attribute = new SingleAttribute("HOST_MONITORING_INTERVAL",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    // HOST_PER_INTERVAL
    value = "15";

    attribute = new SingleAttribute("HOST_PER_INTERVAL",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    // POLL_INTERVAL
    value = "600";

    attribute = new SingleAttribute("VM_POLLING_INTERVAL",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    // VM_PER_INTERVAL
    value = "5";

    attribute = new SingleAttribute("VM_PER_INTERVAL",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //VM_DIR
    attribute = new SingleAttribute("VM_DIR",var_location);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //XML-RPC Server PORT
    value = "2633";

    attribute = new SingleAttribute("PORT",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //DB CONFIGURATION
    map<string,string> vvalue;
    vvalue.insert(make_pair("BACKEND","sqlite"));

    vattribute = new VectorAttribute("DB",vvalue);
    conf_default.insert(make_pair(vattribute->name(),vattribute));

    //VNC_BASE_PORT
    value = "5900";

    attribute = new SingleAttribute("VNC_BASE_PORT",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //XML-RPC Server PORT
    value = "2633";

    attribute = new SingleAttribute("PORT",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //SCRIPTS_REMOTE_DIR
    value = "/var/tmp/one";

    attribute = new SingleAttribute("SCRIPTS_REMOTE_DIR",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

/*
#*******************************************************************************
# Physical Networks configuration
#*******************************************************************************
#  NETWORK_SIZE
#  MAC_PREFIX
#*******************************************************************************
*/
    //MAC_PREFIX
    value = "02:00";

    attribute = new SingleAttribute("MAC_PREFIX",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //NETWORK_SIZE
    value = "254";

    attribute = new SingleAttribute("NETWORK_SIZE",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

/*
#*******************************************************************************
# Image Repository Configuration
#*******************************************************************************
#  DEFAULT_IMAGE_TYPE
#  DEFAULT_DEVICE_PREFIX
#*******************************************************************************
*/
    //SYSTEM_DS
    vvalue.clear();
    vvalue.insert(make_pair("BASE_PATH","/var/lib/one/system_ds"));
    vvalue.insert(make_pair("TYPE","shared"));

    vattribute = new VectorAttribute("SYSTEM_DS",vvalue);
    conf_default.insert(make_pair(vattribute->name(),vattribute));

    //DEFAULT_IMAGE_TYPE
    value = "OS";

    attribute = new SingleAttribute("DEFAULT_IMAGE_TYPE",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    //DEFAULT_DEVICE_PREFIX
    value = "hd";

    attribute = new SingleAttribute("DEFAULT_DEVICE_PREFIX",value);
    conf_default.insert(make_pair(attribute->name(),attribute));
/*

#*******************************************************************************
# Auth Manager Configuration
#*******************************************************************************
# SESSION_EXPIRATION_TIME
# ENABLE_OTHER_PERMISSIONS
#*******************************************************************************
*/
    // SESSION_EXPIRATION_TIME
    value = "0";

    attribute = new SingleAttribute("SESSION_EXPIRATION_TIME",value);
    conf_default.insert(make_pair(attribute->name(),attribute));

    // ENABLE_OTHER_PERMISSIONS
    value = "YES";

    attribute = new SingleAttribute("ENABLE_OTHER_PERMISSIONS",value);
    conf_default.insert(make_pair(attribute->name(),attribute));
}

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "Instance.h"
#include "Class.h"
#include "Utils.h"
#include "PyMI.h"

static PyObject* Instance_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    Instance* self = NULL;
    self = (Instance*)type->tp_alloc(type, 0);
    self->instance = NULL;
    return (PyObject *)self;
}

static int Instance_init(Instance* self, PyObject* args, PyObject* kwds)
{
    PyErr_SetString(PyMIError, "An Instance object cannot be allocated directly.");
    return -1;
}

static void Instance_dealloc(Instance* self)
{
    if (self->instance)
    {
        delete self->instance;
        self->instance = NULL;
    }

    self->ob_type->tp_free((PyObject*)self);
}

static PyObject* Instance_subscript(Instance *self, PyObject *item)
{
    try
    {
        // TODO: size buffer based on actual size
        wchar_t w[1024];
        Py_ssize_t i;
        if (!GetIndexOrName(item, w, i))
            return NULL;

        MI::ValueElement element;
        if (i >= 0)
        {
            element = (*self->instance)[i];
        }
        else
        {
            element = (*self->instance)[w];
        }
        return MI2Py(element.m_value, element.m_type, element.m_flags);
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return NULL;
    }
}

static Py_ssize_t Instance_length(Instance *self)
{
    try
    {
        return self->instance->GetElementsCount();
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return -1;
    }
}

static int Instance_ass_subscript(Instance* self, PyObject* item, PyObject* value)
{
    try
    {
        // TODO: size buffer based on actual size
        wchar_t w[1024];
        w[0] = NULL;
        Py_ssize_t i = 0;
        if (!GetIndexOrName(item, w, i))
            return NULL;

        bool addElement = false;

        MI_Value miValue;
        MI_UNREFERENCED_PARAMETER(&miValue);
        MI_Type miType;
        if (i >= 0)
        {
            miType = self->instance->GetElementType(i);
        }
        else
        {
            miType = self->instance->GetElementType(w);
        }

        Py2MI(value, miValue, miType);

        if (i >= 0)
        {
            self->instance->SetElement(i, value == Py_None? NULL : &miValue, miType);
        }
        else
        {
            self->instance->SetElement(w, value == Py_None ? NULL : &miValue, miType);
        }

        return 0;
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return -1;
    }
}

static PyObject* Instance_getattro(Instance *self, PyObject* name)
{
    PyObject* attr = PyObject_GenericGetAttr((PyObject*)self, name);
    if (attr)
    {
        return attr;
    }

    return Instance_subscript(self, name);
}

static int Instance_setattro(Instance *self, PyObject* name, PyObject* value)
{
    return -1;
}

static PyObject* Instance_GetClass(Instance *self, PyObject*)
{
    try
    {
        MI::Class* c = self->instance->GetClass();
        return (PyObject*)Class_New(c);
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return NULL;
    }
}

static PyObject* Instance_Clone(Instance *self, PyObject*)
{
    try
    {
        MI::Instance* instance = self->instance->Clone();
        return (PyObject*)Instance_New(instance);
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return NULL;
    }
}

static PyObject* Instance_GetPath(Instance *self, PyObject*)
{
    try
    {
        std::wstring path = self->instance->GetPath();
        return PyUnicode_FromWideChar(path.c_str(), path.length());
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return NULL;
    }
}

static PyObject* Instance_GetClassName(Instance *self, PyObject*)
{
    try
    {
        std::wstring className = self->instance->GetClassName();
        return PyUnicode_FromWideChar(className.c_str(), className.length());
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return NULL;
    }
}

Instance* Instance_New(MI::Instance* instance)
{
    Instance* obj = (Instance*)Instance_new(&InstanceType, NULL, NULL);
    obj->instance = instance;
    return obj;
}

static PyMemberDef Instance_members[] = {
    { NULL }  /* Sentinel */
};

static PyMethodDef Instance_methods[] = {
    { "__getitem__", (PyCFunction)Instance_subscript, METH_O | METH_COEXIST, "" },
    { "get_path", (PyCFunction)Instance_GetPath, METH_NOARGS, "" },
    { "get_class_name", (PyCFunction)Instance_GetClassName, METH_NOARGS, "" },
    { "get_class", (PyCFunction)Instance_GetClass, METH_NOARGS, "" },
    { "clone", (PyCFunction)Instance_Clone, METH_NOARGS, "Clones this instance." },
    { NULL }  /* Sentinel */
};

static PyMappingMethods Instance_as_mapping = {
    (lenfunc)Instance_length,
    (binaryfunc)Instance_subscript,
    (objobjargproc)Instance_ass_subscript
};

PyTypeObject InstanceType = {
    PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "mi.Instance",             /*tp_name*/
    sizeof(Instance),             /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    (destructor)Instance_dealloc, /*tp_dealloc*/
    0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    0,                         /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    &Instance_as_mapping,      /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    0,                         /*tp_str*/
    (getattrofunc)Instance_getattro, /*tp_getattro*/
    (setattrofunc)Instance_setattro, /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
    "Instance objects",           /* tp_doc */
    0,		               /* tp_traverse */
    0,		               /* tp_clear */
    0,		               /* tp_richcompare */
    0,		               /* tp_weaklistoffset */
    0,		               /* tp_iter */
    0,		               /* tp_iternext */
    Instance_methods,             /* tp_methods */
    Instance_members,             /* tp_members */
    0,                         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    (initproc)Instance_init,    /* tp_init */
    0,                         /* tp_alloc */
    Instance_new,                 /* tp_new */
};
<commit_msg>Adds Instance.get_element<commit_after>#include "stdafx.h"
#include "Instance.h"
#include "Class.h"
#include "Utils.h"
#include "PyMI.h"

static PyObject* Instance_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    Instance* self = NULL;
    self = (Instance*)type->tp_alloc(type, 0);
    self->instance = NULL;
    return (PyObject *)self;
}

static int Instance_init(Instance* self, PyObject* args, PyObject* kwds)
{
    PyErr_SetString(PyMIError, "An Instance object cannot be allocated directly.");
    return -1;
}

static void Instance_dealloc(Instance* self)
{
    if (self->instance)
    {
        delete self->instance;
        self->instance = NULL;
    }

    self->ob_type->tp_free((PyObject*)self);
}

MI::ValueElement GetElement(Instance *self, PyObject *item)
{
    // TODO: size buffer based on actual size
    wchar_t w[1024];
    Py_ssize_t i;
    if (!GetIndexOrName(item, w, i))
        throw MI::Exception(L"Cannot find element");

    MI::ValueElement element;
    if (i >= 0)
    {
        return (*self->instance)[i];
    }
    else
    {
        return (*self->instance)[w];
    }
}

static PyObject* Instance_subscript(Instance *self, PyObject *item)
{
    try
    {
        MI::ValueElement element = GetElement(self, item);
        return MI2Py(element.m_value, element.m_type, element.m_flags);
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return NULL;
    }
}

static PyObject* Instance_GetElement(Instance *self, PyObject *item)
{
    try
    {
        MI::ValueElement element = GetElement(self, item);
        PyObject* tuple = PyTuple_New(3);
        PyTuple_SetItem(tuple, 0, PyUnicode_FromWideChar(element.m_name.c_str(), element.m_name.length()));
        PyTuple_SetItem(tuple, 1, PyInt_FromLong(element.m_type));
        PyTuple_SetItem(tuple, 2, MI2Py(element.m_value, element.m_type, element.m_flags));
        return tuple;
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return NULL;
    }
}

static Py_ssize_t Instance_length(Instance *self)
{
    try
    {
        return self->instance->GetElementsCount();
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return -1;
    }
}

static int Instance_ass_subscript(Instance* self, PyObject* item, PyObject* value)
{
    try
    {
        // TODO: size buffer based on actual size
        wchar_t w[1024];
        w[0] = NULL;
        Py_ssize_t i = 0;
        if (!GetIndexOrName(item, w, i))
            return NULL;

        bool addElement = false;

        MI_Value miValue;
        MI_UNREFERENCED_PARAMETER(&miValue);
        MI_Type miType;
        if (i >= 0)
        {
            miType = self->instance->GetElementType(i);
        }
        else
        {
            miType = self->instance->GetElementType(w);
        }

        Py2MI(value, miValue, miType);

        if (i >= 0)
        {
            self->instance->SetElement(i, value == Py_None? NULL : &miValue, miType);
        }
        else
        {
            self->instance->SetElement(w, value == Py_None ? NULL : &miValue, miType);
        }

        return 0;
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return -1;
    }
}

static PyObject* Instance_getattro(Instance *self, PyObject* name)
{
    PyObject* attr = PyObject_GenericGetAttr((PyObject*)self, name);
    if (attr)
    {
        return attr;
    }

    return Instance_subscript(self, name);
}

static int Instance_setattro(Instance *self, PyObject* name, PyObject* value)
{
    return -1;
}

static PyObject* Instance_GetClass(Instance *self, PyObject*)
{
    try
    {
        MI::Class* c = self->instance->GetClass();
        return (PyObject*)Class_New(c);
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return NULL;
    }
}

static PyObject* Instance_Clone(Instance *self, PyObject*)
{
    try
    {
        MI::Instance* instance = self->instance->Clone();
        return (PyObject*)Instance_New(instance);
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return NULL;
    }
}

static PyObject* Instance_GetPath(Instance *self, PyObject*)
{
    try
    {
        std::wstring path = self->instance->GetPath();
        return PyUnicode_FromWideChar(path.c_str(), path.length());
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return NULL;
    }
}

static PyObject* Instance_GetClassName(Instance *self, PyObject*)
{
    try
    {
        std::wstring className = self->instance->GetClassName();
        return PyUnicode_FromWideChar(className.c_str(), className.length());
    }
    catch (std::exception& ex)
    {
        SetPyException(ex);
        return NULL;
    }
}

Instance* Instance_New(MI::Instance* instance)
{
    Instance* obj = (Instance*)Instance_new(&InstanceType, NULL, NULL);
    obj->instance = instance;
    return obj;
}

static PyMemberDef Instance_members[] = {
    { NULL }  /* Sentinel */
};

static PyMethodDef Instance_methods[] = {
    { "__getitem__", (PyCFunction)Instance_subscript, METH_O | METH_COEXIST, "" },
    { "get_element", (PyCFunction)Instance_GetElement, METH_O, "Returns an element by either index or name" },
    { "get_path", (PyCFunction)Instance_GetPath, METH_NOARGS, "" },
    { "get_class_name", (PyCFunction)Instance_GetClassName, METH_NOARGS, "" },
    { "get_class", (PyCFunction)Instance_GetClass, METH_NOARGS, "" },
    { "clone", (PyCFunction)Instance_Clone, METH_NOARGS, "Clones this instance." },
    { NULL }  /* Sentinel */
};

static PyMappingMethods Instance_as_mapping = {
    (lenfunc)Instance_length,
    (binaryfunc)Instance_subscript,
    (objobjargproc)Instance_ass_subscript
};

PyTypeObject InstanceType = {
    PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "mi.Instance",             /*tp_name*/
    sizeof(Instance),             /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    (destructor)Instance_dealloc, /*tp_dealloc*/
    0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    0,                         /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    &Instance_as_mapping,      /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    0,                         /*tp_str*/
    (getattrofunc)Instance_getattro, /*tp_getattro*/
    (setattrofunc)Instance_setattro, /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
    "Instance objects",           /* tp_doc */
    0,		               /* tp_traverse */
    0,		               /* tp_clear */
    0,		               /* tp_richcompare */
    0,		               /* tp_weaklistoffset */
    0,		               /* tp_iter */
    0,		               /* tp_iternext */
    Instance_methods,             /* tp_methods */
    Instance_members,             /* tp_members */
    0,                         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    (initproc)Instance_init,    /* tp_init */
    0,                         /* tp_alloc */
    Instance_new,                 /* tp_new */
};
<|endoftext|>