public: void stop()
	{
		DCS_DEBUG_TRACE("BEGIN Stopping Application: '" << name_ << "'");

		// check: pointer to simulation model is a valid pointer
		DCS_DEBUG_ASSERT( ptr_sim_model_ );

		ptr_sim_model_->stop_application();

		DCS_DEBUG_TRACE("END Stopping Application: '" << name_ << "'");
	}
		void start(VMForwardIterT first, VMForwardIterT last)
	{
		DCS_DEBUG_TRACE("BEGIN Starting Application: '" << name_ << "'");

		// check: pointer to simulation model is a valid pointer
		DCS_DEBUG_ASSERT( ptr_sim_model_ );

		ptr_sim_model_->tier_virtual_machines(first, last);
		ptr_sim_model_->start_application();

		DCS_DEBUG_TRACE("END Starting Application: '" << name_ << "'");
	}
Ejemplo n.º 3
0
	/**
	 * \brief Perform system experiment.
	 */
	public: void run()
	{
		typedef typename app_experiment_container::const_iterator app_experiment_iterator;
//		typedef typename monitor_container::const_iterator monitor_iterator;

		DCS_DEBUG_TRACE( "BEGIN Execution of System EXPERIMENT" );

		app_experiment_iterator app_exp_end_it(app_exps_.end());
		app_experiment_iterator app_exp_beg_it(app_exps_.begin());

		(*p_sta_sig_)(*this);

		if (app_exp_beg_it != app_exp_end_it)
		{
			// There is some experiment to run

			::boost::thread_group exp_thds;
			// Create threads for application experiments
			for (app_experiment_iterator app_exp_it = app_exp_beg_it;
				 app_exp_it != app_exp_end_it;
				 ++app_exp_it)
			{
				app_experiment_pointer p_app_exp(*app_exp_it);

				detail::runnable<app_experiment_type> exp_runner(*app_exp_it);
				//::boost::thread exp_thd(exp_runner);
				exp_thds.create_thread(exp_runner);
				//::boost::this_thread::sleep_for(::boost::chrono::seconds(2));
			}
//			// Create threads for experiment monitors
//			system_experiment_context<traits_type> ctx(this);
//			monitor_iterator mon_end_it(mons_.end());
//			for (monitor_iterator mon_it = mons_.begin();
//				 mon_it != mon_end_it;
//				 ++mon_it)
//			{
//				monitor_pointer p_mon(*mon_it);
//
//				detail::monitor_runnable<monitor_type> mon_runner(p_mon, ctx);
//				exp_thds.create_thread(mon_runner);
//			}
			running_ = true;
			exp_thds.join_all();
			running_ = false;
		}

		(*p_sto_sig_)(*this);

		DCS_DEBUG_TRACE( "END Execution of System EXPERIMENT" );
	}
Ejemplo n.º 4
0
	/// Accumulate the effective amount of work done (the work will not be scaled)
	public: void accumulate_work2(real_type w)
	{
		// NOTE: the use of epsilon() is to take care of cancellation errors due
		//       to floating-point subtraction.

DCS_DEBUG_TRACE("(" << this << ") Accumulating work for Customer: " << ::std::setprecision(12) << get_customer() << " -> Work: " << w << " - Old Total work: " << wt_ << " - New Total work: " << (wt_+w) << " - Service Demand: " << sd_ << " - Condition: " << ::std::boolalpha << (wt_+w<=sd_) << " - Condition#2: " << ::std::boolalpha << ((wt_+w)<=sd_) << " - Condition#3: " << ::std::boolalpha << ((wt_+w)>sd_) << " - Difference: " << ((wt_+w)-sd_) << " - epsilon: " << ::std::numeric_limits<real_type>::epsilon());//XXX
		DCS_DEBUG_ASSERT( w >= 0 );
		//DCS_DEBUG_ASSERT( wt_+w <= sd_ );
		DCS_DEBUG_ASSERT( ::dcs::math::float_traits<real_type>::definitely_less_equal(wt_+w, sd_) );

		wt_ += w;
		lwut_ = -1; // not available
	}
	private: void do_control()
	{
//		DCS_MACRO_SUPPRESS_UNUSED_VARIABLE_WARNING( evt );
//		DCS_MACRO_SUPPRESS_UNUSED_VARIABLE_WARNING( ctx );

//		DCS_DEBUG_TRACE("(" << this << ") BEGIN Do Processing CONTROL (Clock: " << ctx.simulated_time() << ")");//XXX

        // pre: physical machine must have already been set
        DCS_DEBUG_ASSERT( this->machine_ptr() );

		typedef typename base_type::physical_machine_type physical_machine_type;
		typedef typename physical_machine_type::vmm_type vmm_type;
		typedef typename vmm_type::virtual_machine_type vm_type;
		typedef typename vmm_type::virtual_machine_pointer vm_pointer;
		typedef typename vmm_type::virtual_machine_container vm_container;
		typedef typename vm_container::const_iterator vm_iterator;
		typedef typename vm_type::resource_share_container share_container;
		typedef typename share_container::const_iterator share_iterator;
		typedef ::std::map<physical_resource_category,real_type> share_map_container;

		vm_container actual_vms(this->machine().vmm().virtual_machines(powered_on_power_status));
		share_map_container share_sums;
		short step = 1;

		do
		{
			// Share assignment is done in 2 steps
			// 1. In the first step computes the total resource fraction
			//    requested by all VMs. The computed value both serves to check
			//    if the total fraction overpass the maximum allowable
			//    utilization and as a normalization constant.
			// 2. In the second step assign resource shares.
			//    Specifically, if the total amount of requested resource
			//    capacity is greater than the one assignable then
			vm_iterator vm_end_it(actual_vms.end());
			for (vm_iterator vm_it = actual_vms.begin(); vm_it != vm_end_it; ++vm_it)
			{
				vm_pointer ptr_vm(*vm_it);
				share_container vm_wanted_shares(ptr_vm->wanted_resource_shares());
				share_iterator share_end_it(vm_wanted_shares.end());
				for (share_iterator share_it = vm_wanted_shares.begin(); share_it != share_end_it; ++share_it)
				{
					physical_resource_category category(share_it->first);
					real_type share(share_it->second);

					if (step == 1)
					{
						// Compute share sum for this resource category

						if (share_sums.count(category) > 0)
						{
							share_sums[category] += share;
						}
						else
						{
							share_sums[category] = share;
						}
					}
					else
					{
						// Assign share for this resource category

						real_type share_sum(share_sums.at(category));
						real_type threshold(this->machine().resource(category)->utilization_threshold());

#ifdef DCS_DES_CLOUD_EXP_PROPORTIONAL_MACH_CONTROLLER_WORK_CONSERVATIVE
						// Assign share proportionally
						share *= threshold/share_sum;
						// The operation below may appear useless. However it is needed to compensate spurious decimal digit derived from the above product.
						share = ::std::min(share, threshold);
#else // DCS_DES_CLOUD_EXP_PROPORTIONAL_MACH_CONTROLLER_WORK_CONSERVATIVE
						if (share_sum > threshold)
						{
							// Assign share proportionally
							share *= threshold/share_sum;
							// The operation below may appear useless. However it is needed to compensate spurious decimal digit derived from the above product.
							share = ::std::min(share, threshold);
						}
						// ... else Assign share as it is originally requested.
#endif // DCS_DES_CLOUD_EXP_PROPORTIONAL_MACH_CONTROLLER_WORK_CONSERVATIVE

						// check: make sure resource share is bounded in [0,1]
						//        and respects the utilization threshold.
						DCS_DEBUG_ASSERT( share >= real_type(0) && share <= threshold && share <= real_type(1) );

//::std::cerr << "APP: " << ptr_vm->guest_system().application().id() << ", MACH: " << this->machine().id() << ", VM: " << ptr_vm->id() << ", WantedShare: " << share_it->second << ", GotShare: " << share << ::std::endl;//XXX
						ptr_vm->resource_share(category, share);

						DCS_DEBUG_TRACE("APP: " << ptr_vm->guest_system().application().id() << ", MACH: " << this->machine().id() << " - Assigned new share: VM: " << ptr_vm->name() << " (" << ptr_vm->id() << ") - Category: " << category << " - Threshold: " << threshold << " - Share Sum: " << share_sum << " ==> Wanted: " << share_it->second << " - Got: " << share);//XXX
::std::cerr << "[proportional_machine_controller] APP: " << ptr_vm->guest_system().application().id() << ", MACH: " << this->machine().id() << " - Assigned new share: VM: " << ptr_vm->name() << " (" << ptr_vm->id() << ") - Category: " << category << " - Threshold: " << threshold << " - Share Sum: " << share_sum << " ==> Wanted: " << share_it->second << " - Got: " << share << ::std::endl;//XXX

#ifdef DCS_DES_CLOUD_EXP_OUTPUT_VM_SHARES
						detail::dump_vm_share<traits_type>(ptr_vm->id(),
														   ptr_vm->guest_system().application().id(),
														   ptr_vm->guest_system().id(),
														   this->machine().id(),
														   category,
														   share_it->second,
														   share);
#endif // DCS_DES_CLOUD_EXP_OUTPUT_VM_SHARES
					}
				}
			}

			++step;
		}
		while (step <= 2);
//
//		DCS_DEBUG_TRACE("(" << this << ") END Do Processing CONTROL (Clock: " << ctx.simulated_time() << ")");//XXX
	}
Ejemplo n.º 6
0
bool run_matlab_command(::std::string const& cmd,
						ArgsT const& args,
						ConsumerT& consumer)
{
	int pipefd[2];

	// Create a pipe to let to communicate with MATLAB.
	// Specifically, we want to read the output from MATLAB.
	// So, the parent process read from the pipe, while the child process
	// write on it.
	if (::pipe(pipefd) == -1)
	{
		char const* err_str = ::strerror(errno);
		::std::ostringstream oss;
		oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] pipe(2) failed: "
			<< ::std::string(err_str);
		throw ::std::runtime_error(oss.str());
	}

//	// Install signal handlers
//	struct ::sigaction sig_act;
//	struct ::sigaction old_sigterm_act;
//	struct ::sigaction old_sigint_act;
//	//::memset(&sig_act, 0, sizeof(sig_act));
//	::sigemptyset(&sig_act.sa_mask);
//	sig_act.sa_flags = 0;
//	sig_act.sa_handler = self_type::process_signals;
//	::sigaction(SIGTERM, &sig_act, &old_sigterm_act);
//	::sigaction(SIGINT, &sig_act, &old_sigint_act);

	// Spawn a new process

	// Between fork() and execve() only async-signal-safe functions
	// must be called if multithreaded applications should be supported.
	// That's why the following code is executed before fork() is called.

	::pid_t pid = ::fork();

	// check: pid == -1 --> error
	if (pid == -1)
	{
		char const* err_str = ::strerror(errno);
		::std::ostringstream oss;
		oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] fork(2) failed: "
			<< ::std::string(err_str);
		throw ::std::runtime_error(oss.str());
	}

	if (pid == 0)
	{
		// The child

//		// Cancel signal handler set for parent
//		sig_act.sa_handler = SIG_DFL;
//		::sigaction(SIGTERM, &sig_act, 0);
//		::sigaction(SIGINT, &sig_act, 0);

		// Get the maximum number of files this process is allowed to open
#if defined(F_MAXFD)
		int maxdescs = ::fcntl(-1, F_MAXFD, 0);
		if (maxdescs == -1)
		{
#if defined(_SC_OPEN_MAX)
			maxdescs = ::sysconf(_SC_OPEN_MAX);
#else
			::rlimit limit;
			if (::getrlimit(RLIMIT_NOFILE, &limit) < 0)
			{
				char const* err_str = ::strerror(errno);
				::std::ostringstream oss;
				oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] getrlimit(2) failed: "
					<< ::std::string(err_str);
				throw ::std::runtime_error(oss.str());
			}
			maxdescs = limit.rlim_cur;
#endif // _SC_OPEN_MAX
		}
#else // F_MAXFD
#if defined(_SC_OPEN_MAX)
		int maxdescs = ::sysconf(_SC_OPEN_MAX);
#else // _SC_OPEN_MAX
		::rlimit limit;
		if (::getrlimit(RLIMIT_NOFILE, &limit) < 0)
		{
			char const* err_str = ::strerror(errno);
			::std::ostringstream oss;
			oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] getrlimit(2) failed: "
				<< ::std::string(err_str);
			throw ::std::runtime_error(oss.str());
		}
		maxdescs = limit.rlim_cur;
#endif // _SC_OPEN_MAX
#endif // F_MAXFD
		if (maxdescs == -1)
		{
			maxdescs = 1024;
		}

		::std::vector<bool> close_fd(maxdescs, true);

		// Associate the child's stdout to the pipe write fd.
		close_fd[STDOUT_FILENO] = false;
		if (pipefd[1] != STDOUT_FILENO)
		{
			if (::dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO)
			{
				char const* err_str = ::strerror(errno);
				::std::ostringstream oss;
				oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] dup2(2) failed: "
					<< ::std::string(err_str);
				throw ::std::runtime_error(oss.str());
			}
		}
		else
		{
			close_fd[pipefd[1]] = false;
		}
//			::close(STDOUT_FILENO);
//			::dup(pipefd[1]);

		// Check if the command already has path information
		::std::string cmd_path;
		::std::string cmd_name;
		typename ::std::string::size_type pos;
		pos = cmd.find_last_of('/');
		if (pos != ::std::string::npos)
		{
			cmd_path = cmd.substr(0, pos);
			cmd_name = cmd.substr(pos+1);
		}

		//FIXME: use scoped_ptr in place of "new"

		::std::size_t nargs = args.size()+1;
		char** argv = new char*[nargs + 2];
		argv[0] = new char[cmd_name.size()+1];
		::std::strncpy(argv[0], cmd_name.c_str(), cmd_name.size()+1); // by convention, the first argument is always the command name
		typename ArgsT::size_type i(1);
		typename ArgsT::const_iterator end_it(args.end());
		for (typename ArgsT::const_iterator it = args.begin(); it != end_it; ++it)
		{
			argv[i] = new char[it->size()+1];
			::std::strncpy(argv[i], it->c_str(), it->size()+1);
			++i;
		}
		argv[nargs] = 0;

		//char** envp(0);

		// Close unused file descriptors
#ifdef DCS_DEBUG
		// Keep standard error open for debug
		close_fd[STDERR_FILENO] = false;
#endif // DCS_DEBUG
		for (int fd = 0; fd < maxdescs; ++fd)
		{
			if (close_fd[fd])
			{
				::close(fd);
			}
		}

//[XXX]
#ifdef DCS_DEBUG
::std::cerr << "Executing MATLAB: " << cmd;//XXX
for (::std::size_t i=0; i < args.size(); ++i)//XXX
{//XXX
::std::cerr << " " << args[i] << ::std::flush;//XXX
}//XXX
::std::cerr << ::std::endl;//XXX
#endif // DCS_DEBUG
//[/XXX]
//DCS_DEBUG_TRACE("Executing: " << cmd << " " << args[0] << " " << args[1] << " " << args[2] << " - " << args[3]);

		//::execve(cmd.c_str(), argv, envp);
		::execvp(cmd.c_str(), argv);

		// Actually we should delete argv and envp data. As we must not
		// call any non-async-signal-safe functions though we simply exit.
		::write(STDERR_FILENO, "execvp() failed\n", 17);
		//_exit(EXIT_FAILURE);
		_exit(127);
	}

	// The parent

//		// Associate the parent's stdin to the pipe read fd.
	::close(pipefd[1]);
//		::close(STDIN_FILENO);
//		::dup(pipefd[0]);
	if (pipefd[0] != STDIN_FILENO)
	{
		if (::dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO)
		{
			char const* err_str = ::strerror(errno);
			::std::ostringstream oss;
			oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] dup2(2) failed: "
				<< ::std::string(err_str);
			throw ::std::runtime_error(oss.str());
		}
		::close(pipefd[0]);
	}

	typedef ::boost::iostreams::file_descriptor_source fd_device_type;
	typedef ::boost::iostreams::stream_buffer<fd_device_type> fd_streambuf_type;
	//fd_device_type fd_src(pipefd[0], ::boost::iostreams::close_handle);
	fd_device_type fd_src(STDIN_FILENO, ::boost::iostreams::close_handle);
	fd_streambuf_type fd_buf(fd_src);
	::std::istream is(&fd_buf);

	consumer(is);

DCS_DEBUG_TRACE("END parsing MATLAB output");//XXX
DCS_DEBUG_TRACE("IS state: " << is.good() << " - " << is.eof() << " - " << is.fail() << " - " << is.bad());//XXX

	// Wait the child termination (in order to prevent zombies)
	int status;
//		::pid_t wait_pid;
//		wait_pid = ::wait(&status);
//		if (wait_pid != pid)
//		{
//			throw ::std::runtime_error("[dcs::des::cloud::detail::rls_miso_matlab_app_proxy::run_matlab] Unexpected child process.");
//		}
	if (::waitpid(pid, &status, 0) == -1)
	{
		char const* err_str = ::strerror(errno);
		::std::ostringstream oss;
		oss << "[dcs::des::cloud::detail::matlab::run_matlab_command] waitpid(2) failed: "
			<< ::std::string(err_str);
		throw ::std::runtime_error(oss.str());
	}
DCS_DEBUG_TRACE("MATLAB exited");//XXX
	bool ok(true);
	if (WIFEXITED(status))
	{
DCS_DEBUG_TRACE("MATLAB exited with a call to 'exit(" << WEXITSTATUS(status) << ")'");//XXX
		if (WEXITSTATUS(status))
		{
			// status != 0 --> error in the execution
			::std::clog << "[Warning] MATLAB command exited with status " << WEXITSTATUS(status) << ::std::endl;
			ok = false;
		}
	}
	else if (WIFSIGNALED(status))
	{
DCS_DEBUG_TRACE("MATLAB exited with a call to 'kill(" << WTERMSIG(status) << ")'");//XXX
	   ::std::clog << "[Warning] MATLAB command received signal " << WTERMSIG(status) << ::std::endl;
		ok = false;
	}
	else
	{
DCS_DEBUG_TRACE("MATLAB exited with an unexpected way");//XXX
		ok = false;
	}

//	// Restore signal handler
//	::sigaction(SIGTERM, &old_sigterm_act, 0);
//	::sigaction(SIGINT, &old_sigint_act, 0);
	return ok;
}
	private: void do_control()
	{
		typedef typename base_type::target_value_map::const_iterator target_iterator;
		typedef typename app_type::vm_pointer vm_pointer;

		DCS_DEBUG_TRACE("(" << this << ") BEGIN Do CONTROL - Count: " << ctl_count_ << "/" << ctl_skip_count_ << "/" << ctl_fail_count_);

		++ctl_count_;

		bool skip_ctl = false;

		::std::map<virtual_machine_performance_category,::std::vector<real_type> > cress;
		::std::map<application_performance_category,real_type> rgains;

		::std::vector<vm_pointer> vms = this->app().vms();
		const ::std::size_t nvms = vms.size();

		for (::std::size_t i = 0; i < nvms; ++i)
		{
			const virtual_machine_performance_category cat = cpu_util_virtual_machine_performance;
			const vm_pointer p_vm = vms[i];

//			if (this->data_estimator(cat, vms[i]->id()).count() > 0)
//			{
//				//const real_type uh = this->data_estimator(cat, p_vm->id()).estimate();
//				const real_type uh = this->data_smoother(cat, p_vm->id()).forecast(0);
//				const real_type c = p_vm->cpu_share();
//
//				cress[cat].push_back(c-uh);
//			}
//			else
//			{
//				// No observation collected during the last control interval
//				DCS_DEBUG_TRACE("No input observation collected during the last control interval -> Skip control");
//				skip_ctl = true;
//				break;
//			}
			const real_type uh = this->data_smoother(cat, p_vm->id()).forecast(0);
			const real_type c = p_vm->cpu_share();
			const real_type cres = c-uh;

			cress[cat].push_back(cres);
DCS_DEBUG_TRACE("VM " << p_vm->id() << " - Performance Category: " << cat << " - Uhat(k): " << uh << " - C(k): " << c << " -> Cres(k+1): " << cres << " (Relative Cres(k+1): " << cres/c << ")");//XXX
		}

		if (!skip_ctl)
		{
			const target_iterator tgt_end_it = this->target_values().end();
			for (target_iterator tgt_it = this->target_values().begin();
				 tgt_it != tgt_end_it;
				 ++tgt_it)
			{
				const application_performance_category cat(tgt_it->first);

				// Compute a summary statistics of collected observation
				if (this->data_estimator(cat).count() > 0)
				{
					const real_type yh = this->data_estimator(cat).estimate();
					const real_type yr = this->target_value(cat);

					switch (cat)
					{
						case response_time_application_performance:
							rgains[cat] = (yr-yh)/yr;
							break;
						case throughput_application_performance:
							rgains[cat] = (yh-yr)/yr;
							break;
					}
DCS_DEBUG_TRACE("APP Performance Category: " << cat << " - Yhat(k): " << yh << " - R: " << yr << " -> Rgain(k+1): " << rgains.at(cat));//XXX
				}
				else
				{
					// No observation collected during the last control interval
					DCS_DEBUG_TRACE("No output observation collected during the last control interval -> Skip control");
					skip_ctl = true;
					break;
				}
#ifdef DCSXX_TESTBED_EXP_APP_MGR_RESET_ESTIMATION_EVERY_INTERVAL
				this->data_estimator(cat).reset();
#endif // DCSXX_TESTBED_EXP_APP_MGR_RESET_ESTIMATION_EVERY_INTERVAL
			}
		}
        if (!skip_ctl)
        {
			//FIXME: actually we only handle SISO systems
			DCS_ASSERT(cress.size() == 1 && rgains.size() == 1,
					   DCS_EXCEPTION_THROW(::std::runtime_error,
					   "Only SISO system are currently managed"));

			// Perform fuzzy control
			bool ok = false;
			::std::vector<real_type> deltacs(nvms);
			try
			{
				for (::std::size_t i = 0; i < nvms; ++i)
				{
					vm_pointer p_vm = vms[i];

					const real_type cres = cress.begin()->second.at(i);
					const real_type rgain = rgains.begin()->second;

					p_fuzzy_eng_->setInputValue(cres_fuzzy_var_name, cres/p_vm->cpu_share());
					p_fuzzy_eng_->setInputValue(rgain_fuzzy_var_name, rgain);

					p_fuzzy_eng_->process();

					const real_type deltac = p_fuzzy_eng_->getOutputValue(deltac_fuzzy_var_name);

					deltacs[i] = deltac;
DCS_DEBUG_TRACE("VM " << vms[i]->id() << " -> DeltaC(k+1): " << deltacs.at(i));//XXX
				}

				ok = true;
			}
			catch (fl::Exception const& fe)
			{
				DCS_DEBUG_TRACE( "Caught exception: " << fe.what() );

				::std::ostringstream oss;
				oss << "Unable to compute optimal control: " << fe.what();
				::dcs::log_warn(DCS_LOGGING_AT, oss.str());
			}
			catch (::std::exception const& e)
			{
				DCS_DEBUG_TRACE( "Caught exception: " << e.what() );

				::std::ostringstream oss;
				oss << "Unable to compute optimal control: " << e.what();
				::dcs::log_warn(DCS_LOGGING_AT, oss.str());
			}

			// Apply fuzzy control results
			if (ok)
			{
				for (::std::size_t i = 0; i < nvms; ++i)
				{
					vm_pointer p_vm = vms[i];

					const real_type old_share = p_vm->cpu_share();
					const real_type new_share = ::std::max(::std::min(old_share+deltacs[i], 1.0), 0.0);

					DCS_DEBUG_TRACE("VM '" << p_vm->id() << "' - old-share: " << old_share << " - new-share: " << new_share);

					if (::std::isfinite(new_share) && !::dcs::math::float_traits<real_type>::essentially_equal(old_share, new_share))
					{
						p_vm->cpu_share(new_share);
DCS_DEBUG_TRACE("VM " << vms[i]->id() << " -> C(k+1): " << new_share);//XXX
					}
				}
DCS_DEBUG_TRACE("Optimal control applied");//XXX
			}
			else
			{
				++ctl_fail_count_;

				::std::ostringstream oss;
				oss << "Control not applied: failed to solve the control problem";
				::dcs::log_warn(DCS_LOGGING_AT, oss.str());
			}
		}
		else
		{
			++ctl_skip_count_;
		}

		// Export to file
		if (p_dat_ofs_)
		{
			*p_dat_ofs_ << ::std::time(0) << ",";
			for (::std::size_t i = 0; i < nvms; ++i)
			{
				const vm_pointer p_vm = vms[i];

				// check: p_vm != null
				DCS_DEBUG_ASSERT( p_vm );

				if (i != 0)
				{
					*p_dat_ofs_ << ",";
				}
				*p_dat_ofs_ << p_vm->cpu_cap() << "," << p_vm->cpu_share();
			}
			*p_dat_ofs_ << ",";
			const target_iterator tgt_end_it = this->target_values().end();
			for (target_iterator tgt_it = this->target_values().begin();
			tgt_it != tgt_end_it;
			++tgt_it)
			{
				const application_performance_category cat = tgt_it->first;

				if (tgt_it != this->target_values().begin())
				{
					*p_dat_ofs_ << ",";
				}
				const real_type yh = this->data_estimator(cat).estimate();
				const real_type yr = tgt_it->second;
				const real_type yn = yh/yr;
				*p_dat_ofs_ << yh << "," << yn << "," << yr;
			}
			*p_dat_ofs_ << "," << ctl_count_ << "," << ctl_skip_count_ << "," << ctl_fail_count_;
			*p_dat_ofs_ << ::std::endl;
		}

		DCS_DEBUG_TRACE("(" << this << ") END Do CONTROL - Count: " << ctl_count_ << "/" << ctl_skip_count_ << "/" << ctl_fail_count_);
	}
	private: void do_sample()
	{
		typedef typename in_sensor_map::const_iterator in_sensor_iterator;
		typedef typename out_sensor_map::const_iterator out_sensor_iterator;
		typedef ::std::vector<typename sensor_type::observation_type> obs_container;
		typedef typename obs_container::const_iterator obs_iterator;

		DCS_DEBUG_TRACE("(" << this << ") BEGIN Do SAMPLE - Count: " << ctl_count_ << "/" << ctl_skip_count_ << "/" << ctl_fail_count_);

		// Collect input values
		const in_sensor_iterator in_sens_end_it = in_sensors_.end();
		for (in_sensor_iterator in_sens_it = in_sensors_.begin();
			 in_sens_it != in_sens_end_it;
			 ++in_sens_it)
		{
			const virtual_machine_performance_category cat = in_sens_it->first;

			//const ::std::size_t n = in_sens_it->second.size();
			//for (::std::size_t i = 0; i < n; ++i)
			//{
			//	sensor_pointer p_sens = in_sens_it->second.at(i);
			const typename in_sensor_map::mapped_type::const_iterator vm_end_it = in_sens_it->second.end();
			for (typename in_sensor_map::mapped_type::const_iterator vm_it = in_sens_it->second.begin();
				 vm_it != vm_end_it;
				 ++vm_it)
			{
				const vm_identifier_type vm_id = vm_it->first;
				sensor_pointer p_sens = vm_it->second;

				// check: p_sens != null
				DCS_DEBUG_ASSERT( p_sens );

				p_sens->sense();
				if (p_sens->has_observations())
				{
					const obs_container obs = p_sens->observations();
					const obs_iterator end_it = obs.end();
					for (obs_iterator it = obs.begin();
						 it != end_it;
						 ++it)
					{
						//this->data_estimator(cat, vm_id).collect(it->value());
						this->data_smoother(cat, vm_id).smooth(it->value());
					}
				}
			}
		}

		// Collect output values
		const out_sensor_iterator out_sens_end_it = out_sensors_.end();
		for (out_sensor_iterator out_sens_it = out_sensors_.begin();
			 out_sens_it != out_sens_end_it;
			 ++out_sens_it)
		{
			const application_performance_category cat = out_sens_it->first;

			sensor_pointer p_sens = out_sens_it->second;

			// check: p_sens != null
			DCS_DEBUG_ASSERT( p_sens );

			p_sens->sense();
			if (p_sens->has_observations())
			{
				const obs_container obs = p_sens->observations();
				const obs_iterator end_it = obs.end();
				for (obs_iterator it = obs.begin();
					 it != end_it;
					 ++it)
				{
					this->data_estimator(cat).collect(it->value());
				}
			}
		}

		DCS_DEBUG_TRACE("(" << this << ") END Do SAMPLE - Count: " << ctl_count_ << "/" << ctl_skip_count_ << "/" << ctl_fail_count_);
	}
    virtual_machines_placement<traits_type> do_placement(data_center_type const& dc)
    {
        DCS_DEBUG_TRACE("BEGIN Initial Placement");//XXX
        ::std::cerr << "[optimal_initial_placement] BEGIN Initial Placement" << ::std::endl;//XXX
        typedef typename traits_type::physical_machine_identifier_type physical_machine_identifier_type;
        typedef typename traits_type::virtual_machine_identifier_type virtual_machine_identifier_type;
        typedef ::std::map<virtual_machine_identifier_type,real_type> virtual_machine_utilization_map;
        typedef typename optimal_solver_type::physical_virtual_machine_map physical_virtual_machine_map;
        typedef typename physical_virtual_machine_map::const_iterator physical_virtual_machine_iterator;
        typedef typename optimal_solver_type::resource_share_container resource_share_container;
        typedef typename data_center_type::physical_machine_type physical_machine_type;
        typedef typename data_center_type::physical_machine_pointer physical_machine_pointer;
        typedef typename data_center_type::virtual_machine_type virtual_machine_type;
        typedef typename data_center_type::virtual_machine_pointer virtual_machine_pointer;
        typedef typename data_center_type::application_type application_type;
        typedef typename application_type::reference_physical_resource_type ref_resource_type;
        typedef typename application_type::reference_physical_resource_container ref_resource_container;
        typedef typename ref_resource_container::const_iterator ref_resource_iterator;


        virtual_machine_utilization_map vm_util_map;

        // Retrieve application performance info
        {
            typedef ::std::vector<virtual_machine_pointer> virtual_machine_container;
            typedef typename virtual_machine_container::const_iterator virtual_machine_iterator;

            virtual_machine_container vms(dc.active_virtual_machines());
            virtual_machine_iterator vm_end_it(vms.end());
            for (virtual_machine_iterator vm_it = vms.begin(); vm_it != vm_end_it; ++vm_it)
            {
                virtual_machine_pointer ptr_vm(*vm_it);

                // paranoid-check: null
                DCS_DEBUG_ASSERT( ptr_vm );

                ref_resource_container rress(ptr_vm->guest_system().application().reference_resources());
                ref_resource_iterator rress_end_it(rress.end());
                for (ref_resource_iterator rress_it = rress.begin(); rress_it != rress_end_it; ++rress_it)
                {
                    ref_resource_type res(*rress_it);

                    //TODO: CPU resource category not yet handle in app simulation model and optimization problem
                    DCS_ASSERT(
                        res.category() == cpu_resource_category,
                        DCS_EXCEPTION_THROW(
                            ::std::runtime_error,
                            "Resource categories other than CPU are not yet implemented."
                        )
                    );

                    vm_util_map[ptr_vm->id()] = ptr_vm->guest_system().application().performance_model().tier_measure(
                                                    ptr_vm->guest_system().id(),
                                                    ::dcs::des::cloud::utilization_performance_measure
                                                );
                    ::std::cerr << "[optimal_initial_placement] VM: " << *ptr_vm << " - U: " << vm_util_map.at(ptr_vm->id()) << ::std::endl;//XXX
                }
            }
        }

        // Solve the optimization problem

        //optimal_solver_type solver;

        ptr_solver_->solve(dc, wp_, ws_, this->reference_share_penalty(), vm_util_map);

        // Check solution and act accordingly

        //FIXME: handle ref_penalty

        if (!ptr_solver_->result().solved())
        {
            throw ::std::runtime_error("[dcs::des::cloud::optimal_initial_placement_strategy] Unable to solve optimal problem.");
        }

        virtual_machines_placement<traits_type> deployment;

        physical_virtual_machine_map pm_vm_map(ptr_solver_->result().placement());
//[XXX]
        ::std::cerr << "CHECK SOLVER INITIAL PLACEMENT" << ::std::endl;//XXX
        for (typename physical_virtual_machine_map::const_iterator it = ptr_solver_->result().placement().begin(); it != ptr_solver_->result().placement().end(); ++it)//XXX
        {   //XXX
            ::std::cerr << "VM ID: " << (it->first.second) << " placed on PM ID: " << (it->first.first) << " with SHARE: " << ((it->second)[0].second) << ::std::endl;//XXX
        }//XXX
//[/XXX]
        physical_virtual_machine_iterator pm_vm_end_it(pm_vm_map.end());
        for (physical_virtual_machine_iterator pm_vm_it = pm_vm_map.begin(); pm_vm_it != pm_vm_end_it; ++pm_vm_it)
        {
            physical_machine_pointer ptr_pm(dc.physical_machine_ptr(pm_vm_it->first.first));
            virtual_machine_pointer ptr_vm(dc.virtual_machine_ptr(pm_vm_it->first.second));
            resource_share_container shares(pm_vm_it->second);

//::std::cerr << "Going to migrate VM (" << pm_vm_it->first.second << "): " << *ptr_vm << " into PM (" << pm_vm_it->first.first << "): " << *ptr_pm << ::std::endl; //XXX
            deployment.place(*ptr_vm,
                             *ptr_pm,
                             shares.begin(),
                             shares.end());
            DCS_DEBUG_TRACE("Placed: VM(" << ptr_vm->id() << ") -> PM(" << ptr_pm->id() << ")");//XXX
        }

        ::std::cerr << "[optimal_initial_placement] END Initial Placement" << ::std::endl;//XXX
        DCS_DEBUG_TRACE("END Initial Placement ==> " << deployment);///XXX
        return deployment;
    }
Ejemplo n.º 10
0
	::std::vector< partition_info<RealT> > operator()(::gtpack::cooperative_game<RealT> const& game, ::std::map< gtpack::cid_type, coalition_info<RealT> > const& visited_coalitions)
	{
		namespace alg = ::dcs::algorithm;

		// Generate all partitions and select the ones that are Pareto optimal

		::std::vector< partition_info<RealT> > best_partitions;

		const ::std::vector<gtpack::player_type> players(game.players());
		const ::std::size_t np(players.size());

		alg::lexicographic_partition partition(np);

		::std::vector<RealT> best_payoffs(np, ::std::numeric_limits<RealT>::quiet_NaN());

		while (partition.has_next())
		{
			typedef typename alg::partition_traits<bsid_type>::subset_container subset_container;
			typedef typename alg::partition_traits<bsid_type>::subset_const_iterator subset_iterator;

			subset_container subs;

			// Each subset is a collection of coalitions
			subs = alg::next_partition(players.begin(), players.end(), partition);

			DCS_DEBUG_TRACE("--- PARTITION: " << partition);//XXX

			partition_info<RealT> candidate_partition;

			subset_iterator sub_end_it(subs.end());
			for (subset_iterator sub_it = subs.begin();
				 sub_it != sub_end_it;
				 ++sub_it)
			{
				const gtpack::cid_type cid = gtpack::players_coalition<RealT>::make_id(sub_it->begin(), sub_it->end());

				if (visited_coalitions.count(cid) == 0)
				{
					continue;
				}

				DCS_DEBUG_TRACE("--- COALITION: " << game.coalition(cid) << " (CID=" << cid << ")");//XXX

				candidate_partition.coalitions.insert(cid);

				::std::vector<gtpack::player_type> coal_players(sub_it->begin(), sub_it->end());
				for (::std::size_t p = 0; p < coal_players.size(); ++p)
				{
					const gtpack::player_type pid = coal_players[p];

					if (visited_coalitions.at(cid).payoffs.count(pid) > 0)
					{
						candidate_partition.payoffs[pid] = visited_coalitions.at(cid).payoffs.at(pid);
					}
					else
					{
						candidate_partition.payoffs[pid] = ::std::numeric_limits<RealT>::quiet_NaN();
					}
				}
			}

			// Check Pareto optimality

			bool pareto_optimal(true);

			// For all players $p$
			for (std::size_t p = 0; p < np && pareto_optimal; ++p)
			{
				const gtpack::player_type pid(players[p]);

				if (::std::isnan(best_payoffs[p]) || candidate_partition.payoffs.at(pid) > best_payoffs[p])
				{
					best_payoffs[p] = candidate_partition.payoffs.at(pid);
				}
				else
				{
					pareto_optimal = false;
				}
			}

			if (pareto_optimal)
			{
				best_partitions.push_back(candidate_partition);
			}
		}

		return best_partitions;
	}