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; }
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; }
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; }