コード例 #1
0
ファイル: DBStateServer.cpp プロジェクト: Astron/Astron
void DBStateServer::handle_get_fields_resp(DatagramIterator& dgi)
{
    uint32_t db_context = dgi.read_uint32();
    if(!is_expected_context(db_context)) {
        return;
    }

    // Get the datagram from the db_context
    DatagramPtr dg = m_context_datagrams[db_context];
    m_context_datagrams.erase(db_context);

    // Check to make sure the datagram is appropriate
    DatagramIterator check_dgi = DatagramIterator(dg);
    uint16_t resp_type = check_dgi.get_msg_type();
    if(resp_type != STATESERVER_OBJECT_GET_FIELDS_RESP) {
        if(resp_type == STATESERVER_OBJECT_GET_FIELD_RESP) {
            m_log->warning() << "Received GetFieldResp, but expecting GetFieldsResp." << std::endl;
        } else if(resp_type == STATESERVER_OBJECT_GET_ALL_RESP) {
            m_log->warning() << "Received GetAllResp, but expecting GetFieldsResp." << std::endl;
        }
        return;
    }

    m_log->trace() << "Received GetFieldResp from database." << std::endl;

    // Add database field payload to response (don't know dclass, so must copy payload).
    if(dgi.read_bool() == true) {
        dgi.read_uint16(); // Discard field count
        dg->add_data(dgi.read_remainder());
    }
    route_datagram(dg);
}
コード例 #2
0
ファイル: DBStateServer.cpp プロジェクト: Astron/Astron
void DBStateServer::handle_get_all_resp(DatagramIterator& dgi)
{
    uint32_t db_context = dgi.read_uint32();
    if(!is_expected_context(db_context)) {
        return;
    }

    // Get the datagram from the db_context
    DatagramPtr dg = m_context_datagrams[db_context];
    m_context_datagrams.erase(db_context);

    // Check to make sure the datagram is appropriate
    DatagramIterator check_dgi = DatagramIterator(dg);
    uint16_t resp_type = check_dgi.get_msg_type();
    if(resp_type != STATESERVER_OBJECT_GET_ALL_RESP) {
        if(resp_type == STATESERVER_OBJECT_GET_FIELD_RESP) {
            m_log->warning() << "Received GetFieldResp, but expecting GetAllResp." << std::endl;
        } else if(resp_type == STATESERVER_OBJECT_GET_FIELDS_RESP) {
            m_log->warning() << "Received GetFieldsResp, but expecting GetAllResp." << std::endl;
        }
        return;
    }

    // Get do_id from datagram
    check_dgi.seek_payload();
    check_dgi.skip(sizeof(channel_t) + sizeof(doid_t)); // skip over sender and context to do_id;
    doid_t do_id = check_dgi.read_doid();

    // Remove cached loading operation
    if(m_inactive_loads[do_id].size() > 1) {
        m_inactive_loads[do_id].erase(db_context);
    } else {
        m_inactive_loads.erase(do_id);
    }

    m_log->trace() << "Received GetAllResp from database." << std::endl;

    // If object not found, just cleanup the context map
    if(dgi.read_bool() != true) {
        return; // Object not found
    }

    // Read object class
    uint16_t dc_id = dgi.read_uint16();
    if(!dc_id) {
        m_log->error() << "Received object from database with unknown dclass"
                       << " - id:" << dc_id << std::endl;
        return;
    }
    const Class* r_class = g_dcf->get_class_by_id(dc_id);

    // Get fields from database
    UnorderedFieldValues required_fields;
    FieldValues ram_fields;
    if(!unpack_db_fields(dgi, r_class, required_fields, ram_fields)) {
        m_log->error() << "Error while unpacking fields from database." << std::endl;
        return;
    }

    // Add class to response
    dg->add_uint16(r_class->get_id());

    // Add required fields to datagram
    int dcc_field_count = r_class->get_num_fields();
    for(int i = 0; i < dcc_field_count; ++i) {
        const Field *field = r_class->get_field(i);
        if(!field->as_molecular() && field->has_keyword("required")) {
            auto req_it = required_fields.find(field);
            if(req_it != required_fields.end()) {
                dg->add_data(req_it->second);
            } else {
                dg->add_data(field->get_default_value());
            }
        }
    }

    // Add ram fields to datagram
    dg->add_uint16(ram_fields.size());
    for(const auto& it : ram_fields) {
        dg->add_uint16(it.first->get_id());
        dg->add_data(it.second);
    }

    // Send response back to caller
    route_datagram(dg);
}
コード例 #3
0
ファイル: LoadingObject.cpp プロジェクト: Echocage/Astron
void LoadingObject::handle_datagram(DatagramHandle in_dg, DatagramIterator &dgi)
{
	/*channel_t sender =*/ dgi.read_channel(); // sender not used
	uint16_t msgtype = dgi.read_uint16();
	switch(msgtype)
	{
		case DBSERVER_OBJECT_GET_ALL_RESP:
		{
			if(m_is_loaded)
			{
				break; // Don't care about these message any more if loaded
			}

			uint32_t db_context = dgi.read_uint32();
			if(db_context != m_context &&
			   m_valid_contexts.find(db_context) == m_valid_contexts.end())
			{
				m_log->warning() << "Received get_all_resp with incorrect context '"
				                 << db_context << "'.\n";
				break;
			}

			m_log->trace() << "Received GetAllResp from database.\n";
			m_is_loaded = true;

			if(dgi.read_bool() != true)
			{
				m_log->debug() << "Object not found in database.\n";
				m_dbss->discard_loader(m_do_id);
				forward_datagrams();
				break;
			}

			uint16_t dc_id = dgi.read_uint16();
			const Class *r_dclass = g_dcf->get_class_by_id(dc_id);
			if(!r_dclass)
			{
				m_log->error() << "Received object from database with unknown dclass"
				               << " - id:" << dc_id << std::endl;
				m_dbss->discard_loader(m_do_id);
				forward_datagrams();
				break;
			}

			if(m_dclass && r_dclass != m_dclass)
			{
				m_log->error() << "Requested object of class '" << m_dclass->get_id()
				               << "', but received class " << dc_id << std::endl;
				m_dbss->discard_loader(m_do_id);
				forward_datagrams();
				break;
			}

			// Get fields from database
			if(!unpack_db_fields(dgi, r_dclass, m_required_fields, m_ram_fields))
			{
				m_log->error() << "Error while unpacking fields from database.\n";
				m_dbss->discard_loader(m_do_id);
				forward_datagrams();
				break;
			}

			// Add default values and updated values
			int dcc_field_count = r_dclass->get_num_fields();
			for(int i = 0; i < dcc_field_count; ++i)
			{
				const Field *field = r_dclass->get_field(i);
				if(!field->as_molecular())
				{
					if(field->has_keyword("required"))
					{
						if(m_field_updates.find(field) != m_field_updates.end())
						{
							m_required_fields[field] = m_field_updates[field];
						}
						else if(m_required_fields.find(field) == m_required_fields.end())
						{
							std::string val = field->get_default_value();
							m_required_fields[field] = std::vector<uint8_t>(val.begin(), val.end());
						}
					}
					else if(field->has_keyword("ram"))
					{
						if(m_field_updates.find(field) != m_field_updates.end())
						{
							m_ram_fields[field] = m_field_updates[field];
						}
					}
				}
			}

			// Create object on stateserver
			DistributedObject* obj = new DistributedObject(m_dbss, m_dbss->m_db_channel, m_do_id,
			        m_parent_id, m_zone_id, r_dclass,
			        m_required_fields, m_ram_fields);

			// Tell DBSS about object and handle datagram queue
			m_dbss->receive_object(obj);
			replay_datagrams(obj);

			// Cleanup this loader
			m_dbss->discard_loader(m_do_id);
			forward_datagrams();
			break;
		}
		case DBSS_OBJECT_ACTIVATE_WITH_DEFAULTS:
		case DBSS_OBJECT_ACTIVATE_WITH_DEFAULTS_OTHER:
		{
			// Don't cache these messages in the queue, they are received and
			// handled by the DBSS.  Since the object is already loading they
			// are simply ignored (the DBSS may generate a warning/error).
			break;
		}
		default:
		{
			m_datagram_queue.push_back(in_dg);
		}
	}
}