giopserver.cc

来自「编译工具」· CC 代码 · 共 1,880 行 · 第 1/4 页

CC
1,880
字号
      if (conn->pd_has_dedicated_thread) {	giopWorker* task = new giopWorker(cs->strand, this, 0);	if (!orbAsyncInvoker->insert(task)) {	  // Cannot start serving this new connection.	  if (omniORB::trace(1)) {	    omniORB::logger log;	    log << "Cannot create a worker for this endpoint: "		<< conn->myaddress()		<< " from "		<< conn->peeraddress()		<< "\n";	  }	  delete task;	  {	    omni_tracedmutex_lock sync(*omniTransportLock);	    cs->strand->safeDelete();	  }	  csRemove(conn);	  pd_lock.unlock();	  delete cs;	  pd_lock.lock();	  throw outOfResource();	}	task->insert(cs->workers);	conn->pd_n_workers++;	pd_n_dedicated_workers++;      }      else {	if (!conn->isSelectable()) {	  if (omniORB::trace(20)) {	    omniORB::logger log;	    log << "Connection from " << conn->peeraddress()		<< " is not selectable. Closing it.\n";	  }	  {	    omni_tracedmutex_lock sync(*omniTransportLock);	    cs->strand->safeDelete();	  }	  csRemove(conn);	  pd_lock.unlock();	  delete cs;	  pd_lock.lock();	  throw outOfResource();	}	pd_lock.unlock();	conn->setSelectable(1);	pd_lock.lock();      }      break;    }  default:    if (omniORB::trace(25)) {      omniORB::logger l;      l << "giopServer terminate connection from "	<< conn->peeraddress() << ".\n";    }    throw Terminate();  }}////////////////////////////////////////////////////////////////////////////voidgiopServer::notifyRzDone(giopRendezvouser* r, CORBA::Boolean exit_on_error){  omni_tracedmutex_lock sync(pd_lock);  if (!exit_on_error) {    OMNIORB_ASSERT(pd_state == INFLUX);    // For the moment, we do not instantiate giopRendezvouser to do    // single shot.    // Therefore, this function will *NEVER* be called until:    //  1. We have called deactivate()    //  2. giopRendezvouser have encountered a non-recoverable error. In which    //     case exit_on_error == 1.  }  giopEndpoint* ept = r->endpoint();  if (omniORB::trace(25)) {    omniORB::logger l;    l << "giopRendezvouser for endpoint " << ept->address() << " exit.\n";  }  r->remove();  delete r;  if (exit_on_error) {    if (omniORB::trace(1)) {      omniORB::logger log;      log << "Unrecoverable error for this endpoint: ";      log << ept->address();      log << ", it will no longer be serviced.\n";    }    ept->Shutdown();  }  else {    pd_endpoints.push_back(ept);    // A new giopRendezvouser will be instantiated for this endpoint next    // time activate() is called.  }  if (pd_state == INFLUX) {    if (Link::is_empty(pd_rendezvousers)) {      pd_cond.broadcast();    }  }}////////////////////////////////////////////////////////////////////////////voidgiopServer::notifyRzReadable(giopConnection* conn,			     CORBA::Boolean force_create){  // Theory of operation: read the state diagrams at the end of this file.  omni_tracedmutex_lock sync(pd_lock);  switch (pd_state) {  case ACTIVE:  case INFLUX:    {      if (conn->pd_dying) return;      if (!force_create &&	  conn->pd_n_workers >= (int)orbParameters::maxServerThreadPerConnection) {	conn->pd_has_hit_n_workers_limit = 1;	return;      }      connectionState* cs = csLocate(conn);      if (!cs) return;      giopWorker* task = new giopWorker(cs->strand,this,1);      if (!orbAsyncInvoker->insert(task)) {	// Cannot start serving this new connection.	// Should never happen	OMNIORB_ASSERT(0);      }      task->insert(cs->workers);      conn->pd_n_workers++;      pd_n_temporary_workers++;      break;    }  default:    break;  }}////////////////////////////////////////////////////////////////////////////voidgiopServer::notifyCallFullyBuffered(giopConnection* conn){  notifyRzReadable(conn,1);}////////////////////////////////////////////////////////////////////////////voidgiopServer::removeConnectionAndWorker(giopWorker* w){  ASSERT_OMNI_TRACEDMUTEX_HELD(pd_lock, 0);  connectionState* cs;  CORBA::Boolean   cs_removed = 0;  {    omni_tracedmutex_lock sync(pd_lock);    giopConnection* conn = w->strand()->connection;    conn->pd_dying = 1; // From now on, the giopServer will not create                        // any more workers to serve this connection.    cs = csLocate(conn);    // We remove the lock on pd_lock before calling the connection's    // clearSelectable(). This is necessary so that a simultaneous    // callback from the Rendezvouser thread will have a chance to    // look at the connectionState table.    pd_lock.unlock();    conn->clearSelectable();    // Once we reach here, it is certain that the rendezvouser thread    // would not take any interest in this connection anymore. It    // is therefore safe to delete this record.    pd_lock.lock();    int workers;    if (w->singleshot())      workers = --pd_n_temporary_workers;    else      workers = --pd_n_dedicated_workers;    w->remove();    delete w;    conn->pd_n_workers--;    if (Link::is_empty(cs->workers)) {      csRemove(conn);      cs_removed = 1;    }    if (pd_state == INFLUX) {      if (workers == 0) {	pd_cond.broadcast();      }    }  }  // Must not hold pd_lock when deleting cs, since the deletion may  // cause a call to SocketCollection::removeSocket(), which needs to  // lock the fdset lock. The fdset lock comes before pd_lock in the  // partial order.  if (cs_removed)    delete cs;}////////////////////////////////////////////////////////////////////////////CORBA::BooleangiopServer::notifyWkDone(giopWorker* w, CORBA::Boolean exit_on_error){  // Theory of operation: read the state diagrams at the end of this file.  ASSERT_OMNI_TRACEDMUTEX_HELD(pd_lock,0);  if (exit_on_error) {    removeConnectionAndWorker(w);    return 0;  }  giopConnection* conn = w->strand()->connection;  if (conn->pd_has_dedicated_thread) {    // This connection is managed with the thread-per-connection policy    if (!w->singleshot()) {      // This is the dedicated thread      conn->clearSelectable();      omni_tracedmutex_lock sync(pd_lock);      conn->pd_dedicated_thread_in_upcall = 0;      conn->pd_has_hit_n_workers_limit = 0;      return 1;    }    else {      // This is a temporary worker thread      omni_tracedmutex_lock sync(pd_lock);      if (conn->pd_has_hit_n_workers_limit) {	// Previously we have hit the limit on the no. of worker threads,	// There is definitely a request pending. We re-cycle this	// worker to deal with it *UNLESS* the dedicated thread is already	// doing so.	conn->pd_has_hit_n_workers_limit = 0;	if (conn->pd_dedicated_thread_in_upcall ) {	  return 1;	}      }      if (conn->pd_n_workers == 1 && conn->pd_dying) {	// Connection is dying. Go round again so this thread spots	// the condition.	omniORB::logs(25, "Last worker sees connection is dying.");	return 1;      }      w->remove();      delete w;      conn->pd_n_workers--;      pd_n_temporary_workers--;      if (pd_state == INFLUX && pd_n_temporary_workers == 0)	pd_cond.broadcast();      return 0;    }  }  else {    // This connection is managed with the thread-pool policy.    OMNIORB_ASSERT(w->singleshot() == 1); // Never called by a dedicated thread    CORBA::Boolean select_and_return = 0;    {      omni_tracedmutex_lock sync(pd_lock);      if (conn->pd_has_hit_n_workers_limit) {	// Previously we have hit the limit on the no. of worker threads,	// There is definitely a request pending. We re-cycle this	// worker to deal with it.	conn->pd_has_hit_n_workers_limit = 0;	return 1;      }      // If there are other workers for this connection, or there are      // too many temporary workers, let this worker finish.      if (conn->pd_n_workers > orbParameters::threadPoolWatchConnection ||	  pd_n_temporary_workers > orbParameters::maxServerThreadPoolSize) {	select_and_return = 1;      }    }    if (!select_and_return) {      // Call Peek(). This thread will be used for a short time to      // monitor the connection. If the connection is available for      // reading, the callback function peekCallBack is called. We can      // probably afford to call Peek() here because this thread is      // otherwise idle.      CORBA::Boolean readable = 0;      conn->Peek(peekCallBack,(void*)&readable);      if (readable) {	// There is data to be read. Tell the worker to go around again.	return 1;      }    }    // If connection is selectable, it's selectable now    if (!conn->pd_dying)      conn->setSelectable(2);    // Worker is no longer needed.    {      omni_tracedmutex_lock sync(pd_lock);      w->remove();      delete w;      conn->pd_n_workers--;      pd_n_temporary_workers--;      if (pd_state == INFLUX) {	omniORB::logs(25, "Temporary worker finishing.");	if (pd_n_temporary_workers == 0)	  pd_cond.broadcast();      }    }    return 0;  }#ifndef __DECCXX  // Never reach here (and the hp/compaq/dec compiler is smart enough  // to figure that out).  OMNIORB_ASSERT(0);  return 0;#endif}////////////////////////////////////////////////////////////////////////////// Callback function used by giopConnection::Peek(). Called when the// connection indeed has something to read immediately.voidgiopServer::peekCallBack(void* cookie, giopConnection* conn) {  CORBA::Boolean* readable = (CORBA::Boolean*)cookie;  *readable = 1;}////////////////////////////////////////////////////////////////////////////voidgiopServer::notifyWkPreUpCall(giopWorker* w, CORBA::Boolean data_in_buffer) {  // Theory of operation: read the state diagrams at the end of this file.  ASSERT_OMNI_TRACEDMUTEX_HELD(pd_lock,0);  giopConnection* conn = w->strand()->connection;  if (conn->pd_has_dedicated_thread) {    // This connection is managed with the thread-per-connection policy    if (!w->singleshot()) {      // This is the dedicated thread.      // setSelectable.      {	omni_tracedmutex_lock sync(pd_lock);	conn->pd_dedicated_thread_in_upcall = 1;      }      if (orbParameters::maxServerThreadPerConnection > 1) {	// If only one thread per connection is allowed, there is no	// need to setSelectable, since we won't be able to act on any	// interleaved calls that arrive.	conn->setSelectable(orbParameters::connectionWatchImmediate,			    data_in_buffer);      }    }    else {      // This is a temporary worker thread      // setSelectable only if the dedicated thread is in upcall.      CORBA::Boolean n;      {	omni_tracedmutex_lock sync(pd_lock);	n = conn->pd_dedicated_thread_in_upcall;      }      if (n) {	conn->setSelectable(orbParameters::connectionWatchImmediate,			    data_in_buffer);      }    }  }  else {    // This connection is managed with the thread-pool policy    conn->setSelectable(orbParameters::connectionWatchImmediate,			data_in_buffer);  }}////////////////////////////////////////////////////////////////////////////CORBA::BooleangiopServer::notifySwitchToBiDirectional(giopConnection* conn){  return 1;  // Note: we could override the threading policy to dictate that all  //       bidirectional connection will be served by a dedicated thread  //       on the server side. }////////////////////////////////////////////////////////////////////////////voidgiopServer::notifyMrDone(giopMonitor* m, CORBA::Boolean exit_on_error){  ASSERT_OMNI_TRACEDMUTEX_HELD(pd_lock,0);  omni_tracedmutex_lock sync(pd_lock);  if (!exit_on_error && !m->collection()->isEmpty()) {    // We may have seen a race condition in which the Monitor is about    // to return when another connection has been added to be monitored.    // We should not remove the monitor in this case.    if (orbAsyncInvoker->insert(m)) {      return;    }    // Otherwise, we let the following deal with it.  }  m->remove();  delete m;  if (pd_state == INFLUX) {    if (Link::is_empty(pd_bidir_monitors)) {      pd_cond.broadcast();    }  }}////////////////////////////////////////////////////////////////////////////voidgiopServer::Link::insert(giopServer::Link& head){  next = head.prev->next;  head.prev->next = this;  prev = head.prev;  head.prev = this;}////////////////////////////////////////////////////////////////////////////voidgiopServer::Link::remove(){  prev->next = next;  next->prev = prev;  next = prev = this;}////////////////////////////////////////////////////////////////////////////CORBA::BooleangiopServer::Link::is_empty(giopServer::Link& head){  return (head.next == &head);}/////////////////////////////////////////////////////////////////////////////giopServer*&giopServer::singleton() {  static giopServer* singleton_ = 0;  if (!singleton_) {    singleton_ = new giopServer();  }  return singleton_;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?