Exemplo n.º 1
0
void DistributedObject::handle_ai_change(channel_t new_ai, channel_t sender,
        bool channel_is_explicit)
{
    channel_t old_ai = m_ai_channel;
    if(new_ai == old_ai) {
        return;
    }

    // Set of channels that must be notified about ai_change
    unordered_set<channel_t> targets;

    if(old_ai) {
        targets.insert(old_ai);
    }
    if(!m_zone_objects.empty()) {
        // We have at least one child, so we want to notify the children as well
        targets.insert(parent_to_children(m_do_id));
    }

    m_ai_channel = new_ai;
    m_ai_explicitly_set = channel_is_explicit;

    DatagramPtr dg = Datagram::create(targets, sender, STATESERVER_OBJECT_CHANGING_AI);
    dg->add_doid(m_do_id);
    dg->add_channel(new_ai);
    dg->add_channel(old_ai);
    route_datagram(dg);

    if(new_ai) {
        m_log->trace() << "Sending AI entry to " << new_ai << ".\n";
        send_ai_entry(new_ai);
    }

}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
void DistributedObject::wake_children()
{
    DatagramPtr dg = Datagram::create(parent_to_children(m_do_id), m_do_id,
                                      STATESERVER_OBJECT_GET_LOCATION);
    dg->add_uint32(STATESERVER_CONTEXT_WAKE_CHILDREN);
    route_datagram(dg);
}
Exemplo n.º 4
0
void DBStateServer::handle_get_all(channel_t sender, DatagramIterator &dgi)
{
    uint32_t r_context = dgi.read_uint32();
    doid_t r_do_id = dgi.read_doid();
    if(is_activated_object(r_do_id)) {
        return;
    }

    m_log->trace() << "Received GetAll for inactive object with id " << r_do_id << std::endl;

    // Get context for db query, and remember caller with it
    uint32_t db_context = m_next_context++;

    DatagramPtr resp_dg = Datagram::create(sender, r_do_id, STATESERVER_OBJECT_GET_ALL_RESP);
    resp_dg->add_uint32(r_context);
    resp_dg->add_doid(r_do_id);
    resp_dg->add_channel(INVALID_CHANNEL); // Location
    m_context_datagrams[db_context] = resp_dg;

    // Cache the do_id --> context in case we get a dbss_activate
    m_inactive_loads[r_do_id].insert(db_context);

    // Send query to database
    DatagramPtr dg = Datagram::create(m_db_channel, r_do_id, DBSERVER_OBJECT_GET_ALL);
    dg->add_uint32(db_context);
    dg->add_doid(r_do_id);
    route_datagram(dg);
}
Exemplo n.º 5
0
void Client::annihilate()
{
    lock_guard<recursive_mutex> lock(m_client_lock);
    if(is_terminated()) {
        return;
    }

    // Unsubscribe from all channels first so the DELETE messages aren't sent back to us.
    unsubscribe_all();
    m_client_agent->m_ct.free_channel(m_allocated_channel);

    // Delete all session objects
    while(m_session_objects.size() > 0) {
        doid_t do_id = *m_session_objects.begin();
        m_session_objects.erase(do_id);
        m_log->debug() << "Client exited, deleting session object with id " << do_id << ".\n";
        DatagramPtr dg = Datagram::create(do_id, m_channel, STATESERVER_OBJECT_DELETE_RAM);
        dg->add_doid(do_id);
        route_datagram(dg);
    }

    // Note that finish() normally results in the InterestOperation deleting
    // itself from m_pending_interests, so we have to be VERY careful with this
    // for loop. Using (it++) ensures that 'it' is advanced BEFORE finish() is
    // called; doing so after means the iterator is invalid!
    for(auto it = m_pending_interests.begin(); it != m_pending_interests.end();) {
        (it++)->second->finish();
    }

    // Tell the MD this client is gone
    terminate();
}
Exemplo n.º 6
0
void LoadingObject::send_get_object(doid_t do_id)
{
	DatagramPtr dg = Datagram::create(m_dbss->m_db_channel, do_id, DBSERVER_OBJECT_GET_ALL);
	dg->add_uint32(m_context); // Context
	dg->add_doid(do_id);
	route_datagram(dg);
}
Exemplo n.º 7
0
void MessageDirector::recall_post_removes(channel_t sender)
{
    // Clear post removes upstream
    if(m_upstream != nullptr) {
        DatagramPtr dg = Datagram::create(CONTROL_CLEAR_POST_REMOVES);
        dg->add_channel(sender);
        m_upstream->handle_datagram(dg);
    }
}
Exemplo n.º 8
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();
}
Exemplo n.º 9
0
void DistributedObject::delete_children(channel_t sender)
{
    if(!m_zone_objects.empty()) {
        // We have at least one child, so we want to notify the children as well
        DatagramPtr dg = Datagram::create(parent_to_children(m_do_id), sender,
                                          STATESERVER_OBJECT_DELETE_CHILDREN);
        dg->add_doid(m_do_id);
        route_datagram(dg);
    }
}
Exemplo n.º 10
0
void MessageDirector::preroute_post_remove(channel_t sender, DatagramHandle post_remove)
{
    // Add post remove upstream
    if(m_upstream != nullptr) {
        DatagramPtr dg = Datagram::create(CONTROL_ADD_POST_REMOVE);
        dg->add_channel(sender);
        dg->add_blob(post_remove);
        m_upstream->handle_datagram(dg);
    }
}
Exemplo n.º 11
0
bool DistributedObject::handle_one_update(DatagramIterator &dgi, channel_t sender)
{
    vector<uint8_t> data;
    uint16_t field_id = dgi.read_uint16();
    const Field *field = m_dclass->get_field_by_id(field_id);
    if(!field) {
        m_log->error() << "Received set_field for field: " << field_id
                       << ", not valid for class: " << m_dclass->get_name() << ".\n";
        return false;
    }

    m_log->trace() << "Handling update for '" << field->get_name() << "'.\n";

    dgsize_t field_start = dgi.tell();

    try {
        dgi.unpack_field(field, data);
    } catch(const DatagramIteratorEOF&) {
        m_log->error() << "Received truncated update for " << field->get_name() << ".\n";
        return false;
    }

    const MolecularField *molecular = field->as_molecular();
    if(molecular) {
        dgi.seek(field_start);
        int n = molecular->get_num_fields();
        for(int i = 0; i < n; ++i) {
            vector<uint8_t> field_data;
            const Field *atomic = molecular->get_field(i);
            dgi.unpack_field(atomic, field_data);
            save_field(atomic, field_data);
        }
    } else {
        save_field(field, data);
    }

    unordered_set<channel_t> targets;
    if(field->has_keyword("broadcast")) {
        targets.insert(location_as_channel(m_parent_id, m_zone_id));
    }
    if(field->has_keyword("airecv") && m_ai_channel && m_ai_channel != sender) {
        targets.insert(m_ai_channel);
    }
    if(field->has_keyword("ownrecv") && m_owner_channel && m_owner_channel != sender) {
        targets.insert(m_owner_channel);
    }
    if(targets.size()) { // TODO: Review this for efficiency?
        DatagramPtr dg = Datagram::create(targets, sender, STATESERVER_OBJECT_SET_FIELD);
        dg->add_doid(m_do_id);
        dg->add_uint16(field_id);
        dg->add_data(data);
        route_datagram(dg);
    }
    return true;
}
Exemplo n.º 12
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();
}
Exemplo n.º 13
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();
}
Exemplo n.º 14
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();
}
Exemplo n.º 15
0
// notify_interest_done send a CLIENTAGENT_DONE_INTEREST_RESP to the
// interest operation's caller, if one has been set.
void Client::notify_interest_done(uint16_t interest_id, channel_t caller)
{
    if(caller == 0) {
        return;
    }

    DatagramPtr resp = Datagram::create(caller, m_channel, CLIENTAGENT_DONE_INTEREST_RESP);
    resp->add_channel(m_channel);
    resp->add_uint16(interest_id);
    route_datagram(resp);
}
Exemplo n.º 16
0
// notify_interest_done send a CLIENTAGENT_DONE_INTEREST_RESP to the
// interest operation's caller, if one has been set.
void Client::notify_interest_done(const InterestOperation* iop)
{
    if(iop->m_callers.size() == 0) {
        return;
    }

    DatagramPtr resp = Datagram::create(iop->m_callers, m_channel, CLIENTAGENT_DONE_INTEREST_RESP);
    resp->add_channel(m_channel);
    resp->add_uint16(iop->m_interest_id);
    route_datagram(resp);
}
Exemplo n.º 17
0
void DistributedObject::send_interest_entry(channel_t location, uint32_t context)
{
    DatagramPtr dg = Datagram::create(location, m_do_id, m_ram_fields.size() ?
                                      STATESERVER_OBJECT_ENTER_INTEREST_WITH_REQUIRED_OTHER :
                                      STATESERVER_OBJECT_ENTER_INTEREST_WITH_REQUIRED);
    dg->add_uint32(context);
    append_required_data(dg, true);
    if(m_ram_fields.size()) {
        append_other_data(dg, true);
    }
    route_datagram(dg);
}
Exemplo n.º 18
0
    void handle_create(DBClientBase *client, DBOperation *operation)
    {
        // First, let's convert the requested object into BSON; this way, if
        // a failure happens, it happens before we waste a doid.
        BSONObjBuilder fields;

        try {
            for(auto it = operation->set_fields().begin();
                it != operation->set_fields().end();
                ++it) {
                DatagramPtr dg = Datagram::create();
                dg->add_data(it->second);
                DatagramIterator dgi(dg);
                fields << it->first->get_name()
                       << bamboo2bson(it->first->get_type(), dgi)["_"];
            }
        } catch(mongo::DBException &e) {
            m_log->error() << "While formatting "
                           << operation->dclass()->get_name()
                           << " for insertion: " << e.what() << endl;
            operation->on_failure();
            return;
        }

        doid_t doid = assign_doid(client);
        if(doid == INVALID_DO_ID) {
            // The error will already have been emitted at this point, so
            // all that's left for us to do is fail silently:
            operation->on_failure();
            return;
        }

        BSONObj b = BSON("_id" << doid <<
                         "dclass" << operation->dclass()->get_name() <<
                         "fields" << fields.obj());

        m_log->trace() << "Inserting new " << operation->dclass()->get_name()
                       << "(" << doid << "): " << b << endl;

        try {
            client->insert(m_obj_collection, b);
        } catch(mongo::DBException &e) {
            m_log->error() << "Cannot insert new "
                           << operation->dclass()->get_name()
                           << "(" << doid << "): " << e.what() << endl;
            operation->on_failure();
            return;
        }

        operation->on_complete(doid);
    }
Exemplo n.º 19
0
void DBStateServer::handle_get_activated(channel_t sender, DatagramIterator& dgi)
{
    uint32_t r_context = dgi.read_uint32();
    doid_t r_do_id = dgi.read_doid();
    if(m_loading.find(r_do_id) != m_loading.end()) {
        return;
    }

    m_log->trace() << "Received GetActivated for id " << r_do_id << "\n";

    if(m_objs.find(r_do_id) != m_objs.end()) {
        // If object is active return true
        DatagramPtr dg = Datagram::create(sender, r_do_id, DBSS_OBJECT_GET_ACTIVATED_RESP);
        dg->add_uint32(r_context);
        dg->add_doid(r_do_id);
        dg->add_bool(true);
        route_datagram(dg);
    } else {
        // If object isn't active or loading, we can return false
        DatagramPtr dg = Datagram::create(sender, r_do_id, DBSS_OBJECT_GET_ACTIVATED_RESP);
        dg->add_uint32(r_context);
        dg->add_doid(r_do_id);
        dg->add_bool(false);
        route_datagram(dg);
    }
}
Exemplo n.º 20
0
void DistributedObject::append_required_data(DatagramPtr dg, bool client_only, bool also_owner)
{
    dg->add_doid(m_do_id);
    dg->add_location(m_parent_id, m_zone_id);
    dg->add_uint16(m_dclass->get_id());
    size_t field_count = m_dclass->get_num_fields();
    for(size_t i = 0; i < field_count; ++i) {
        const Field *field = m_dclass->get_field(i);
        if(field->has_keyword("required") && !field->as_molecular() && (!client_only
                || field->has_keyword("broadcast") || field->has_keyword("clrecv")
                || (also_owner && field->has_keyword("ownrecv")))) {
            dg->add_data(m_required_fields[field]);
        }
    }
}
Exemplo n.º 21
0
void StateServer::handle_delete_ai(DatagramIterator& dgi, channel_t sender)
{
    channel_t ai_channel = dgi.read_channel();
    std::set <channel_t> targets;
    for(auto it = m_objs.begin(); it != m_objs.end(); ++it) {
        if(it->second && it->second->m_ai_channel == ai_channel && it->second->m_ai_explicitly_set) {
            targets.insert(it->second->m_do_id);
        }
    }

    if(targets.size()) {
        DatagramPtr dg = Datagram::create(targets, sender, STATESERVER_DELETE_AI_OBJECTS);
        dg->add_channel(ai_channel);
        route_datagram(dg);
    }
}
Exemplo n.º 22
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();
}
Exemplo n.º 23
0
Client::~Client()
{
    unsubscribe_all();
    m_client_agent->m_ct.free_channel(m_allocated_channel);

    // Delete all session objects
    while(m_session_objects.size() > 0) {
        doid_t do_id = *m_session_objects.begin();
        m_session_objects.erase(do_id);
        m_log->debug() << "Client exited, deleting session object with id " << do_id << ".\n";
        DatagramPtr dg = Datagram::create(do_id, m_channel, STATESERVER_OBJECT_DELETE_RAM);
        dg->add_doid(do_id);
        route_datagram(dg);
    }

    delete m_log;
}
Exemplo n.º 24
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();
}
Exemplo n.º 25
0
    // Get a DBObjectSnapshot from a MongoDB BSON object; returns NULL if failure.
    DBObjectSnapshot *format_snapshot(doid_t doid, const BSONObj &obj)
    {
        m_log->trace() << "Formatting database snapshot of " << doid << ": "
                       << obj << endl;
        try {
            string dclass_name = obj["dclass"].String();
            const dclass::Class *dclass = g_dcf->get_class_by_name(dclass_name);
            if(!dclass) {
                m_log->error() << "Encountered unknown database object: "
                               << dclass_name << "(" << doid << ")" << endl;
                return NULL;
            }

            BSONObj fields = obj["fields"].Obj();

            DBObjectSnapshot *snap = new DBObjectSnapshot();
            snap->m_dclass = dclass;
            for(auto it = fields.begin(); it.more(); ++it) {
                const char *name = (*it).fieldName();
                const dclass::Field *field = dclass->get_field_by_name(name);
                if(!field) {
                    m_log->warning() << "Encountered unexpected field " << name
                                     << " while formatting " << dclass_name
                                     << "(" << doid << "); ignored." << endl;
                    continue;
                }
                {
                    DatagramPtr dg = Datagram::create();
                    bson2bamboo(field->get_type(), *it, *dg);
                    snap->m_fields[field].resize(dg->size());
                    memcpy(snap->m_fields[field].data(), dg->get_data(), dg->size());
                }
            }

            return snap;
        } catch(mongo::DBException &e) {
            m_log->error() << "Unexpected error while trying to format"
                           " database snapshot for " << doid << ": "
                           << e.what() << endl;
            return NULL;
        }
    }
Exemplo n.º 26
0
void DBStateServer::handle_delete_disk(channel_t sender, DatagramIterator& dgi)
{
    doid_t do_id = dgi.read_doid();
    if(m_loading.find(do_id) != m_loading.end()) {
        // Ignore this message for now, it'll be bounced back to us
        // from the loading object if it succeeds or fails at loading.
        return;
    }

    // If object exists broadcast the delete message
    auto obj_keyval = m_objs.find(do_id);
    if(obj_keyval != m_objs.end()) {
        DistributedObject* obj = obj_keyval->second;
        std::unordered_set<channel_t> targets;

        // Add location to broadcast
        if(obj->get_location()) {
            targets.insert(obj->get_location());
        }

        // Add AI to broadcast
        if(obj->get_ai()) {
            targets.insert(obj->get_ai());
        }

        // Add owner to broadcast
        if(obj->get_owner()) {
            targets.insert(obj->get_owner());
        }

        // Build and send datagram
        DatagramPtr dg = Datagram::create(targets, sender, DBSS_OBJECT_DELETE_DISK);
        dg->add_doid(do_id);
        route_datagram(dg);
    }

    // Send delete to database
    DatagramPtr dg = Datagram::create(m_db_channel, do_id, DBSERVER_OBJECT_DELETE);
    dg->add_doid(do_id);
    route_datagram(dg);

}
Exemplo n.º 27
0
void DistributedObject::annihilate(channel_t sender, bool notify_parent)
{
    unordered_set<channel_t> targets;
    if(m_parent_id) {
        targets.insert(location_as_channel(m_parent_id, m_zone_id));
        // Leave parent on explicit delete ram
        if(notify_parent) {
            DatagramPtr dg = Datagram::create(m_parent_id, sender, STATESERVER_OBJECT_CHANGING_LOCATION);
            dg->add_doid(m_do_id);
            dg->add_location(INVALID_DO_ID, 0);
            dg->add_location(m_parent_id, m_zone_id);
            route_datagram(dg);
        }
    }
    if(m_owner_channel) {
        targets.insert(m_owner_channel);
    }
    if(m_ai_channel) {
        targets.insert(m_ai_channel);
    }
    DatagramPtr dg = Datagram::create(targets, sender, STATESERVER_OBJECT_DELETE_RAM);
    dg->add_doid(m_do_id);
    route_datagram(dg);

    delete_children(sender);

    m_stateserver->m_objs.erase(m_do_id);
    m_log->debug() << "Deleted.\n";

    terminate();
}
Exemplo n.º 28
0
void DBStateServer::handle_set_fields(DatagramIterator &dgi)
{
    doid_t do_id = dgi.read_doid();
    if(m_loading.find(do_id) != m_loading.end()) {
        // Ignore this message for now, it'll be bounced back to us
        // from the loading object if it succeeds or fails at loading.
        return;
    }

    uint16_t field_count = dgi.read_uint16();

    FieldValues db_fields;
    for(uint16_t i = 0; i < field_count; ++i) {
        uint16_t field_id = dgi.read_uint16();
        const Field* field = g_dcf->get_field_by_id(field_id);
        if(!field) {
            m_log->warning() << "Received invalid field with id " << field_id << " in SetFields.\n";
            return;
        }
        if(field->has_keyword("db")) {
            dgi.unpack_field(field, db_fields[field]);
        } else {
            dgi.skip_field(field);
        }
    }

    if(db_fields.size() > 0) {
        m_log->trace() << "Forwarding SetFields on object with id " << do_id << " to database.\n";

        DatagramPtr dg = Datagram::create(m_db_channel, do_id, DBSERVER_OBJECT_SET_FIELDS);
        dg->add_doid(do_id);
        dg->add_uint16(db_fields.size());
        for(const auto& it : db_fields) {
            dg->add_uint16(it.first->get_id());
            dg->add_data(it.second);
        }
        route_datagram(dg);
    }
}
Exemplo n.º 29
0
bool DistributedObject::handle_one_get(DatagramPtr out, uint16_t field_id,
                                       bool succeed_if_unset, bool is_subfield)
{
    const Field *field = m_dclass->get_field_by_id(field_id);
    if(!field) {
        m_log->error() << "Received get_field for field: " << field_id
                       << ", not valid for class: " << m_dclass->get_name() << ".\n";
        return false;
    }
    m_log->trace() << "Handling query for '" << field->get_name() << "'.\n";

    const MolecularField *molecular = field->as_molecular();
    if(molecular) {
        int n = molecular->get_num_fields();
        out->add_uint16(field_id);
        for(int i = 0; i < n; ++i) {
            if(!handle_one_get(out, molecular->get_field(i)->get_id(), succeed_if_unset, true)) {
                return false;
            }
        }
        return true;
    }

    if(m_required_fields.count(field)) {
        if(!is_subfield) {
            out->add_uint16(field_id);
        }
        out->add_data(m_required_fields[field]);
    } else if(m_ram_fields.count(field)) {
        if(!is_subfield) {
            out->add_uint16(field_id);
        }
        out->add_data(m_ram_fields[field]);
    } else {
        return succeed_if_unset;
    }

    return true;
}
Exemplo n.º 30
0
void DBStateServer::handle_set_field(DatagramIterator &dgi)
{
    doid_t do_id = dgi.read_doid();
    if(m_loading.find(do_id) != m_loading.end()) {
        // Ignore this message for now, it'll be bounced back to us
        // from the loading object if it succeeds or fails at loading.
        return;
    }

    uint16_t field_id = dgi.read_uint16();

    const Field* field = g_dcf->get_field_by_id(field_id);
    if(field && field->has_keyword("db")) {
        m_log->trace() << "Forwarding SetField for field \"" << field->get_name()
                       << "\" on object with id " << do_id << " to database.\n";

        DatagramPtr dg = Datagram::create(m_db_channel, do_id, DBSERVER_OBJECT_SET_FIELD);
        dg->add_doid(do_id);
        dg->add_uint16(field_id);
        dg->add_data(dgi.read_remainder());
        route_datagram(dg);
    }
}