コード例 #1
0
ファイル: ThriftServer.cpp プロジェクト: nemith/fbthrift
void ThriftServer::setup() {
  DCHECK_NOTNULL(cpp2Pfac_.get());
  DCHECK_GT(nWorkers_, 0);

  uint32_t threadsStarted = 0;

  // Make sure EBM exists if we haven't set one explicitly
  getEventBaseManager();

  // Initialize event base for this thread, ensure event_init() is called
  serveEventBase_ = eventBaseManager_->getEventBase();
  // Print some libevent stats
  VLOG(1) << "libevent " <<
    TEventBase::getLibeventVersion() << " method " <<
    TEventBase::getLibeventMethod();

  try {
    // We check for write success so we don't need or want SIGPIPEs.
    signal(SIGPIPE, SIG_IGN);

    if (!observer_ && apache::thrift::observerFactory_) {
      observer_ = apache::thrift::observerFactory_->getObserver();
    }

    // We always need a threadmanager for cpp2.
    if (!threadFactory_) {
      setThreadFactory(
        std::make_shared<apache::thrift::concurrency::PosixThreadFactory>(
          apache::thrift::concurrency::PosixThreadFactory::kDefaultPolicy,
          apache::thrift::concurrency::PosixThreadFactory::kDefaultPriority,
          threadStackSizeMB_
        )
      );
    }

    if (saslPolicy_ == "required" || saslPolicy_ == "permitted") {
      if (!saslThreadManager_) {
        auto numThreads = nSaslPoolThreads_ > 0
                              ? nSaslPoolThreads_
                              : (nPoolThreads_ > 0 ? nPoolThreads_ : nWorkers_);
        saslThreadManager_ = ThreadManager::newSimpleThreadManager(
            numThreads,
            0, /* pendingTaskCountMax -- no limit */
            false, /* enableTaskStats */
            0 /* maxQueueLen -- large default */);
        saslThreadManager_->setNamePrefix("thrift-sasl");
        saslThreadManager_->threadFactory(threadFactory_);
        saslThreadManager_->start();
      }
      auto saslThreadManager = saslThreadManager_;

      if (getSaslServerFactory()) {
        // If the factory is already set, don't override it with the default
      } else if (FLAGS_pin_service_identity &&
                 !FLAGS_service_identity.empty()) {
        // If pin_service_identity flag is set and service_identity is specified
        // force the server use the corresponding principal from keytab.
        char hostname[256];
        if (gethostname(hostname, 255)) {
          LOG(FATAL) << "Failed getting hostname";
        }
        setSaslServerFactory([=] (TEventBase* evb) {
          auto saslServer = std::unique_ptr<SaslServer>(
            new GssSaslServer(evb, saslThreadManager));
          saslServer->setServiceIdentity(
            FLAGS_service_identity + "/" + hostname);
          return std::move(saslServer);
        });
      } else {
        // Allow the server to accept anything in the keytab.
        setSaslServerFactory([=] (TEventBase* evb) {
          return std::unique_ptr<SaslServer>(
            new GssSaslServer(evb, saslThreadManager));
        });
      }
    }

    if (!threadManager_) {
      int numThreads = nPoolThreads_ > 0 ? nPoolThreads_ : nWorkers_;
      std::shared_ptr<apache::thrift::concurrency::ThreadManager>
        threadManager(PriorityThreadManager::newPriorityThreadManager(
                        numThreads,
                        true /*stats*/,
                        getMaxRequests() + numThreads /*maxQueueLen*/));
      threadManager->enableCodel(getEnableCodel());
      if (!poolThreadName_.empty()) {
        threadManager->setNamePrefix(poolThreadName_);
      }
      threadManager->start();
      setThreadManager(threadManager);
    }
    threadManager_->setExpireCallback([&](std::shared_ptr<Runnable> r) {
        EventTask* task = dynamic_cast<EventTask*>(r.get());
        if (task) {
          task->expired();
        }
    });
    threadManager_->setCodelCallback([&](std::shared_ptr<Runnable> r) {
        auto observer = getObserver();
        if (observer) {
          observer->queueTimeout();
        }
    });

    if (!serverChannel_) {

      ServerBootstrap::socketConfig.acceptBacklog = listenBacklog_;

      // Resize the IO pool
      ioThreadPool_->setNumThreads(nWorkers_);

      ServerBootstrap::childHandler(
        std::make_shared<ThriftAcceptorFactory>(this));
      {
        std::lock_guard<std::mutex> lock(ioGroupMutex_);
        ServerBootstrap::group(acceptPool_, ioThreadPool_);
      }
      if (socket_) {
        ServerBootstrap::bind(std::move(socket_));
      } else if (port_ != -1) {
        ServerBootstrap::bind(port_);
      } else {
        ServerBootstrap::bind(address_);
      }
      // Update address_ with the address that we are actually bound to.
      // (This is needed if we were supplied a pre-bound socket, or if
      // address_'s port was set to 0, so an ephemeral port was chosen by
      // the kernel.)
      ServerBootstrap::getSockets()[0]->getAddress(&address_);

      for (auto& socket : getSockets()) {
        socket->setShutdownSocketSet(shutdownSocketSet_.get());
        socket->setMaxNumMessagesInQueue(maxNumMsgsInQueue_);
        socket->setAcceptRateAdjustSpeed(acceptRateAdjustSpeed_);
      }

      // Notify handler of the preServe event
      if (eventHandler_ != nullptr) {
        eventHandler_->preServe(&address_);
      }

    } else {
      CHECK(configMutable());
      duplexWorker_ = folly::make_unique<Cpp2Worker>(this, serverChannel_);
    }

    // Do not allow setters to be called past this point until the IO worker
    // threads have been joined in stopWorkers().
    configMutable_ = false;
  } catch (std::exception& ex) {
    // This block allows us to investigate the exception using gdb
    LOG(ERROR) << "Got an exception while setting up the server: "
      << ex.what();
    handleSetupFailure();
    throw;
  } catch (...) {
    handleSetupFailure();
    throw;
  }
}
コード例 #2
0
ファイル: ThriftServer.cpp プロジェクト: UIKit0/fbthrift
void ThriftServer::setup() {
  DCHECK_NOTNULL(cpp2Pfac_.get());
  DCHECK_GT(nWorkers_, 0);

  uint32_t threadsStarted = 0;
  bool eventBaseAttached = false;

  // Make sure EBM exists if we haven't set one explicitly
  getEventBaseManager();

  // Initialize event base for this thread, ensure event_init() is called
  serveEventBase_ = eventBaseManager_->getEventBase();
  // Print some libevent stats
  LOG(INFO) << "libevent " <<
    TEventBase::getLibeventVersion() << " method " <<
    TEventBase::getLibeventMethod();

  try {
    // We check for write success so we don't need or want SIGPIPEs.
    signal(SIGPIPE, SIG_IGN);

    if (!observer_ && apache::thrift::observerFactory_) {
      observer_ = apache::thrift::observerFactory_->getObserver();
    }

    // bind to the socket
    if (socket_ == nullptr) {
      socket_.reset(new TAsyncServerSocket());
      socket_->setShutdownSocketSet(shutdownSocketSet_.get());
      if (port_ != -1) {
        socket_->bind(port_);
      } else {
        DCHECK(address_.isInitialized());
        socket_->bind(address_);
      }
    }

    socket_->listen(listenBacklog_);
    socket_->setMaxNumMessagesInQueue(maxNumMsgsInQueue_);
    socket_->setAcceptRateAdjustSpeed(acceptRateAdjustSpeed_);

    // We always need a threadmanager for cpp2.
    if (!threadFactory_) {
      setThreadFactory(std::shared_ptr<ThreadFactory>(
        new PosixThreadFactory));
    }

    if (!threadManager_) {
      std::shared_ptr<apache::thrift::concurrency::ThreadManager>
        threadManager(PriorityThreadManager::newPriorityThreadManager(
                        nPoolThreads_ > 0 ? nPoolThreads_ : nWorkers_,
                        true /*stats*/));
      threadManager->enableCodel(getEnableCodel());
      threadManager->start();
      setThreadManager(threadManager);
    }
    threadManager_->setExpireCallback([&](std::shared_ptr<Runnable> r) {
        EventTask* task = dynamic_cast<EventTask*>(r.get());
        if (task) {
          task->expired();
        }
    });
    threadManager_->setCodelCallback([&](std::shared_ptr<Runnable> r) {
        auto observer = getObserver();
        if (observer) {
          observer->queueTimeout();
        }
    });

    auto b = std::make_shared<boost::barrier>(nWorkers_ + 1);

    // Create the worker threads.
    workers_.reserve(nWorkers_);
    for (uint32_t n = 0; n < nWorkers_; ++n) {
      addWorker();
      workers_[n].worker->getEventBase()->runInLoop([b](){
        b->wait();
      });
    }

    // Update address_ with the address that we are actually bound to.
    // (This is needed if we were supplied a pre-bound socket, or if address_'s
    // port was set to 0, so an ephemeral port was chosen by the kernel.)
    socket_->getAddress(&address_);

    // Notify handler of the preServe event
    if (eventHandler_ != nullptr) {
      eventHandler_->preServe(&address_);
    }

    for (auto& worker: workers_) {
      worker.thread->start();
      ++threadsStarted;
      worker.thread->setName(folly::to<std::string>("Cpp2Worker",
                                                    threadsStarted));
    }

    // Wait for all workers to start
    b->wait();

    socket_->attachEventBase(eventBaseManager_->getEventBase());
    eventBaseAttached = true;
    socket_->startAccepting();
  } catch (...) {
    // XXX: Cpp2Worker::acceptStopped() calls
    //      eventBase_.terminateLoopSoon().  Normally this stops the
    //      worker from processing more work and stops the event loop.
    //      However, if startConsuming() and eventBase_.loop() haven't
    //      run yet this won't do the right thing. The worker thread
    //      will still continue to call startConsuming() later, and
    //      will then start the event loop.
    for (uint32_t i = 0; i < threadsStarted; ++i) {
      workers_[i].worker->acceptStopped();
      workers_[i].thread->join();
    }
    workers_.clear();

    if (socket_) {
      if (eventBaseAttached) {
        socket_->detachEventBase();
      }

      socket_.reset();
    }

    throw;
  }
}
コード例 #3
0
ファイル: view.cpp プロジェクト: TwilitProgrammer/Equalizer
float View::_computeFocusRatio( Vector3f& eye )
{
    eye = Vector3f::ZERO;
    const Observer* observer = getObserver();
    const FocusMode mode = observer ? observer->getFocusMode() :FOCUSMODE_FIXED;
    if( mode == FOCUSMODE_FIXED )
        return 1.f;

    const Channels& channels = getChannels();
    if( channels.empty( ))
        return 1.f;

    Vector4f view4( Vector3f::FORWARD );
    if( mode == FOCUSMODE_RELATIVE_TO_OBSERVER )
    {
        view4 = observer->getHeadMatrix() * view4;
        eye = observer->getEyeWorld( EYE_CYCLOP );
    }
    Vector3f view = view4;
    view.normalize();

    float distance = std::numeric_limits< float >::max();
    if( getCurrentType() != Frustum::TYPE_NONE ) // frustum from view
    {
        const Wall& wall = getWall();
        const Vector3f w = wall.getW();
        const float denom = view.dot( w );
        if( denom != 0.f ) // view parallel to wall
        {
            const float d = (wall.bottomLeft - eye).dot( w ) / denom;
            if( d > 0.f )
                distance = d;
        }
    }
    else
    {
        // Find closest segment and its distance from cyclop eye
        for( ChannelsCIter i = channels.begin(); i != channels.end(); ++i )
        {
            Segment* segment = (*i)->getSegment();
            segment->inheritFrustum();
            if( segment->getCurrentType() == Frustum::TYPE_NONE )
                continue;

            // http://en.wikipedia.org/wiki/Line-plane_intersection
            const Wall& wall = segment->getWall();
            const Vector3f w = wall.getW();
            const float denom = view.dot( w );
            if( denom == 0.f ) // view parallel to wall
                continue;

            const float d = (wall.bottomLeft - eye).dot( w ) / denom;
            if( d > distance || d <= 0.f ) // further away or behind
                continue;

            distance = d;
            //LBINFO << "Eye " << eye << " is " << d << " from " << wall
            // << std::endl;
        }
    }

    float focusDistance = observer->getFocusDistance();
    if( mode == FOCUSMODE_RELATIVE_TO_ORIGIN )
    {
        eye = observer->getEyeWorld( EYE_CYCLOP );

        if( distance != std::numeric_limits< float >::max( ))
        {
            distance += eye.z();
            focusDistance += eye.z();
            if( fabsf( distance ) <= std::numeric_limits< float >::epsilon( ))
                distance = 2.f * std::numeric_limits< float >::epsilon();
        }
    }

    if( distance == std::numeric_limits< float >::max( ))
        return 1.f;
    return focusDistance / distance;
}
コード例 #4
0
ファイル: ThriftServer.cpp プロジェクト: Jasonudoo/fbthrift
void ThriftServer::setup() {
  DCHECK_NOTNULL(cpp2Pfac_.get());
  DCHECK_GT(nWorkers_, 0);

  uint32_t threadsStarted = 0;
  bool eventBaseAttached = false;

  // Make sure EBM exists if we haven't set one explicitly
  getEventBaseManager();

  // Initialize event base for this thread, ensure event_init() is called
  serveEventBase_ = eventBaseManager_->getEventBase();
  // Print some libevent stats
  LOG(INFO) << "libevent " <<
    TEventBase::getLibeventVersion() << " method " <<
    TEventBase::getLibeventMethod();

  try {
    // We check for write success so we don't need or want SIGPIPEs.
    signal(SIGPIPE, SIG_IGN);

    if (!observer_ && apache::thrift::observerFactory_) {
      observer_ = apache::thrift::observerFactory_->getObserver();
    }

    // bind to the socket
    if (!serverChannel_) {
      if (socket_ == nullptr) {
        socket_.reset(new TAsyncServerSocket());
        socket_->setShutdownSocketSet(shutdownSocketSet_.get());
        if (port_ != -1) {
          socket_->bind(port_);
        } else {
          DCHECK(address_.isInitialized());
          socket_->bind(address_);
        }
      }

      socket_->listen(listenBacklog_);
      socket_->setMaxNumMessagesInQueue(maxNumMsgsInQueue_);
      socket_->setAcceptRateAdjustSpeed(acceptRateAdjustSpeed_);
    }

    // We always need a threadmanager for cpp2.
    if (!threadFactory_) {
      setThreadFactory(
        std::make_shared<apache::thrift::concurrency::NumaThreadFactory>());
    }

    if (FLAGS_sasl_policy == "required" || FLAGS_sasl_policy == "permitted") {
      if (!saslThreadManager_) {
        saslThreadManager_ = ThreadManager::newSimpleThreadManager(
          nPoolThreads_ > 0 ? nPoolThreads_ : nWorkers_, /* count */
          0, /* pendingTaskCountMax -- no limit */
          false, /* enableTaskStats */
          0 /* maxQueueLen -- large default */);
        saslThreadManager_->setNamePrefix("thrift-sasl");
        saslThreadManager_->threadFactory(threadFactory_);
        saslThreadManager_->start();
      }
      auto saslThreadManager = saslThreadManager_;

      if (getSaslServerFactory()) {
        // If the factory is already set, don't override it with the default
      } else if (FLAGS_kerberos_service_name.empty()) {
        // If the service name is not specified, not need to pin the principal.
        // Allow the server to accept anything in the keytab.
        setSaslServerFactory([=] (TEventBase* evb) {
          return std::unique_ptr<SaslServer>(
            new GssSaslServer(evb, saslThreadManager));
        });
      } else {
        char hostname[256];
        if (gethostname(hostname, 255)) {
          LOG(FATAL) << "Failed getting hostname";
        }
        setSaslServerFactory([=] (TEventBase* evb) {
          auto saslServer = std::unique_ptr<SaslServer>(
            new GssSaslServer(evb, saslThreadManager));
          saslServer->setServiceIdentity(
            FLAGS_kerberos_service_name + "/" + hostname);
          return std::move(saslServer);
        });
      }
    }

    if (!threadManager_) {
      std::shared_ptr<apache::thrift::concurrency::ThreadManager>
        threadManager(new apache::thrift::concurrency::NumaThreadManager(
                        nPoolThreads_ > 0 ? nPoolThreads_ : nWorkers_,
                        true /*stats*/,
                        getMaxRequests() /*maxQueueLen*/));
      threadManager->enableCodel(getEnableCodel());
      if (!poolThreadName_.empty()) {
        threadManager->setNamePrefix(poolThreadName_);
      }
      threadManager->start();
      setThreadManager(threadManager);
    }
    threadManager_->setExpireCallback([&](std::shared_ptr<Runnable> r) {
        EventTask* task = dynamic_cast<EventTask*>(r.get());
        if (task) {
          task->expired();
        }
    });
    threadManager_->setCodelCallback([&](std::shared_ptr<Runnable> r) {
        auto observer = getObserver();
        if (observer) {
          observer->queueTimeout();
        }
    });

    if (!serverChannel_) {
      // regular server
      auto b = std::make_shared<boost::barrier>(nWorkers_ + 1);

      // Create the worker threads.
      workers_.reserve(nWorkers_);
      for (uint32_t n = 0; n < nWorkers_; ++n) {
        addWorker();
        workers_[n].worker->getEventBase()->runInLoop([b](){
          b->wait();
        });
      }

      // Update address_ with the address that we are actually bound to.
      // (This is needed if we were supplied a pre-bound socket, or if
      // address_'s port was set to 0, so an ephemeral port was chosen by
      // the kernel.)
      if (socket_) {
        socket_->getAddress(&address_);
      }

      // Notify handler of the preServe event
      if (eventHandler_ != nullptr) {
        eventHandler_->preServe(&address_);
      }

      for (auto& worker: workers_) {
        worker.thread->start();
        ++threadsStarted;
        worker.thread->setName(folly::to<std::string>(cpp2WorkerThreadName_,
                                                      threadsStarted));
      }

      // Wait for all workers to start
      b->wait();

      if (socket_) {
        socket_->attachEventBase(eventBaseManager_->getEventBase());
      }
      eventBaseAttached = true;
      if (socket_) {
        socket_->startAccepting();
      }
    } else {
      // duplex server
      // Create the Cpp2Worker
      DCHECK(workers_.empty());
      WorkerInfo info;
      uint32_t workerID = 0;
      info.worker.reset(new Cpp2Worker(this, workerID, serverChannel_));
      // no thread, use current one (shared with client)
      info.thread = nullptr;

      workers_.push_back(info);
    }
  } catch (...) {
    // XXX: Cpp2Worker::acceptStopped() calls
    //      eventBase_.terminateLoopSoon().  Normally this stops the
    //      worker from processing more work and stops the event loop.
    //      However, if startConsuming() and eventBase_.loop() haven't
    //      run yet this won't do the right thing. The worker thread
    //      will still continue to call startConsuming() later, and
    //      will then start the event loop.
    if (!serverChannel_) {
      for (uint32_t i = 0; i < threadsStarted; ++i) {
        workers_[i].worker->acceptStopped();
        workers_[i].thread->join();
      }
    }
    workers_.clear();

    if (socket_) {
      if (eventBaseAttached) {
        socket_->detachEventBase();
      }

      socket_.reset();
    }

    // avoid crash on stop()
    serveEventBase_ = nullptr;

    throw;
  }
}