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