// 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; } }
static void bson2bamboo(const dclass::DistributedType *type, const BSONElement &element, Datagram &dg) { switch(type->get_type()) { case dclass::Type::T_INT8: { dg.add_int8(element.Int()); } break; case dclass::Type::T_INT16: { dg.add_int16(element.Int()); } break; case dclass::Type::T_INT32: { dg.add_int32(element.Int()); } break; case dclass::Type::T_INT64: { dg.add_int64(element.Int()); } break; case dclass::Type::T_UINT8: { dg.add_uint8(element.Int()); } break; case dclass::Type::T_UINT16: { dg.add_uint16(element.Int()); } break; case dclass::Type::T_UINT32: { dg.add_uint32(element.Int()); } break; case dclass::Type::T_UINT64: { dg.add_uint64(element.Int()); } break; case dclass::Type::T_CHAR: { string str = element.String(); if(str.size() != 1) { throw mongo::DBException("Expected single-length string for char field", 0); } dg.add_uint8(str[0]); } break; case dclass::Type::T_FLOAT32: { dg.add_float32(element.Number()); } break; case dclass::Type::T_FLOAT64: { dg.add_float64(element.Number()); } break; case dclass::Type::T_STRING: { dg.add_data(element.String()); } break; case dclass::Type::T_VARSTRING: { dg.add_string(element.String()); } break; case dclass::Type::T_BLOB: { int len; const uint8_t *rawdata = (const uint8_t *)element.binData(len); dg.add_data(rawdata, len); } break; case dclass::Type::T_VARBLOB: { int len; const uint8_t *rawdata = (const uint8_t *)element.binData(len); dg.add_blob(rawdata, len); } break; case dclass::Type::T_ARRAY: { const dclass::ArrayType *array = type->as_array(); std::vector<BSONElement> data = element.Array(); for(auto it = data.begin(); it != data.end(); ++it) { bson2bamboo(array->get_element_type(), *it, dg); } } break; case dclass::Type::T_VARARRAY: { const dclass::ArrayType *array = type->as_array(); std::vector<BSONElement> data = element.Array(); DatagramPtr newdg = Datagram::create(); for(auto it = data.begin(); it != data.end(); ++it) { bson2bamboo(array->get_element_type(), *it, *newdg); } dg.add_blob(newdg->get_data(), newdg->size()); } break; case dclass::Type::T_STRUCT: { const dclass::Struct *s = type->as_struct(); size_t fields = s->get_num_fields(); for(unsigned int i = 0; i < fields; ++i) { const dclass::Field *field = s->get_field(i); bson2bamboo(field->get_type(), element[field->get_name()], dg); } } break; case dclass::Type::T_METHOD: { const dclass::Method *m = type->as_method(); size_t parameters = m->get_num_parameters(); for(unsigned int i = 0; i < parameters; ++i) { const dclass::Parameter *parameter = m->get_parameter(i); string name = parameter->get_name(); if(name.empty() || element[name].eoo()) { stringstream n; n << "_" << i; name = n.str(); } bson2bamboo(parameter->get_type(), element[name], dg); } } break; case dclass::Type::T_INVALID: default: assert(false); break; } }