int
ACE_Bounded_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::find_or_create_svc_handler_i
(SVC_HANDLER *&sh,
 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
 ACE_Time_Value *timeout,
 const ACE_PEER_CONNECTOR_ADDR &local_addr,
 bool reuse_addr,
 int flags,
 int perms,
 ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>,
 std::pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
 int &found)
{

  REFCOUNTED_HASH_RECYCLABLE_ADDRESS search_addr (remote_addr);

  // Try to find the address in the cache.  Only if we don't find it
  // do we create a new <SVC_HANDLER> and connect it with the server.
  while (this->find (search_addr, entry) != -1)
    {
      // We found a cached svc_handler.
      // Get the cached <svc_handler>
      sh = entry->int_id_.first ();

      // Is the connection clean?
      int state_result= ACE::handle_ready (sh->peer ().get_handle (),
                                           &ACE_Time_Value::zero,
                                           1, // read ready
                                           0, // write ready
                                           1);// exception ready

      if (state_result == 1)
        {
          // The connection was disconnected during idle.
          // close the svc_handler down.
          if (sh->close () == -1)
            {
              ACE_ASSERT (0);
              return -1;
            }
          sh = 0;
          // and rotate once more...
        }
      else if ((state_result == -1) && (errno == ETIME))
        {
          // Found!!!
          // Set the flag
          found = 1;

          // Tell the <svc_handler> that it should prepare itself for
          // being recycled.
          if (this->prepare_for_recycling (sh) == -1)
            {
              ACE_ASSERT (0);
              return -1;
            }

          return 0;
        }
      else  // some other return value or error...
        {
          ACE_ASSERT (0); // just to see it coming

          ACE_ERROR ((LM_ERROR,
                      ACE_TEXT ("(%t)ACE_Bounded_Cached_Connect_Strategy<>::")
                      ACE_TEXT ("find_or_create_svc_handler_i - ")
                      ACE_TEXT ("error polling server socket state.\n")));

          return -1;
        }
    }

  // Not found...

  // Set the flag
  found = 0;

  // Check the limit of handlers...
  if ((this->max_size_ > 0) &&
      (this->connection_cache_.current_size () >= this->max_size_))
    {
      // Try to purge idle connections
      if (this->purge_connections () == -1)
        return -1;

      // Check limit again.
      if (this->connection_cache_.current_size () >= this->max_size_)
        // still too much!
        return -1;

      // OK, we have room now...
    }

  // We need to use a temporary variable here since we are not
  // allowed to change <sh> because other threads may use this
  // when we let go of the lock during the OS level connect.
  //
  // Note that making a new svc_handler, connecting remotely,
  // binding to the map, and assigning of the hint and recycler
  // should be atomic to the outside world.
  SVC_HANDLER *potential_handler = 0;

  // Create a new svc_handler
  if (this->make_svc_handler (potential_handler) == -1)
    return -1;

  // Connect using the svc_handler.
  if (this->cached_connect (potential_handler,
                            remote_addr,
                            timeout,
                            local_addr,
                            reuse_addr,
                            flags,
                            perms) == -1)
    {
      // Close the svc handler.
      potential_handler->close (0);
      return -1;
    }
  else
    {
      // Insert the new SVC_HANDLER instance into the cache.
      if (this->connection_cache_.bind (search_addr,
                                        potential_handler,
                                        entry) == -1)
        {
          // Close the svc handler and reset <sh>.
          potential_handler->close (0);

          return -1;
        }

      // Everything succeeded as planned. Assign <sh> to
      // <potential_handler>.
      sh = potential_handler;

      // Set the recycler and the recycling act
      this->assign_recycler (sh, this, entry);
    }

  return 0;
}
Example #2
0
void process_serial_nw_ctrl_pkt(GatewayToNodeSerial_Packet *pkt) // CHECKED SO
{
	if(DEBUG_SR == 1)
	{
		nrk_kprintf(PSTR("SR: process_serial_nw_ctrl_pkt(): Received a network control packet of type = \r\n"));
		printf("%x\r\n", pkt -> type);
	}
		
	
	switch(pkt -> type)
	{
		 case SERIAL_ROUTE_REPLY:
							
			unpack_Msg_RouteReply(&mrr, pkt -> data);
			if(DEBUG_SR == 0)
			{
				nrk_kprintf(PSTR("SR: RX SERIAL_ROUTE_REPLY: "));
				printf("%u\r\n", mrr.seq_no);
			}
			
			mrr.dg = NODE_ADDR;				// fill up the default gateway in any case
			
			process_Msg_RouteReply(&mrr); 	// look whether this message contains my address
											// and update routing tables accordingly
			
			// in any case send this packet into the network
			set_nw_pkt_header(&nw_pkt, NODE_ADDR, BCAST_ADDR, BCAST_ADDR, NODE_ADDR, NODE_ADDR, MAX_NETWORK_DIAMETER, ROUTE_REPLY, SIZE_MSG_ROUTE_REPLY, NORMAL_PRIORITY);
			// FIX ME, should nextHop = INVALID_ADDR?
			pack_Msg_RouteReply(nw_pkt.data, &mrr);
			send_nw_pkt_blocking(&nw_pkt);
					
			break;				
		
		case SERIAL_SEND_NW_INFO:
			
			unpack_Msg_SendNwInfo(&msnwi, pkt -> data); // unpack the message from the GatewayToNodeSerial_Packet packet
			if(DEBUG_SR == 0)
			{
				nrk_kprintf(PSTR("SR: RX SERIAL_SEND_NW_INFO: "));
				printf("%u\r\n", msnwi.seq_no);
			}
			
			msnwi.dg = NODE_ADDR;	// fill up the default gateway address in any case
			
			// Check if the gateway is requesting for my NGB_LIST information
			if(search_addr(NODE_ADDR, msnwi.addrs, MAX_SUBNET_SIZE) == TRUE)
				set_continue_sending_ngblist(1);
			
			// create a network layer packet to disseminate this information
			// the function route_addr() will return the correct 'nextHop' address regardless of whether
			// msnwi.addr equals BCAST_ADDR or some other node's address. Again it does not matter if the 
			// gateway knows the route to msnwi.addr or not.
			//set_nw_pkt_header(&nw_pkt, NODE_ADDR, msnwi.addr, route_addr(msnwi.addr), NODE_ADDR, NODE_ADDR, MAX_NETWORK_DIAMETER, SEND_NW_INFO, SIZE_MSG_SEND_NW_INFO, NORMAL_PRIORITY);
			set_nw_pkt_header(&nw_pkt, NODE_ADDR, BCAST_ADDR, BCAST_ADDR, NODE_ADDR, NODE_ADDR, MAX_NETWORK_DIAMETER, SEND_NW_INFO, SIZE_MSG_SEND_NW_INFO, NORMAL_PRIORITY);
			pack_Msg_SendNwInfo(nw_pkt.data, &msnwi);
			send_nw_pkt_blocking(&nw_pkt);
			break;
		
			
		case SERIAL_NW_INFO_ACQUIRED:
			
			unpack_Msg_NwInfoAcquired(&mnwia, pkt -> data); // unpack the message from the GatewayToNodeSerial_Packet packet
			if(DEBUG_SR == 0)
			{
				nrk_kprintf(PSTR("SR: RX SERIAL_NW_INFO_ACQUIRED: "));
				printf("%u\r\n", mnwia.seq_no);
			}
			mnwia.dg = NODE_ADDR;							// fill up the default gateway address in any case
			
			// the gateway has obtained my NGB_LIST information
			if(search_addr(NODE_ADDR, mnwia.addrs, MAX_SUBNET_SIZE) == TRUE)
				set_continue_sending_ngblist(0);
				
			// create a network layer packet to disseminate this information
			set_nw_pkt_header(&nw_pkt, NODE_ADDR, BCAST_ADDR, BCAST_ADDR, NODE_ADDR, NODE_ADDR, MAX_NETWORK_DIAMETER, NW_INFO_ACQUIRED, SIZE_MSG_NW_INFO_ACQUIRED, NORMAL_PRIORITY);
			pack_Msg_NwInfoAcquired(nw_pkt.data, &mnwia);
			send_nw_pkt_blocking(&nw_pkt);
			
			break;
			
		case SERIAL_SEND_NODE_INFO:
			
			unpack_Msg_SendNodeInfo(&msni, pkt -> data); // unpack the message from the GatewayToNodeSerial_Packet packet
			if(DEBUG_SR == 0)
			{
				nrk_kprintf(PSTR("SR: RX SERIAL_SEND_NODE_INFO: "));
				printf("%u\r\n", msni.seq_no);
			}
		
			msni.dg = NODE_ADDR;						// fill up the default gateway address in any case
			// Does the gateway wants my NODE_INFO information?
			if(search_addr(NODE_ADDR, msni.addrs, MAX_SUBNET_SIZE) == TRUE)
				set_continue_sending_nodeinfo(1);
			
			// create a network layer packet to disseminate this information
			// this packet is broadcast into the network
			set_nw_pkt_header(&nw_pkt, NODE_ADDR, BCAST_ADDR, BCAST_ADDR, NODE_ADDR, NODE_ADDR, MAX_NETWORK_DIAMETER, SEND_NODE_INFO, SIZE_MSG_SEND_NODE_INFO, NORMAL_PRIORITY);
			pack_Msg_SendNodeInfo(nw_pkt.data, &msni);
			send_nw_pkt_blocking(&nw_pkt);
			
			break;
		
		case SERIAL_NODE_INFO_ACQUIRED:
		
			unpack_Msg_NodeInfoAcquired(&mnia, pkt -> data); // unpack the message from the GatewayToNodeSerial_Packet packet
			if(DEBUG_SR == 0)
			{
				nrk_kprintf(PSTR("SR: RX SERIAL_NODE_INFO_ACQUIRED: "));
				printf("%u\r\n", mnia.seq_no);
			}
			mnia.dg = NODE_ADDR;							 // fill up the default gateway address in any case
			
			// Has the gateway has obtained my NODE_INFO information?
			if(search_addr(NODE_ADDR, mnia.addrs, MAX_SUBNET_SIZE) == TRUE)
				set_continue_sending_nodeinfo(0);
				
			// create a network layer packet to disseminate this information
			set_nw_pkt_header(&nw_pkt, NODE_ADDR, BCAST_ADDR, BCAST_ADDR, NODE_ADDR, NODE_ADDR, MAX_NETWORK_DIAMETER, NODE_INFO_ACQUIRED, SIZE_MSG_NODE_INFO_ACQUIRED, NORMAL_PRIORITY);
			pack_Msg_NodeInfoAcquired(nw_pkt.data, &mnia);
			send_nw_pkt_blocking(&nw_pkt);
			
			break;
					
		default:
			while(1)
				nrk_kprintf(PSTR("SR: process_serial_nw_ctrl_pkt(): Invalid nw_ctrl packet received: ERROR\r\n"));
	} // end switch()
	
	return;
}
template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class CACHING_STRATEGY, class ATTRIBUTES, class MUTEX> int
ACE_Cached_Connect_Strategy_Ex<SVC_HANDLER, ACE_PEER_CONNECTOR_2, CACHING_STRATEGY, ATTRIBUTES, MUTEX>::find_or_create_svc_handler_i
(SVC_HANDLER *&sh,
 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
 ACE_Time_Value *timeout,
 const ACE_PEER_CONNECTOR_ADDR &local_addr,
 bool reuse_addr,
 int flags,
 int perms,
 ACE_Hash_Map_Entry<ACE_Refcounted_Hash_Recyclable<ACE_PEER_CONNECTOR_ADDR>, std::pair<SVC_HANDLER *, ATTRIBUTES> > *&entry,
 int &found)
{
  REFCOUNTED_HASH_RECYCLABLE_ADDRESS search_addr (remote_addr);

  // Try to find the address in the cache.  Only if we don't find it
  // do we create a new <SVC_HANDLER> and connect it with the server.
  while (this->find (search_addr, entry) != -1)
  {
    // We found a cached svc_handler.
    // Get the cached <svc_handler>
    sh = entry->int_id_.first;

    // Is the connection clean?
    int state_result =
      ACE::handle_ready (sh->peer ().get_handle (),
                         &ACE_Time_Value::zero,
                         1, // read ready
                         0, // write ready
                         1);// exception ready

    if (state_result == 1)
    {

      if (sh->close () == -1)
        return -1;

      sh = 0;

      // Cycle it once again..
    }
    else if ((state_result == -1) && (errno == ETIME))
    {
      // Found!!!
      // Set the flag
      found = 1;

      // Tell the <svc_handler> that it should prepare itself for
      // being recycled.
      if (this->prepare_for_recycling (sh) == -1)
        return -1;

      return 0;
    }
    else
    {
      return -1;
    }
  }

  // Not found...

  // Set the flag
  found = 0;

  // We need to use a temporary variable here since we are not
  // allowed to change <sh> because other threads may use this
  // when we let go of the lock during the OS level connect.
  //
  // Note that making a new svc_handler, connecting remotely,
  // binding to the map, and assigning of the hint and recycler
  // should be atomic to the outside world.
  SVC_HANDLER *potential_handler = 0;

  // Create a new svc_handler
  if (this->make_svc_handler (potential_handler) == -1)
    return -1;

  // Connect using the svc_handler.
  if (this->cached_connect (potential_handler,
                            remote_addr,
                            timeout,
                            local_addr,
                            reuse_addr,
                            flags,
                            perms) == -1)
    {
      // Close the svc handler.
      potential_handler->close (0);

      return -1;
    }
    else
    {
      // Insert the new SVC_HANDLER instance into the cache.
      if (this->connection_cache_.bind (search_addr,
                                        potential_handler,
                                        entry) == -1)
        {
          // Close the svc handler and reset <sh>.
          potential_handler->close (0);

          return -1;
        }

      // Everything succeeded as planned. Assign <sh> to
      // <potential_handler>.
      sh = potential_handler;

      // Set the recycler and the recycling act

      this->assign_recycler (sh, this, entry);
    }

  return 0;
}
Example #4
0
template<class SVC_HANDLER, ACE_PEER_CONNECTOR_1, class MUTEX> int
ACE_Cached_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2, MUTEX>::find_or_create_svc_handler_i
(SVC_HANDLER *&sh,
 const ACE_PEER_CONNECTOR_ADDR &remote_addr,
 ACE_Time_Value *timeout,
 const ACE_PEER_CONNECTOR_ADDR &local_addr,
 int reuse_addr,
 int flags,
 int perms,
 CONNECTION_MAP_ENTRY *&entry,
 int &found)
{
  // Explicit type conversion
  REFCOUNTED_HASH_RECYCLABLE_ADDRESS search_addr (remote_addr);

  // Try to find the address in the cache.  Only if we don't find it
  // do we create a new <SVC_HANDLER> and connect it with the server.
  if (this->find (search_addr, entry) == -1)
    {
      // Set the flag
      found = 0;

      // We need to use a temporary variable here since we are not
      // allowed to change <sh> because other threads may use this
      // when we let go of the lock during the OS level connect.
      //
      // Note that making a new svc_handler, connecting remotely,
      // binding to the map, and assigning of the hint and recycler
      // should be atomic to the outside world.
      SVC_HANDLER *potential_handler = 0;

      // Create a new svc_handler
      if (this->make_svc_handler (potential_handler) == -1)
        return -1;

      // Actively establish the connection.  This is a timed blocking
      // connect.
      if (this->new_connection (potential_handler,
                                remote_addr,
                                timeout,
                                local_addr,
                                reuse_addr,
                                flags,
                                perms) == -1)
        {
          // If connect() failed because of timeouts, we have to
          // reject the connection entirely. This is necessary since
          // currently there is no way for the non-blocking connects
          // to complete and for the <Connector> to notify the cache
          // of the completion of connect().
          if (errno == EWOULDBLOCK)
            errno = ENOTSUP;

          // Close the svc handler.
          potential_handler->close (0);

          return -1;
        }
      else
        {
          // Insert the new SVC_HANDLER instance into the cache.
          if (this->connection_map_.bind (search_addr,
                                          potential_handler,
                                          entry) == -1)
            {
              // Close the svc handler.
              potential_handler->close (CLOSE_DURING_NEW_CONNECTION);

              return -1;
            }

          // Everything succeeded as planned. Assign <sh> to <potential_handler>.
          sh = potential_handler;

          // Set the recycler and the recycling act
          this->assign_recycler (sh, this, entry);
        }
    }
  else
    // We found a cached svc_handler.
    {
      // Set the flag
      found = 1;

      // Get the cached <svc_handler>
      sh = entry->int_id_;

      // Tell the <svc_handler> that it should prepare itself for
      // being recycled.
      this->prepare_for_recycling (sh);
    }

  return 0;
}