void DBOperationUpdate::on_criteria_mismatch(DBObjectSnapshot *snapshot) { DatagramPtr resp = Datagram::create(); resp->add_server_header(m_sender, m_dbserver->m_control_channel, m_resp_msgtype); resp->add_uint32(m_context); resp->add_uint8(FAILURE); // Calculate the fields that we are sending in our response: FieldValues mismatched_fields; for(auto it = m_criteria_fields.begin(); it != m_criteria_fields.end(); ++it) { auto it2 = snapshot->m_fields.find(it->first); if(it2 != snapshot->m_fields.end() && !it2->second.empty()) { mismatched_fields[it2->first] = it2->second; } } if(m_resp_msgtype == DBSERVER_OBJECT_SET_FIELDS_IF_EQUALS_RESP) { resp->add_uint16(mismatched_fields.size()); } for(auto it = mismatched_fields.begin(); it != mismatched_fields.end(); ++it) { resp->add_uint16(it->first->get_id()); resp->add_data(it->second); } m_dbserver->route_datagram(resp); delete snapshot; cleanup(); }
void DBOperation::announce_fields(const FieldValues& fields) { // Calculate the fields that we are sending in our response: FieldValues changed_fields; FieldSet deleted_fields; for(auto it = fields.begin(); it != fields.end(); ++it) { if(it->second.empty()) deleted_fields.insert(it->first); else changed_fields[it->first] = it->second; } // Send delete fields broadcast if(!deleted_fields.empty()) { bool multi = (deleted_fields.size() > 1); DatagramPtr update = Datagram::create(); update->add_server_header(database_to_object(m_doid), m_sender, multi ? DBSERVER_OBJECT_DELETE_FIELDS : DBSERVER_OBJECT_DELETE_FIELD); update->add_doid(m_doid); if(multi) { update->add_uint16(deleted_fields.size()); } for(auto it = deleted_fields.begin(); it != deleted_fields.end(); ++it) { update->add_uint16((*it)->get_id()); } m_dbserver->route_datagram(update); } // Send update fields broadcast if(!changed_fields.empty()) { bool multi = (changed_fields.size() > 1); DatagramPtr update = Datagram::create(); update->add_server_header(database_to_object(m_doid), m_sender, multi ? DBSERVER_OBJECT_SET_FIELDS : DBSERVER_OBJECT_SET_FIELD); update->add_doid(m_doid); if(multi) { update->add_uint16(changed_fields.size()); } for(auto it = changed_fields.begin(); it != changed_fields.end(); ++it) { update->add_uint16(it->first->get_id()); update->add_data(it->second); } m_dbserver->route_datagram(update); } }
void DBOperationGet::on_complete(DBObjectSnapshot *snapshot) { DatagramPtr resp = Datagram::create(); resp->add_server_header(m_sender, m_dbserver->m_control_channel, m_resp_msgtype); resp->add_uint32(m_context); resp->add_uint8(SUCCESS); // Calculate the fields that we are sending in our response: FieldValues response_fields; if(m_resp_msgtype == DBSERVER_OBJECT_GET_ALL_RESP) { // Send everything: response_fields = snapshot->m_fields; } else { // Send only what was requested: for(auto it = m_get_fields.begin(); it != m_get_fields.end(); ++it) { auto it2 = snapshot->m_fields.find(*it); if(it2 != snapshot->m_fields.end()) { response_fields[it2->first] = it2->second; } } } // WHAT we send depends on our m_resp_msgtype, so: if(m_resp_msgtype == DBSERVER_OBJECT_GET_FIELD_RESP) { if(response_fields.empty()) { // We did not find the field we were looking for. // Therefore, this is a failure. on_failure(); return; } resp->add_uint16(response_fields.begin()->first->get_id()); resp->add_data(response_fields.begin()->second); // And that's it. We're done. m_dbserver->route_datagram(resp); delete snapshot; cleanup(); return; } if(m_resp_msgtype == DBSERVER_OBJECT_GET_ALL_RESP) { resp->add_uint16(snapshot->m_dclass->get_id()); } resp->add_uint16(response_fields.size()); for(auto it = response_fields.begin(); it != response_fields.end(); ++it) { resp->add_uint16(it->first->get_id()); resp->add_data(it->second); } m_dbserver->route_datagram(resp); delete snapshot; cleanup(); }
void DBOperationUpdate::on_failure() { DatagramPtr resp = Datagram::create(); resp->add_server_header(m_sender, m_dbserver->m_control_channel, m_resp_msgtype); resp->add_uint32(m_context); resp->add_uint8(FAILURE); m_dbserver->route_datagram(resp); cleanup(); }
void DBOperationDelete::on_complete() { // Broadcast update to object's channel if(m_dbserver->m_broadcast) { DatagramPtr update = Datagram::create(); update->add_server_header(database_to_object(m_doid), m_sender, DBSERVER_OBJECT_DELETE); update->add_doid(m_doid); m_dbserver->route_datagram(update); } cleanup(); }
void DBOperationCreate::on_complete(doid_t doid) { DatagramPtr resp = Datagram::create(); resp->add_server_header(m_sender, m_dbserver->m_control_channel, DBSERVER_CREATE_OBJECT_RESP); resp->add_uint32(m_context); resp->add_doid(doid); m_dbserver->route_datagram(resp); cleanup(); }
void DBOperationUpdate::on_complete() { // Broadcast update to object's channel if(m_dbserver->m_broadcast) { announce_fields(m_set_fields); } // Send update response DatagramPtr resp = Datagram::create(); resp->add_server_header(m_sender, m_dbserver->m_control_channel, m_resp_msgtype); resp->add_uint32(m_context); resp->add_uint8(SUCCESS); m_dbserver->route_datagram(resp); cleanup(); }
// add_interest will start a new interest operation and retrieve all the objects an interest // from the server, subscribing to each zone in the interest. If the interest already // exists, the interest will be updated with the new zones passed in by the argument. void Client::add_interest(Interest &i, uint32_t context, channel_t caller) { unordered_set<zone_t> new_zones; for(const auto& it : i.zones) { 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]; unordered_set<zone_t> killed_zones; for(const auto& it : previous_interest.zones) { 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: notify_interest_done(i.id, caller); handle_interest_done(i.id, context); return; } uint32_t request_context = m_next_context++; InterestOperation *iop = new InterestOperation(this, m_client_agent->m_interest_timeout, i.id, context, request_context, i.parent, new_zones, caller); m_pending_interests.emplace(request_context, iop); DatagramPtr resp = Datagram::create(); resp->add_server_header(i.parent, m_channel, STATESERVER_OBJECT_GET_ZONES_OBJECTS); resp->add_uint32(request_context); resp->add_doid(i.parent); resp->add_uint16(new_zones.size()); for(const auto& it : new_zones) { resp->add_zone(it); subscribe_channel(location_as_channel(i.parent, it)); } route_datagram(resp); }