Ejemplo n.º 1
0
  void TntnetImpl::run()
  {
    log_debug("worker-process");

    _stop = false;

    if (_listeners.empty())
      throwRuntimeError("no listeners defined");

    log_debug(_listeners.size() << " listeners");

    if (_listeners.size() >= _minthreads)
    {
      log_warn("at least one more worker than listeners needed - set MinThreads to "
        << _listeners.size() + 1);
      _minthreads = _listeners.size() + 1;
    }

    if (_maxthreads < _minthreads)
    {
      log_warn("MaxThreads < MinThreads - set MaxThreads = MinThreads = " << _minthreads);
      _maxthreads = _minthreads;
    }

    // initialize worker-process

    // SIGPIPE must be ignored
    ::signal(SIGPIPE, SIG_IGN);

    // create worker-threads
    log_info("create " << _minthreads << " worker threads");
    for (unsigned i = 0; i < _minthreads; ++i)
    {
      log_debug("create worker " << i);
      Worker* s = new Worker(*this);
      s->create();
    }

    // create poller-thread
    log_debug("start poller thread");
    _pollerthread.start();

    log_debug("start timer thread");
    cxxtools::AttachedThread timerThread(cxxtools::callable(*this, &TntnetImpl::timerTask));
    timerThread.start();

    {
      cxxtools::MutexLock lock(allTntnetInstancesMutex);
      allRunningTntnetInstances.insert(this);
    }

    // mainloop
    cxxtools::Mutex mutex;
    while (!_stop)
    {
      {
        cxxtools::MutexLock lock(mutex);
        _queue.noWaitThreads.wait(lock);
      }

      if (_stop)
        break;

      if (Worker::getCountThreads() < _maxthreads)
      {
        log_info("create workerthread");
        Worker* s = new Worker(*this);
        s->create();
      }
      else
        log_info("max worker-threadcount " << _maxthreads << " reached");

      if (TntConfig::it().threadStartDelay > 0)
        usleep(TntConfig::it().threadStartDelay.totalUSecs());
    }

    log_info("stopping TntnetImpl");

    {
      cxxtools::MutexLock lock(allTntnetInstancesMutex);
      allRunningTntnetInstances.erase(this);
    }

    log_info("stop listener");
    for (listeners_type::iterator it = _listeners.begin(); it != _listeners.end(); ++it)
      (*it)->terminate();

    log_info("stop poller thread");
    _poller.doStop();
    _pollerthread.join();

    log_info("stop timer thread");
    timerThread.join();

    if (Worker::getCountThreads() > 0)
    {
      log_info("wait for " << Worker::getCountThreads() << " worker threads to stop");
      while (Worker::getCountThreads() > 0)
      {
        log_debug("wait for worker threads to stop; " << Worker::getCountThreads() << " left");
        usleep(100);
      }
    }

    log_debug("destroy listener");
    for (listeners_type::iterator it = _listeners.begin(); it != _listeners.end(); ++it)
      delete *it;
    _listeners.clear();

    HttpReply::postRunCleanup();
    HttpRequest::postRunCleanup();

    log_info("all threads stopped");
  }
int main( int argc, const char* argv[])
{
	int argi = 1;
	int nofThreads = -1;
	for (; argi < argc && argv[argi][0] == '-'; ++argi)
	{
		if (0==std::strcmp( argv[argi], "--"))
		{
			++argi;
			break;
		}
		else if (0==std::strcmp( argv[argi], "-h") || 0==std::strcmp( argv[argi], "--help"))
		{
			std::cerr << "Usage: testRequestTransactionMap [-h,-V] <nofIterations>" << std::endl;
			return 0;
		}
		else if (0==std::strcmp( argv[argi], "-t") || 0==std::strcmp( argv[argi], "--threads"))
		{
			const char* optarg_ = argv[++argi];
			nofThreads = optarg_ ? atoi( optarg_) : -1;
			if (nofThreads <= 0)
			{
				std::cerr << "argument of option --threads|-t has to be a positive integer: " << (optarg_?optarg_:"NULL") << std::endl;
				return -1;
			}
		}
		else if (0==std::strcmp( argv[argi], "-V") || 0==std::strcmp( argv[argi], "--verbose"))
		{
			g_verbose = true;
		}
		else
		{
			std::cerr << "unknown option " << argv[argi] << " (only --help|-h or --verbose|-V known)" << std::endl;
			return -1;
		}
	}
	int nofIterations = (argc == argi) ? 100 : atoi( argv[argi++]);
	if (nofThreads <= 0)
	{
		nofThreads = strus::platform::cores();
		if (nofThreads <= 0)
		{
			std::cerr << "failed to determine numer of cores, default to 2" << std::endl;
			nofThreads = 2;
		}
		else
		{
			std::cerr << "found " << nofThreads << " cores" << std::endl;
		}
	}
	else
	{
		std::cerr << "number of threads " << nofThreads << " specified as program option." << std::endl;
	}
	if (nofIterations <= 0 || argi < argc)
	{
		std::cerr << "Usage: testRequestTransactionMap [-h,-V,-t <threads>] <nofIterations>" << std::endl;
		return 1;
	}
	try
	{
		g_timecnt_start = g_random.get( 1, std::numeric_limits<int>::max());
		g_timecnt.set( g_timecnt_start);

		enum {MaxTransactionTimeout=60, MinNofTransactionPerSecond=10};
		g_tpool.reset( new strus::TransactionPool( g_timecnt.value(), MaxTransactionTimeout, nofIterations*2*nofThreads + MinNofTransactionPerSecond, NULL/*logger interface*/));
		strus::thread timerThread( &runTimerThread);

		runThreads( nofThreads, nofIterations);
		timerThread.join();
		if (g_errorCounter.value() == 0)
		{
			std::cerr << "OK" << std::endl;
			return 0;
		}
		else
		{
			std::cerr << "ERR " << g_errorCounter.value() << " errors" << std::endl;
			return -1;
		}
	}
	catch (const std::exception& err)
	{
		std::cerr << "ERROR " << err.what() << std::endl;
		return -1;
	}
}