Ejemplo n.º 1
0
    void handle_get(DBClientBase *client, DBOperation *operation)
    {
        BSONObj obj;
        try {
            obj = client->findOne(m_obj_collection,
                                 BSON("_id" << operation->doid()));
        } catch(mongo::DBException &e) {
            m_log->error() << "Unexpected error occurred while trying to"
                           " retrieve object with DOID "
                           << operation->doid() << ": " << e.what() << endl;
            operation->on_failure();
            return;
        }

        if(obj.isEmpty()) {
            m_log->warning() << "Got queried for non-existent object with DOID "
                             << operation->doid() << endl;
            operation->on_failure();
            return;
        }

        DBObjectSnapshot *snap = format_snapshot(operation->doid(), obj);
        if(!snap || !operation->verify_class(snap->m_dclass)) {
            operation->on_failure();
        } else {
            operation->on_complete(snap);
        }
    }
Ejemplo n.º 2
0
		void set_field(doid_t do_id, const Field* field, const val_t &value)
		{
			m_log->trace() << "Setting field on obj-" << do_id << endl;

			YAML::Node document;
			if(!load(do_id, document))
			{
				return;
			}

			// Get the fields from the file that are not being updated
			const Class* dcc = g_dcf->get_class_by_name(document["class"].as<string>());
			ObjectData dbo(dcc->get_id());
			YAML::Node existing = document["fields"];
			for(auto it = existing.begin(); it != existing.end(); ++it)
			{
				const Field* field = dcc->get_field_by_name(it->first.as<string>());
				if(!field)
				{
					m_log->warning() << "Field '" << it->first.as<string>()
					                 << "', loaded from '" << filename(do_id)
					                 << "', does not exist." << endl;
					continue;
				}
				vector<uint8_t> value = read_yaml_field(field, it->second, do_id);
				if(value.size() > 0)
				{
					dbo.fields[field] = value;
				}
			}

			dbo.fields[field] = value;
			write_yaml_object(do_id, dcc, dbo);
		}
Ejemplo n.º 3
0
		bool set_field_if_equals(doid_t do_id, const Field* field, const val_t &equal, val_t &value)
		{
			m_log->trace() << "Setting field if equal on obj-" << do_id << endl;

			YAML::Node document;
			if(!load(do_id, document))
			{
				value = vector<uint8_t>();
				return false;
			}

			// Get current field values from the file
			const Class* dcc = g_dcf->get_class_by_name(document["class"].as<string>());
			ObjectData dbo(dcc->get_id());
			YAML::Node existing = document["fields"];
			for(auto it = existing.begin(); it != existing.end(); ++it)
			{
				const Field* field = dcc->get_field_by_name(it->first.as<string>());
				if(!field)
				{
					m_log->warning() << "Field '" << it->first.as<string>()
					                 << "', loaded from '" << filename(do_id)
					                 << "', does not exist." << endl;
					continue;
				}
				vector<uint8_t> value = read_yaml_field(field, it->second, do_id);
				if(value.size() > 0)
				{
					dbo.fields[field] = value;
				}
			}

			auto found = dbo.fields.find(field);
			if(found == dbo.fields.end() || found->second != equal)
			{
				value = dbo.fields[field];
				return false;
			}

			dbo.fields[field] = value;
			write_yaml_object(do_id, dcc, dbo);
			return true;
		}
Ejemplo n.º 4
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;
        }
    }
Ejemplo n.º 5
0
		bool get_object(doid_t do_id, ObjectData &dbo)
		{
			m_log->trace() << "Getting obj-" << do_id << " ..." << endl;

			// Open file for object
			YAML::Node document;
			if(!load(do_id, document))
			{
				return false;
			}

			// Read object's DistributedClass
			const Class* dcc = g_dcf->get_class_by_name(document["class"].as<string>());
			dbo.dc_id = dcc->get_id();

			// Read object's fields
			YAML::Node fields = document["fields"];
			for(auto it = fields.begin(); it != fields.end(); ++it)
			{
				const Field* field = dcc->get_field_by_name(it->first.as<string>());
				if(!field)
				{
					m_log->warning() << "Field '" << it->first.as<string>()
					                 << "', loaded from '" << filename(do_id)
					                 << "', does not exist." << endl;
					continue;
				}

				vector<uint8_t> value = read_yaml_field(field, it->second, do_id);
				if(value.size() > 0)
				{
					dbo.fields[field] = value;
				}
			}

			return true;
		}
Ejemplo n.º 6
0
		virtual void handle_datagram(Datagram &in_dg, DatagramIterator &dgi)
		{
			channel_t sender = dgi.read_uint64();
			unsigned short msg_type = dgi.read_uint16();
			switch(msg_type)
			{
				case DBSERVER_CREATE_STORED_OBJECT:
				{
					unsigned int context = dgi.read_uint32();

					// Start response with generic header
					Datagram resp;
					resp.add_server_header(sender, m_control_channel, DBSERVER_CREATE_STORED_OBJECT_RESP);
					resp.add_uint32(context);

					// Get DistributedClass
					unsigned short dc_id = dgi.read_uint16();
					DCClass *dcc = gDCF->get_class(dc_id);
					if(!dcc)
					{
						m_log->error() << "Invalid DCClass when creating object: #" << dc_id << std::endl;
						resp.add_uint32(0);
						send(resp);
						return;
					}

					// Unpack fields to be passed to database
					DatabaseObject dbo(dc_id);
					unsigned short field_count = dgi.read_uint16();
					m_log->spam() << "Unpacking fields..." << std::endl;
					try
					{
						for(unsigned int i = 0; i < field_count; ++i)
						{
							unsigned short field_id = dgi.read_uint16();
							DCField *field = dcc->get_field_by_index(field_id);
							if(field)
							{
								if(field->is_db())
								{
									dgi.unpack_field(field, dbo.fields[field]);
								}
								else
								{
									std::string tmp;
									dgi.unpack_field(field, tmp);
								}
							}
						}
					}
					catch(std::exception &e)
					{
						m_log->error() << "Error while unpacking fields, msg may be truncated. e.what(): "
							<< e.what() << std::endl;

						resp.add_uint32(0);
						send(resp);
						return;
					}

					// Check for required fields, and populate with defaults
					m_log->spam() << "Checking all required fields exist..." << std::endl;
					for(int i = 0; i < dcc->get_num_inherited_fields(); ++i)
					{
						DCField *field = dcc->get_inherited_field(i);
						if(field->is_required() && field->is_db() && !field->as_molecular_field())
						{
							if(dbo.fields.find(field) == dbo.fields.end())
							{
								if(!field->has_default_value())
								{
									m_log->error() << "Field " << field->get_name() << " missing when trying to create "
										"object of type " << dcc->get_name();

									resp.add_uint32(0);
									send(resp);
									return;
								}
								else
								{
									dbo.fields[field] = field->get_default_value();
								}
							}
						}
					}

					// Create object in database
					m_log->spam() << "Creating stored object..." << std::endl;
					unsigned int do_id = m_db_engine->create_object(dbo);
					if(do_id == 0 || do_id < m_min_id || do_id > m_max_id)
					{
						m_log->error() << "Ran out of DistributedObject ids while creating new object." << std::endl;
						resp.add_uint32(0);
						send(resp);
						return;
					}

					m_log->spam() << "... created with ID: " << do_id << std::endl;
					resp.add_uint32(do_id);
					send(resp);
				}
				break;
				case DBSERVER_SELECT_STORED_OBJECT_ALL:
				{
					unsigned int context = dgi.read_uint32();

					Datagram resp;
					resp.add_server_header(sender, m_control_channel, DBSERVER_SELECT_STORED_OBJECT_ALL_RESP);
					resp.add_uint32(context);

					unsigned int do_id = dgi.read_uint32();

					DatabaseObject dbo;
					if(m_db_engine->get_object(do_id, dbo))
					{
						resp.add_uint8(1);
						resp.add_uint16(dbo.dc_id);
						resp.add_uint16(dbo.fields.size());
						for(auto it = dbo.fields.begin(); it != dbo.fields.end(); ++it)
						{
							resp.add_uint16(it->first->get_number());
							resp.add_data(it->second);
						}
					}
					else
					{
						resp.add_uint8(0);
					}
					send(resp);
				}
				break;
				case DBSERVER_DELETE_STORED_OBJECT:
				{
					if(dgi.read_uint32() == DBSERVER_DELETE_STORED_OBJECT_VERIFY_CODE)
					{
						unsigned int do_id = dgi.read_uint32();
						m_db_engine->delete_object(do_id);
						m_log->debug() << "Deleted object with ID: " << do_id << std::endl;
					}
					else
					{
						m_log->warning() << "Wrong delete verify code." << std::endl;
					}
				}
				break;
				default:
					m_log->error() << "Recieved unknown MsgType: " << msg_type << std::endl;
			};
		}
Ejemplo n.º 7
0
		bool set_fields_if_equals(doid_t do_id, const map_t &equals, map_t &values)
		{
			m_log->trace() << "Setting fields if equals on obj-" << do_id << endl;

			YAML::Node document;
			if(!load(do_id, document))
			{
				values.clear();
				return false;
			}

			// Get current field values from the file
			const Class* dcc = g_dcf->get_class_by_name(document["class"].as<string>());
			ObjectData dbo(dcc->get_id());
			YAML::Node existing = document["fields"];
			for(auto it = existing.begin(); it != existing.end(); ++it)
			{
				const Field* field = dcc->get_field_by_name(it->first.as<string>());
				if(!field)
				{
					m_log->warning() << "Field '" << it->first.as<string>()
					                 << "', loaded from '" << filename(do_id)
					                 << "', does not exist." << endl;
					continue;
				}
				vector<uint8_t> value = read_yaml_field(field, it->second, do_id);
				if(value.size() > 0)
				{
					dbo.fields[field] = value;
				}
			}

			// Check if equals matches current values
			bool fail = false;
			for(auto it = equals.begin(); it != equals.end(); ++it)
			{
				auto found = dbo.fields.find(it->first);
				if(found == dbo.fields.end())
				{
					values.erase(it->first);
					fail = true;
				}
				else if(it->second != found->second)
				{
					values.erase(it->first);
					fail = true;
				}
			}

			// Return current values on failure
			if(fail)
			{
				for(auto it = values.begin(); it != values.end(); ++it)
				{
					it->second = dbo.fields[it->first];
				}
				return false;
			}

			// Update existing values on success
			for(auto it = values.begin(); it != values.end(); ++it)
			{
				dbo.fields[it->first] = it->second;
			}
			write_yaml_object(do_id, dcc, dbo);
			return true;
		}