Exemple #1
0
		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);
}
Exemple #4
0
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);
}
Exemple #7
0
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);
}
Exemple #8
0
// 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;
	}
}