Exemple #1
0
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();
}
Exemple #2
0
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);
    }
}
Exemple #3
0
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();
}
Exemple #4
0
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();
}
Exemple #5
0
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();
}
Exemple #6
0
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();
}
Exemple #7
0
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();
}
Exemple #8
0
// 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);
}