DatabaseServer(RoleConfig roleconfig) : Role(roleconfig), m_db_engine(DBEngineFactory::singleton.instantiate( engine_type.get_rval(roleconfig), roleconfig["engine"], min_id.get_rval(roleconfig), max_id.get_rval(roleconfig))), m_control_channel(control_channel.get_rval(roleconfig)), m_min_id(min_id.get_rval(roleconfig)), m_max_id(max_id.get_rval(roleconfig)) { // Initialize DatabaseServer log std::stringstream log_title; log_title << "Database(" << m_control_channel << ")"; m_log = new LogCategory("db", log_title.str()); // Check to see the engine was instantiated if(!m_db_engine) { m_log->fatal() << "No database engine of type '" << engine_type.get_rval(roleconfig) << "' exists." << std::endl; exit(1); } // Listen on control channel subscribe_channel(m_control_channel); }
MDPerformanceParticipant() : MDParticipantInterface(), num_messages(0) { boost::random::uniform_int_distribution<uint64_t> dist(0, 0xFFFFFFFFFFFFFFFF); for(uint32_t i = 0; i < MD_PERF_NUM_CHANNELS; ++i) { subscribe_channel(dist(gen)); } }
static void subscribe_command(sub_client *c) { int i; for (i = 1; i < c->argc; i++) { subscribe_channel(c, c->argv[i]); } add_reply_string(c, "+subscribe", 10); add_reply_string(c, "\r\n", 2); }
Client::Client(ClientAgent* client_agent) : m_client_agent(client_agent), m_state(CLIENT_STATE_NEW), m_channel(0), m_allocated_channel(0), m_next_context(0), m_owned_objects(), m_seen_objects(), m_interests(), m_pending_interests() { m_channel = m_client_agent->m_ct.alloc_channel(); if(!m_channel) { send_disconnect(CLIENT_DISCONNECT_GENERIC, "Client capacity reached"); return; } m_allocated_channel = m_channel; std::stringstream name; name << "Client (" << m_allocated_channel << ")"; m_log = new LogCategory("client", name.str()); set_con_name(name.str()); subscribe_channel(m_channel); subscribe_channel(BCHAN_CLIENTS); }
void MDNetworkParticipant::network_datagram(Datagram &dg) { DatagramIterator dgi(dg); unsigned short channels = dgi.read_uint8(); if(channels == 1 && dgi.read_uint64() == CONTROL_MESSAGE) { unsigned short msg_type = dgi.read_uint16(); switch(msg_type) { case CONTROL_ADD_CHANNEL: { subscribe_channel(dgi.read_uint64()); } break; case CONTROL_REMOVE_CHANNEL: { unsubscribe_channel(dgi.read_uint64()); } break; case CONTROL_ADD_RANGE: { channel_t lo = dgi.read_uint64(); channel_t hi = dgi.read_uint64(); subscribe_range(lo, hi); } break; case CONTROL_REMOVE_RANGE: { channel_t lo = dgi.read_uint64(); channel_t hi = dgi.read_uint64(); unsubscribe_range(lo, hi); } break; case CONTROL_ADD_POST_REMOVE: { add_post_remove(dgi.read_string()); } break; case CONTROL_CLEAR_POST_REMOVE: { clear_post_removes(); } break; default: logger().error() << "MDNetworkParticipant got unknown control message, type : " << msg_type << std::endl; } return; } send(dg); }
void MDNetworkParticipant::receive_datagram(DatagramHandle dg) { DatagramIterator dgi(dg); uint16_t channels = dgi.read_uint8(); if(channels == 1 && dgi.read_channel() == CONTROL_MESSAGE) { uint16_t msg_type = dgi.read_uint16(); switch(msg_type) { case CONTROL_ADD_CHANNEL: { subscribe_channel(dgi.read_channel()); break; } case CONTROL_REMOVE_CHANNEL: { unsubscribe_channel(dgi.read_channel()); break; } case CONTROL_ADD_RANGE: { channel_t lo = dgi.read_channel(); channel_t hi = dgi.read_channel(); subscribe_range(lo, hi); break; } case CONTROL_REMOVE_RANGE: { channel_t lo = dgi.read_channel(); channel_t hi = dgi.read_channel(); unsubscribe_range(lo, hi); break; } case CONTROL_ADD_POST_REMOVE: { add_post_remove(dgi.read_datagram()); break; } case CONTROL_CLEAR_POST_REMOVE: { clear_post_removes(); break; } case CONTROL_SET_CON_NAME: { set_con_name(dgi.read_string()); break; } case CONTROL_SET_CON_URL: { set_con_url(dgi.read_string()); break; } default: logger().error() << "MDNetworkParticipant got unknown control message, type : " << msg_type << std::endl; } return; } route_datagram(dg); }
void Client::add_interest(Interest &i, uint32_t context) { std::unordered_set<uint32_t> new_zones; for(auto it = i.zones.begin(); it != i.zones.end(); ++it) { if(lookup_interests(i.parent, *it).empty()) { new_zones.insert(*it); } } if(m_interests.find(i.id) != m_interests.end()) { // This is an already-open interest that is actually being altered. // Therefore, we need to delete the objects that the client can see // through this interest only. Interest previous_interest = m_interests[i.id]; std::unordered_set<uint32_t> killed_zones; for(auto it = previous_interest.zones.begin(); it != previous_interest.zones.end(); ++it) { if(lookup_interests(previous_interest.parent, *it).size() > 1) { // An interest other than the altered one can see this parent/zone, // so we don't care about it. continue; } // If we've gotten here: parent,*it is unique, so if the new interest // doesn't cover it, we add it to the killed zones. if(i.parent != previous_interest.parent || i.zones.find(*it) == i.zones.end()) { killed_zones.insert(*it); } } // Now that we know what zones to kill, let's get to it: close_zones(previous_interest.parent, killed_zones); } m_interests[i.id] = i; if(new_zones.empty()) { // We aren't requesting any new zones with this operation, so don't // bother firing off a State Server request. Instead, let the client // know we're already done: handle_interest_done(i.id, context); return; } InterestOperation *iop = new InterestOperation(i.id, context, i.parent, new_zones); uint32_t request_context = m_next_context++; m_pending_interests.insert(std::pair<uint32_t, InterestOperation*>(request_context, iop)); Datagram resp; resp.add_server_header(i.parent, m_channel, STATESERVER_OBJECT_GET_ZONES_OBJECTS); resp.add_uint32(request_context); resp.add_uint32(i.parent); resp.add_uint16(new_zones.size()); for(auto it = new_zones.begin(); it != new_zones.end(); ++it) { resp.add_uint32(*it); subscribe_channel(LOCATION2CHANNEL(i.parent, *it)); } send(resp); }
// handle_datagram is the handler for datagrams received from the Astron cluster void Client::handle_datagram(Datagram &dg, DatagramIterator &dgi) { channel_t sender = dgi.read_uint64(); uint16_t msgtype = dgi.read_uint16(); switch(msgtype) { case CLIENTAGENT_EJECT: { uint16_t reason = dgi.read_uint16(); std::string error_string = dgi.read_string(); send_disconnect(reason, error_string); return; } break; case CLIENTAGENT_DROP: { handle_drop(); return; } break; case CLIENTAGENT_SET_STATE: { m_state = (ClientState)dgi.read_uint16(); } break; case STATESERVER_OBJECT_SET_FIELD: { uint32_t do_id = dgi.read_uint32(); if(!lookup_object(do_id)) { m_log->warning() << "Received server-side field update for unknown object " << do_id << std::endl; return; } if(sender != m_channel) { uint16_t field_id = dgi.read_uint16(); handle_set_field(do_id, field_id, dgi); } } break; case STATESERVER_OBJECT_DELETE_RAM: { uint32_t do_id = dgi.read_uint32(); if(!lookup_object(do_id)) { m_log->warning() << "Received server-side object delete for unknown object " << do_id << std::endl; return; } if(m_seen_objects.find(do_id) != m_seen_objects.end()) { m_seen_objects.erase(do_id); m_id_history.insert(do_id); handle_remove_object(do_id); } if(m_owned_objects.find(do_id) != m_owned_objects.end()) { m_owned_objects.erase(do_id); handle_remove_ownership(do_id); } m_dist_objs.erase(do_id); } break; case STATESERVER_OBJECT_ENTER_OWNER_WITH_REQUIRED_OTHER: case STATESERVER_OBJECT_ENTER_OWNER_WITH_REQUIRED: { uint32_t do_id = dgi.read_uint32(); uint32_t parent = dgi.read_uint32(); uint32_t zone = dgi.read_uint32(); uint16_t dc_id = dgi.read_uint16(); m_owned_objects.insert(do_id); if(m_dist_objs.find(do_id) == m_dist_objs.end()) { VisibleObject obj; obj.id = do_id; obj.parent = parent; obj.zone = zone; obj.dcc = g_dcf->get_class(dc_id); m_dist_objs[do_id] = obj; } handle_add_ownership(do_id, parent, zone, dc_id, dgi, true); } break; case CLIENTAGENT_SET_CLIENT_ID: { if(m_channel != m_allocated_channel) { unsubscribe_channel(m_channel); } m_channel = dgi.read_uint64(); subscribe_channel(m_channel); } break; case CLIENTAGENT_SEND_DATAGRAM: { Datagram forward; forward.add_data(dgi.read_string()); send_datagram(forward); } break; case CLIENTAGENT_OPEN_CHANNEL: { subscribe_channel(dgi.read_uint64()); } break; case CLIENTAGENT_CLOSE_CHANNEL: { unsubscribe_channel(dgi.read_uint64()); } break; case CLIENTAGENT_ADD_POST_REMOVE: { add_post_remove(dgi.read_string()); } break; case CLIENTAGENT_CLEAR_POST_REMOVES: { clear_post_removes(); } break; case STATESERVER_OBJECT_ENTER_LOCATION_WITH_REQUIRED: case STATESERVER_OBJECT_ENTER_LOCATION_WITH_REQUIRED_OTHER: { uint32_t do_id = dgi.read_uint32(); uint32_t parent = dgi.read_uint32(); uint32_t zone = dgi.read_uint32(); uint16_t dc_id = dgi.read_uint16(); if(m_owned_objects.find(do_id) != m_owned_objects.end() || m_seen_objects.find(do_id) != m_seen_objects.end()) { return; } if(m_dist_objs.find(do_id) == m_dist_objs.end()) { VisibleObject obj; obj.id = do_id; obj.dcc = g_dcf->get_class(dc_id); obj.parent = parent; obj.zone = zone; m_dist_objs[do_id] = obj; } m_seen_objects.insert(do_id); handle_add_object(do_id, parent, zone, dc_id, dgi, msgtype == STATESERVER_OBJECT_ENTER_LOCATION_WITH_REQUIRED_OTHER); // TODO: This is a tad inefficient as it checks every pending interest. // In practice, there shouldn't be many add-interest operations active // at once, however. std::list<uint32_t> deferred_deletes; for(auto it = m_pending_interests.begin(); it != m_pending_interests.end(); ++it) { if(it->second->is_ready(m_dist_objs)) { handle_interest_done(it->second->m_interest_id, it->second->m_client_context); deferred_deletes.push_back(it->first); } } for(auto it = deferred_deletes.begin(); it != deferred_deletes.end(); ++it) { m_pending_interests.erase(*it); } } break; case STATESERVER_OBJECT_GET_ZONES_COUNT_RESP: { uint32_t context = dgi.read_uint32(); uint32_t count = dgi.read_uint32(); if(m_pending_interests.find(context) == m_pending_interests.end()) { m_log->error() << "Received GET_ZONES_COUNT_RESP for unknown context " << context << std::endl; return; } m_pending_interests[context]->store_total(count); if(m_pending_interests[context]->is_ready(m_dist_objs)) { handle_interest_done(m_pending_interests[context]->m_interest_id, m_pending_interests[context]->m_client_context); m_pending_interests.erase(context); } } break; case STATESERVER_OBJECT_CHANGING_LOCATION: { uint32_t do_id = dgi.read_uint32(); uint32_t n_parent = dgi.read_uint32(); uint32_t n_zone = dgi.read_uint32(); dgi.read_uint32(); // Old parent; we don't care about this. dgi.read_uint32(); // Old zone; we don't care about this. bool disable = true; for(auto it = m_interests.begin(); it != m_interests.end(); ++it) { Interest &i = it->second; for(auto it2 = i.zones.begin(); it2 != i.zones.end(); ++it2) { if(*it2 == n_zone) { disable = false; break; } } } if(m_dist_objs.find(do_id) != m_dist_objs.end()) { m_dist_objs[do_id].parent = n_parent; m_dist_objs[do_id].zone = n_zone; } if(disable && m_owned_objects.find(do_id) == m_owned_objects.end()) { handle_remove_object(do_id); m_seen_objects.erase(do_id); m_dist_objs.erase(do_id); } else { handle_change_location(do_id, n_parent, n_zone); } } break; default: m_log->error() << "Recv'd unk server msgtype " << msgtype << std::endl; } }