本文整理汇总了C++中DatagramPtr::add_data方法的典型用法代码示例。如果您正苦于以下问题:C++ DatagramPtr::add_data方法的具体用法?C++ DatagramPtr::add_data怎么用?C++ DatagramPtr::add_data使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类DatagramPtr
的用法示例。
在下文中一共展示了DatagramPtr::add_data方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: on_complete
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();
}
示例2: handle_get_fields_resp
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);
}
示例3: on_criteria_mismatch
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();
}
示例4: handle_one_update
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;
}
示例5: handle_one_get
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;
}
示例6: handle_get_field
void DBStateServer::handle_get_field(channel_t sender, DatagramIterator &dgi)
{
uint32_t r_context = dgi.read_uint32();
doid_t r_do_id = dgi.read_doid();
uint16_t field_id = dgi.read_uint16();
if(is_activated_object(r_do_id)) {
return;
}
m_log->trace() << "Received GetField for field with id " << field_id
<< " on inactive object with id " << r_do_id << "\n";
// Check field is "ram db" or "required"
const Field* field = g_dcf->get_field_by_id(field_id);
if(!field || !(field->has_keyword("required") || field->has_keyword("ram"))) {
DatagramPtr dg = Datagram::create(sender, r_do_id, STATESERVER_OBJECT_GET_FIELD_RESP);
dg->add_uint32(r_context);
dg->add_bool(false);
route_datagram(dg);
return;
}
if(field->has_keyword("db")) {
// Get context for db query
uint32_t db_context = m_next_context++;
// Prepare reponse datagram
DatagramPtr dg_resp = Datagram::create(sender, r_do_id, STATESERVER_OBJECT_GET_FIELD_RESP);
dg_resp->add_uint32(r_context);
m_context_datagrams[db_context] = dg_resp;
// Send query to database
DatagramPtr dg = Datagram::create(m_db_channel, r_do_id, DBSERVER_OBJECT_GET_FIELD);
dg->add_uint32(db_context);
dg->add_doid(r_do_id);
dg->add_uint16(field_id);
route_datagram(dg);
} else if(field->has_default_value()) { // Field is required and not-db
DatagramPtr dg = Datagram::create(sender, r_do_id, STATESERVER_OBJECT_GET_FIELD_RESP);
dg->add_uint32(r_context);
dg->add_bool(true);
dg->add_uint16(field_id);
dg->add_data(field->get_default_value());
route_datagram(dg);
} else {
DatagramPtr dg = Datagram::create(sender, r_do_id, STATESERVER_OBJECT_GET_FIELD_RESP);
dg->add_uint32(r_context);
dg->add_bool(false);
route_datagram(dg);
}
}
示例7: handle_create
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);
}
示例8: append_other_data
void DistributedObject::append_other_data(DatagramPtr dg, bool client_only, bool also_owner)
{
if(client_only) {
vector<const Field*> broadcast_fields;
for(auto it = m_ram_fields.begin(); it != m_ram_fields.end(); ++it) {
if(it->first->has_keyword("broadcast") || it->first->has_keyword("clrecv")
|| (also_owner && it->first->has_keyword("ownrecv"))) {
broadcast_fields.push_back(it->first);
}
}
dg->add_uint16(broadcast_fields.size());
for(auto it = broadcast_fields.begin(); it != broadcast_fields.end(); ++it) {
dg->add_uint16((*it)->get_id());
dg->add_data(m_ram_fields[*it]);
}
} else {
dg->add_uint16(m_ram_fields.size());
for(auto it = m_ram_fields.begin(); it != m_ram_fields.end(); ++it) {
dg->add_uint16(it->first->get_id());
dg->add_data(it->second);
}
}
}
示例9: append_required_data
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]);
}
}
}
示例10: announce_fields
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);
}
}
示例11: handle_set_fields
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);
}
}
示例12: handle_set_field
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);
}
}
示例13: handle_datagram
// handle_datagram is the handler for datagrams received from the Astron cluster
void Client::handle_datagram(DatagramHandle in_dg, DatagramIterator &dgi)
{
lock_guard<recursive_mutex> lock(m_client_lock);
if(is_terminated()) {
return;
}
channel_t sender = dgi.read_channel();
if(sender == m_channel) {
return; // ignore messages from ourselves
}
uint16_t msgtype = dgi.read_uint16();
switch(msgtype) {
case CLIENTAGENT_EJECT: {
uint16_t reason = dgi.read_uint16();
string error_string = dgi.read_string();
send_disconnect(reason, error_string);
return;
}
break;
case CLIENTAGENT_DROP: {
handle_drop();
return;
}
break;
case CLIENTAGENT_SET_STATE: {
m_state = (ClientState)dgi.read_uint16();
}
break;
case CLIENTAGENT_ADD_INTEREST: {
uint32_t context = m_next_context++;
Interest i;
build_interest(dgi, false, i);
handle_add_interest(i, context);
add_interest(i, context, sender);
}
break;
case CLIENTAGENT_ADD_INTEREST_MULTIPLE: {
uint32_t context = m_next_context++;
Interest i;
build_interest(dgi, true, i);
handle_add_interest(i, context);
add_interest(i, context, sender);
}
break;
case CLIENTAGENT_REMOVE_INTEREST: {
uint32_t context = m_next_context++;
uint16_t id = dgi.read_uint16();
Interest &i = m_interests[id];
handle_remove_interest(id, context);
remove_interest(i, context, sender);
}
break;
case CLIENTAGENT_SET_CLIENT_ID: {
if(m_channel != m_allocated_channel) {
unsubscribe_channel(m_channel);
}
m_channel = dgi.read_channel();
subscribe_channel(m_channel);
}
break;
case CLIENTAGENT_SEND_DATAGRAM: {
DatagramPtr forward = Datagram::create();
forward->add_data(dgi.read_string());
forward_datagram(forward);
}
break;
case CLIENTAGENT_OPEN_CHANNEL: {
subscribe_channel(dgi.read_channel());
}
break;
case CLIENTAGENT_CLOSE_CHANNEL: {
unsubscribe_channel(dgi.read_channel());
}
break;
case CLIENTAGENT_ADD_POST_REMOVE: {
add_post_remove(m_allocated_channel, dgi.read_datagram());
}
break;
case CLIENTAGENT_CLEAR_POST_REMOVES: {
clear_post_removes(m_allocated_channel);
}
break;
case CLIENTAGENT_DECLARE_OBJECT: {
doid_t do_id = dgi.read_doid();
uint16_t dc_id = dgi.read_uint16();
if(m_declared_objects.find(do_id) != m_declared_objects.end()) {
m_log->warning() << "Received object declaration for previously declared object "
<< do_id << ".\n";
return;
}
DeclaredObject obj;
//.........这里部分代码省略.........
示例14: handle_get_all_resp
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);
}
示例15: handle_modify
void handle_modify(DBClientBase *client, DBOperation *operation)
{
// First, we have to format our findandmodify.
BSONObjBuilder sets;
bool has_sets = false;
BSONObjBuilder unsets;
bool has_unsets = false;
for(auto it = operation->set_fields().begin();
it != operation->set_fields().end(); ++it) {
stringstream fieldname;
fieldname << "fields." << it->first->get_name();
if(it->second.empty()) {
unsets << fieldname.str() << true;
has_unsets = true;
} else {
DatagramPtr dg = Datagram::create();
dg->add_data(it->second);
DatagramIterator dgi(dg);
sets << fieldname.str() << bamboo2bson(it->first->get_type(), dgi)["_"];
has_sets = true;
}
}
BSONObjBuilder updates_b;
if(has_sets) {
updates_b << "$set" << sets.obj();
}
if(has_unsets) {
updates_b << "$unset" << unsets.obj();
}
BSONObj updates = updates_b.obj();
// Also format any criteria for the change:
BSONObjBuilder query_b;
query_b << "_id" << operation->doid();
for(auto it = operation->criteria_fields().begin();
it != operation->criteria_fields().end(); ++it) {
stringstream fieldname;
fieldname << "fields." << it->first->get_name();
if(it->second.empty()) {
query_b << fieldname.str() << BSON("$exists" << false);
} else {
DatagramPtr dg = Datagram::create();
dg->add_data(it->second);
DatagramIterator dgi(dg);
query_b << fieldname.str() << bamboo2bson(it->first->get_type(), dgi)["_"];
}
}
BSONObj query = query_b.obj();
m_log->trace() << "Performing updates to " << operation->doid()
<< ": " << updates << endl;
m_log->trace() << "Query is: " << query << endl;
BSONObj result;
bool success;
try {
success = client->runCommand(
m_db,
BSON("findandmodify" << "astron.objects"
<< "query" << query
<< "update" << updates),
result);
} catch(mongo::DBException &e) {
m_log->error() << "Unexpected error while modifying "
<< operation->doid() << ": " << e.what() << endl;
operation->on_failure();
return;
}
m_log->trace() << "Update result: " << result << endl;
BSONObj obj;
if(!success || result["value"].isNull()) {
// Okay, something didn't work right. If we had criteria, let's
// try to fetch the object without the criteria to see if it's a
// criteria mismatch or a missing DOID.
if(!operation->criteria_fields().empty()) {
try {
obj = client->findOne(m_obj_collection,
BSON("_id" << operation->doid()));
} catch(mongo::DBException &e) {
m_log->error() << "Unexpected error while modifying "
<< operation->doid() << ": " << e.what() << endl;
operation->on_failure();
return;
}
if(!obj.isEmpty()) {
// There's the problem. Now we can send back a snapshot:
DBObjectSnapshot *snap = format_snapshot(operation->doid(), obj);
if(snap && operation->verify_class(snap->m_dclass)) {
operation->on_criteria_mismatch(snap);
return;
} else {
// Something else weird happened with our snapshot;
// either the class wasn't recognized or it was the
// wrong class. Either way, an error has been logged,
// and we need to fail the operation.
operation->on_failure();
return;
//.........这里部分代码省略.........