Beispiel #1
0
void
Pool::runAllActions(const boost::container::vector<Callback> &actions) {
	boost::container::vector<Callback>::const_iterator it, end = actions.end();
	for (it = actions.begin(); it != end; it++) {
		(*it)();
	}
}
Beispiel #2
0
cpu_times copy_destroy_time(boost::container::vector<typename C::value_type> &unique_range)
{
   cpu_timer copy_timer, assign_timer, destroy_timer;

   cpu_timer total_time;

   for(std::size_t i = 0; i != NIter; ++i){
      {
         C c(unique_range.begin(), unique_range.end());
         total_time.resume();
         copy_timer.resume();
         C caux(c);
         copy_timer.stop();
         assign_timer.resume();
         c = caux;
         assign_timer.stop();
         destroy_timer.resume();
      }
      destroy_timer.stop();
      total_time.stop();
   }
   total_time.stop();

   std::cout << " Copy sorted range             " << boost::timer::format(copy_timer.elapsed(), boost::timer::default_places, "%ws\n");
   std::cout << " Assign sorted range           " << boost::timer::format(assign_timer.elapsed(), boost::timer::default_places, "%ws\n");
   std::cout << " Destroy                       " << boost::timer::format(destroy_timer.elapsed(), boost::timer::default_places, "%ws\n");
   std::cout << " Total time =                  " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws\n") << std::endl;
   return total_time.elapsed();
}
Beispiel #3
0
cpu_times insert_time( boost::container::vector<typename C::value_type> &unique_range
                     , boost::container::vector<typename C::value_type> &range
                     , const char *RangeType)
{
   cpu_timer ur_timer,r_timer;
   ur_timer.stop();r_timer.stop();

   cpu_timer total_time;
   total_time.resume();

   for(std::size_t i = 0; i != NIter; ++i){
      {
         total_time.resume();
         ur_timer.resume();
         C c;
         c.insert(unique_range.begin(), unique_range.end());
         ur_timer.stop();
         total_time.stop();
      }
      {
         total_time.resume();
         r_timer.resume();
         C c;
         c.insert(range.begin(), range.end());
         r_timer.stop();
         total_time.stop();
      }
   }

   std::cout << " Insert " << RangeType << " unique_range " << boost::timer::format(ur_timer.elapsed(), boost::timer::default_places, "%ws\n");
   std::cout << " Insert " << RangeType << " range        " << boost::timer::format(r_timer.elapsed(), boost::timer::default_places, "%ws\n");
   std::cout << " Total time =              " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws\n") << std::endl;
   return total_time.elapsed();
}
Beispiel #4
0
bool
Group::pushGetWaiter(const Options &newOptions, const GetCallback &callback,
	boost::container::vector<Callback> &postLockActions)
{
	if (OXT_LIKELY(!testOverflowRequestQueue()
		&& (newOptions.maxRequestQueueSize == 0
		    || getWaitlist.size() < newOptions.maxRequestQueueSize)))
	{
		getWaitlist.push_back(GetWaiter(
			newOptions.copyAndPersist().detachFromUnionStationTransaction(),
			callback));
		return true;
	} else {
		postLockActions.push_back(boost::bind(GetCallback::call,
			callback, SessionPtr(), boost::make_shared<RequestQueueFullException>(newOptions.maxRequestQueueSize)));

		HookScriptOptions hsOptions;
		if (prepareHookScriptOptions(hsOptions, "queue_full_error")) {
			// TODO <Feb 17, 2015] DK> should probably rate limit this, since we are already at heavy load
			postLockActions.push_back(boost::bind(runHookScripts, hsOptions));
		}

		return false;
	}
}
Beispiel #5
0
/**
 * Process all waiters on the getWaitlist. Call when capacity has become free.
 * This function assigns sessions to them by calling get() on the corresponding
 * Groups, or by creating more Groups, in so far the new capacity allows.
 */
void
Pool::assignSessionsToGetWaiters(boost::container::vector<Callback> &postLockActions) {
	bool done = false;
	vector<GetWaiter>::iterator it, end = getWaitlist.end();
	vector<GetWaiter> newWaitlist;

	for (it = getWaitlist.begin(); it != end && !done; it++) {
		GetWaiter &waiter = *it;

		Group *group = findMatchingGroup(waiter.options);
		if (group != NULL) {
			SessionPtr session = group->get(waiter.options, waiter.callback,
				postLockActions);
			if (session != NULL) {
				postLockActions.push_back(boost::bind(GetCallback::call,
					waiter.callback, session, ExceptionPtr()));
			}
			/* else: the callback has now been put in
			 *       the group's get wait list.
			 */
		} else if (!atFullCapacityUnlocked()) {
			createGroupAndAsyncGetFromIt(waiter.options, waiter.callback,
				postLockActions);
		} else {
			/* Still cannot satisfy this get request. Keep it on the get
			 * wait list and try again later.
			 */
			newWaitlist.push_back(waiter);
		}
	}

	std::swap(getWaitlist, newWaitlist);
}
/** One of the post lock actions can potentially perform a long-running
 * operation, so running them in a thread is advised.
 */
void
Group::finishShutdown(boost::container::vector<Callback> &postLockActions) {
	TRACE_POINT();
	#ifndef NDEBUG
		LifeStatus lifeStatus = (LifeStatus) this->lifeStatus.load(boost::memory_order_relaxed);
		P_ASSERT_EQ(lifeStatus, SHUTTING_DOWN);
	#endif
	P_DEBUG("Finishing shutdown of group " << info.name);
	if (shutdownCallback) {
		postLockActions.push_back(shutdownCallback);
		shutdownCallback = Callback();
	}
	postLockActions.push_back(boost::bind(interruptAndJoinAllThreads,
		shared_from_this()));
	this->lifeStatus.store(SHUT_DOWN, boost::memory_order_seq_cst);
	selfPointer.reset();
}
Beispiel #7
0
bool check_all_not_empty(boost::container::vector< std::pair<Iterator, Iterator > > &iterator_pairs)
{
   for(std::size_t i = 0, max = iterator_pairs.size(); i != max; ++i){
      if(iterator_pairs[i].first == iterator_pairs[i].second)
         return false;
   }
   return true;
}
Beispiel #8
0
bool check_not_end(boost::container::vector<Iterator> &iterators, Iterator itend, std::size_t number_of_ends = 0)
{
   std::size_t end_count = 0;
   for(std::size_t i = 0, max = iterators.size(); i != max; ++i){
      if(iterators[i] == itend && (++end_count > number_of_ends) )
         return false;
   }
   return true;
}
Beispiel #9
0
void
Pool::assignExceptionToGetWaiters(Queue &getWaitlist,
	const ExceptionPtr &exception,
	boost::container::vector<Callback> &postLockActions)
{
	while (!getWaitlist.empty()) {
		postLockActions.push_back(boost::bind(GetCallback::call,
			getWaitlist.front().callback, SessionPtr(),
			exception));
		getWaitlist.pop_front();
	}
}
Beispiel #10
0
void extensions_time(boost::container::vector<typename C::value_type> &sorted_unique_range)
{
   cpu_timer sur_timer,sur_opt_timer;
   sur_timer.stop();sur_opt_timer.stop();

   for(std::size_t i = 0; i != NIter; ++i){
      {
         sur_timer.resume();
         C c(sorted_unique_range.begin(), sorted_unique_range.end());
         sur_timer.stop();
      }
      {
         sur_opt_timer.resume();
         C c(boost::container::ordered_unique_range, sorted_unique_range.begin(), sorted_unique_range.end());
         sur_opt_timer.stop();
      }

   }
   std::cout << " Construct sorted_unique_range             " << boost::timer::format(sur_timer.elapsed(), boost::timer::default_places, "%ws\n");
   std::cout << " Construct sorted_unique_range (extension) " << boost::timer::format(sur_opt_timer.elapsed(), boost::timer::default_places, "%ws\n");
   std::cout << "Extension/Standard: ";
   compare_times(sur_opt_timer.elapsed(), sur_timer.elapsed());
}
/**
 * Must be called before destroying a Group. You can optionally provide a
 * callback so that you are notified when shutdown has finished.
 *
 * The caller is responsible for migrating waiters on the getWaitlist.
 *
 * One of the post lock actions can potentially perform a long-running
 * operation, so running them in a thread is advised.
 */
void
Group::shutdown(const Callback &callback,
	boost::container::vector<Callback> &postLockActions)
{
	assert(isAlive());
	assert(getWaitlist.empty());

	P_DEBUG("Begin shutting down group " << info.name);
	shutdownCallback = callback;
	detachAll(postLockActions);
	startCheckingDetachedProcesses(true);
	interruptableThreads.interrupt_all();
	postLockActions.push_back(boost::bind(doCleanupSpawner, spawner));
	spawner.reset();
	selfPointer = shared_from_this();
	assert(disableWaitlist.empty());
	lifeStatus.store(SHUTTING_DOWN, boost::memory_order_seq_cst);
}
Beispiel #12
0
void
Group::assignSessionsToGetWaiters(boost::container::vector<Callback> &postLockActions) {
	unsigned int i = 0;
	bool done = false;

	while (!done && i < getWaitlist.size()) {
		const GetWaiter &waiter = getWaitlist[i];
		RouteResult result = route(waiter.options);
		if (result.process != NULL) {
			postLockActions.push_back(boost::bind(
				GetCallback::call,
				waiter.callback,
				newSession(result.process),
				ExceptionPtr()));
			getWaitlist.erase(getWaitlist.begin() + i);
		} else {
			done = result.finished;
			if (!result.finished) {
				i++;
			}
		}
	}
}
Beispiel #13
0
std::size_t generate_elements(boost::container::vector<T> &elements, std::size_t L, std::size_t NK, Compare comp)
{
   elements.resize(L);
   boost::movelib::unique_ptr<std::size_t[]> key_reps(new std::size_t[NK ? NK : L]);

   std::srand(0);
   for (std::size_t i = 0; i < (NK ? NK : L); ++i) {
      key_reps[i] = 0;
   }
   for (std::size_t i = 0; i < L; ++i) {
      std::size_t  key = NK ? (i % NK) : i;
      elements[i].key = key;
   }
   ::random_shuffle(elements.data(), elements.data() + L);
   ::random_shuffle(elements.data(), elements.data() + L);

   for (std::size_t i = 0; i < L; ++i) {
      elements[i].val = key_reps[elements[i].key]++;
   }
   std::size_t split_count = L / 2;
   std::stable_sort(elements.data(), elements.data() + split_count, comp);
   std::stable_sort(elements.data() + split_count, elements.data() + L, comp);
   return split_count;
}
Beispiel #14
0
void fill_range_strings()
{
   boost::container::string model_s;
   model_s.append(sizeof(boost::container::string), '*');

   //sorted_unique_range_int
   sorted_unique_range_string.resize(NElements);
   std::stringstream sstr;

   for(std::size_t i = 0, max = sorted_unique_range_string.size(); i != max; ++i){
      sstr.str(std::string());
      sstr << std::setfill('0') << std::setw(10) << i;
      sorted_unique_range_string[i] = model_s;
      const std::string &s = sstr.str();
      sorted_unique_range_string[i].append(s.begin(), s.end());
   }
   //sorted_range_string
   sorted_range_string = sorted_unique_range_string;
   sorted_range_string.insert(sorted_range_string.end(), sorted_unique_range_string.begin(), sorted_unique_range_string.end());
   std::sort(sorted_range_string.begin(), sorted_range_string.end());

   //random_range_string
   std::srand(0);
   random_range_string.assign(sorted_range_string.begin(), sorted_range_string.end());
   std::random_shuffle(random_range_string.begin(), random_range_string.end());
   //random_unique_range_string
   std::srand(0);
   random_unique_range_string.assign(sorted_unique_range_string.begin(), sorted_unique_range_string.end());
   std::random_shuffle(random_unique_range_string.begin(), random_unique_range_string.end());
}
Beispiel #15
0
void fill_range_ints()
{
   //sorted_unique_range_int
   sorted_unique_range_int.resize(NElements);
   for(std::size_t i = 0, max = sorted_unique_range_int.size(); i != max; ++i){
      sorted_unique_range_int[i] = static_cast<int>(i);
   }
   //sorted_range_int
   sorted_range_int = sorted_unique_range_int;
   sorted_range_int.insert(sorted_range_int.end(), sorted_unique_range_int.begin(), sorted_unique_range_int.end());
   std::sort(sorted_range_int.begin(), sorted_range_int.end());

   //random_range_int
   std::srand(0);
   random_range_int.assign(sorted_range_int.begin(), sorted_range_int.end());
   std::random_shuffle(random_range_int.begin(), random_range_int.end());
   //random_unique_range_int
   std::srand(0);
   random_unique_range_int.assign(sorted_unique_range_int.begin(), sorted_unique_range_int.end());
   std::random_shuffle(random_unique_range_int.begin(), random_unique_range_int.end());
}
Beispiel #16
0
cpu_times search_time(boost::container::vector<typename C::value_type> &unique_range, const char *RangeType)
{
   cpu_timer find_timer, lower_timer, upper_timer, equal_range_timer, count_timer;

   C c(unique_range.begin(), unique_range.end());

   cpu_timer total_time;
   total_time.resume();

   boost::container::vector<typename C::iterator> v_it(NElements);
   boost::container::vector< std::pair<typename C::iterator, typename C::iterator> > v_itp(NElements);

   for(std::size_t i = 0; i != NIter; ++i){
      //Find
      {
         find_timer.resume();
         for(std::size_t rep = 0; rep != 2; ++rep)
         for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){
            v_it[i] = c.find(unique_range[i]);
         }
         find_timer.stop();
         if(!check_not_end(v_it, c.end())){
            std::cout << "ERROR! find all elements not found" << std::endl;
         }
      }
      //Lower
      {
         lower_timer.resume();
         for(std::size_t rep = 0; rep != 2; ++rep)
         for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){
            v_it[i] = c.lower_bound(unique_range[i]);
         }
         lower_timer.stop();
         if(!check_not_end(v_it, c.end())){
            std::cout << "ERROR! lower_bound all elements not found" << std::endl;
         }
      }
      //Upper
      {
         upper_timer.resume();
         for(std::size_t rep = 0; rep != 2; ++rep)
         for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){
            v_it[i] = c.upper_bound(unique_range[i]);
         }
         upper_timer.stop();
         if(!check_not_end(v_it, c.end(), 1u)){
            std::cout << "ERROR! upper_bound all elements not found" << std::endl;
         }
      }
      //Equal
      {
         equal_range_timer.resume();
         for(std::size_t rep = 0; rep != 2; ++rep)
         for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){
            v_itp[i] = c.equal_range(unique_range[i]);
         }
         equal_range_timer.stop();
         if(!check_all_not_empty(v_itp)){
            std::cout << "ERROR! equal_range all elements not found" << std::endl;
         }
      }
      //Count
      {
         std::size_t count = 0;
         count_timer.resume();
         for(std::size_t rep = 0; rep != 2; ++rep)
         for(std::size_t i = 0, max = unique_range.size(); i != max; ++i){
            count += c.count(unique_range[i]);
         }
         count_timer.stop();
         if(count/2 != c.size()){
            std::cout << "ERROR! count all elements not found" << std::endl;
         }
      }
   }
   total_time.stop();

   std::cout << " Find        " << RangeType << " " << boost::timer::format(find_timer.elapsed(), boost::timer::default_places, "%ws\n");
   std::cout << " Lower Bound " << RangeType << " " << boost::timer::format(lower_timer.elapsed(), boost::timer::default_places, "%ws\n");
   std::cout << " Upper Bound " << RangeType << " " << boost::timer::format(upper_timer.elapsed(), boost::timer::default_places, "%ws\n");
   std::cout << " Equal Range " << RangeType << " " << boost::timer::format(equal_range_timer.elapsed(), boost::timer::default_places, "%ws\n");
   std::cout << " Count       " << RangeType << " " << boost::timer::format(count_timer.elapsed(), boost::timer::default_places, "%ws\n");
   std::cout << " Total time =      " << boost::timer::format(total_time.elapsed(), boost::timer::default_places, "%ws\n") << std::endl;
   return total_time.elapsed();
}
Beispiel #17
0
void
Group::cleanupSpawner(boost::container::vector<Callback> &postLockActions) {
	assert(isAlive());
	postLockActions.push_back(boost::bind(doCleanupSpawner, spawner));
}
Beispiel #18
0
// The 'self' parameter is for keeping the current Group object alive while this thread is running.
void
Group::finalizeRestart(GroupPtr self,
	Options oldOptions,
	Options newOptions, RestartMethod method,
	SpawningKit::FactoryPtr spawningKitFactory,
	unsigned int restartsInitiated,
	boost::container::vector<Callback> postLockActions)
{
	TRACE_POINT();

	Pool::runAllActions(postLockActions);
	postLockActions.clear();

	this_thread::disable_interruption di;
	this_thread::disable_syscall_interruption dsi;

	// Create a new spawner.
	Options spawnerOptions = oldOptions;
	resetOptions(newOptions, &spawnerOptions);
	SpawningKit::SpawnerPtr newSpawner = spawningKitFactory->create(spawnerOptions);
	SpawningKit::SpawnerPtr oldSpawner;

	UPDATE_TRACE_POINT();
	Pool *pool = getPool();

	Pool::DebugSupportPtr debug = pool->debugSupport;
	if (debug != NULL && debug->restarting) {
		this_thread::restore_interruption ri(di);
		this_thread::restore_syscall_interruption rsi(dsi);
		this_thread::interruption_point();
		debug->debugger->send("About to end restarting");
		debug->messages->recv("Finish restarting");
	}

	ScopedLock l(pool->syncher);
	if (!isAlive()) {
		P_DEBUG("Group " << getName() << " is shutting down, so aborting restart");
		return;
	}
	if (restartsInitiated != this->restartsInitiated) {
		// Before this restart could be finalized, another restart command was given.
		// The spawner we just created might be out of date now so we abort.
		P_DEBUG("Restart of group " << getName() << " aborted because a new restart was initiated concurrently");
		if (debug != NULL && debug->restarting) {
			debug->debugger->send("Restarting aborted");
		}
		return;
	}

	// Run some sanity checks.
	pool->fullVerifyInvariants();
	assert(m_restarting);
	UPDATE_TRACE_POINT();

	// Atomically swap the new spawner with the old one.
	resetOptions(newOptions);
	oldSpawner = spawner;
	spawner    = newSpawner;

	m_restarting = false;
	if (shouldSpawn()) {
		spawn();
	} else if (isWaitingForCapacity()) {
		P_INFO("Group " << getName() << " is waiting for capacity to become available. "
			"Trying to shutdown another idle process to free capacity...");
		if (pool->forceFreeCapacity(this, postLockActions) != NULL) {
			spawn();
		} else {
			P_INFO("There are no processes right now that are eligible "
				"for shutdown. Will try again later.");
		}
	}
	verifyInvariants();

	l.unlock();
	oldSpawner.reset();
	Pool::runAllActions(postLockActions);
	P_DEBUG("Restart of group " << getName() << " done");
	if (debug != NULL && debug->restarting) {
		debug->debugger->send("Restarting done");
	}
}
static void reset_alloc_stats(bc::vector<T, Allocator> &v)
   { v.reset_alloc_stats(); }
Beispiel #20
0
 ~Data()
 {
     assert(iterators.empty());
 }