<commit_before>#include "DatabaseServer.h"

#include "core/global.h"
#include "core/msgtypes.h"
#include "config/constraints.h"
#include "DBBackendFactory.h"
#include "DatabaseBackend.h"

using namespace std;
using dclass::Field;
using dclass::Class;

static RoleFactoryItem<DatabaseServer> dbserver_fact("database");

RoleConfigGroup dbserver_config("database");
static ConfigVariable<channel_t> control_channel("control", INVALID_CHANNEL, dbserver_config);
static ConfigVariable<bool> broadcast_updates("broadcast", true, dbserver_config);
static InvalidChannelConstraint control_not_invalid(control_channel);
static ReservedChannelConstraint control_not_reserved(control_channel);
static BooleanValueConstraint broadcast_is_boolean(broadcast_updates);

static ConfigGroup generate_config("generate", dbserver_config);
static ConfigVariable<doid_t> min_id("min", INVALID_DO_ID, generate_config);
static ConfigVariable<doid_t> max_id("max", UINT_MAX, generate_config);
static InvalidDoidConstraint min_not_invalid(min_id);
static InvalidDoidConstraint max_not_invalid(max_id);
static ReservedDoidConstraint min_not_reserved(min_id);
static ReservedDoidConstraint max_not_reserved(max_id);

class DBOperationImpl : public DBOperation
{
	public:
		DBOperationImpl(DatabaseServer *db) : m_dbserver(db) { }

		virtual bool initialize(channel_t sender, uint16_t msg_type, DatagramIterator &dgi) = 0;

		bool populate_set_fields(DatagramIterator &dgi)
		{
			uint16_t field_count = dgi.read_uint16();
			for(uint16_t i = 0; i < field_count; ++i)
			{
				uint16_t field_id = dgi.read_uint16();
				const Field *field = m_dclass->get_field_by_id(field_id);
				if(!field)
				{
					// TODO: Error!
					return false;
				}
				if(field->has_keyword("db"))
				{
					dgi.unpack_field(field, m_set_fields[field]);
				}
				else
				{
					// TODO: Warning!
					dgi.skip_field(field);
				}
			}

			return true;
		}

		DatabaseServer *m_dbserver;
		channel_t m_sender;
};

class DBOperationImpl_Create : public DBOperationImpl
{
	public:
		DBOperationImpl_Create(DatabaseServer *db) : DBOperationImpl(db) { }

		virtual bool initialize(channel_t sender, uint16_t msg_type, DatagramIterator &dgi)
		{
			m_sender = sender;

			m_type = CREATE_OBJECT;
			m_context = dgi.read_uint32();

			uint16_t dclass_id = dgi.read_uint16();
			m_dclass = g_dcf->get_class_by_id(dclass_id);
			if(!m_dclass)
			{
				// TODO: Error!
				on_failure();
				return false;
			}

			if(!populate_set_fields(dgi))
			{
				on_failure();
				return false;
			}

			return true;
		}

		virtual void 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);

			delete this;
		}

		virtual void on_failure()
		{
			// We just send back an invalid response...
			on_complete(INVALID_DO_ID);
		}

		uint32_t m_context;
};

class DBOperationImpl_Delete : public DBOperationImpl
{
	public:
		DBOperationImpl_Delete(DatabaseServer *db) : DBOperationImpl(db) { }

		virtual bool initialize(channel_t sender, uint16_t msg_type, DatagramIterator &dgi)
		{
			m_sender = sender;

			m_type = DELETE_OBJECT;
			m_doid = dgi.read_uint32();

			return true;
		}

		virtual void on_failure()
		{
			delete this;
		}

		virtual void on_complete()
		{
			delete this;
		}
};

DatabaseServer::DatabaseServer(RoleConfig roleconfig) : Role(roleconfig),
	m_control_channel(control_channel.get_rval(roleconfig)),
	m_min_id(min_id.get_rval(roleconfig)),
	m_max_id(max_id.get_rval(roleconfig)),
	m_broadcast(broadcast_updates.get_rval(roleconfig))
{
	ConfigNode generate = dbserver_config.get_child_node(generate_config, roleconfig);
	ConfigNode backend = dbserver_config.get_child_node(db_backend_config, roleconfig);
	m_db_backend = DBBackendFactory::singleton().instantiate_backend(
		db_backend_type.get_rval(backend), backend,<commit_msg>Database: Fix small typos.<commit_after>#include "DatabaseServer.h"

#include "core/global.h"
#include "core/msgtypes.h"
#include "config/constraints.h"
#include "DBBackendFactory.h"
#include "DatabaseBackend.h"

using namespace std;
using dclass::Field;
using dclass::Class;

static RoleFactoryItem<DatabaseServer> dbserver_fact("database");

RoleConfigGroup dbserver_config("database");
static ConfigVariable<channel_t> control_channel("control", INVALID_CHANNEL, dbserver_config);
static ConfigVariable<bool> broadcast_updates("broadcast", true, dbserver_config);
static InvalidChannelConstraint control_not_invalid(control_channel);
static ReservedChannelConstraint control_not_reserved(control_channel);
static BooleanValueConstraint broadcast_is_boolean(broadcast_updates);

static ConfigGroup generate_config("generate", dbserver_config);
static ConfigVariable<doid_t> min_id("min", INVALID_DO_ID, generate_config);
static ConfigVariable<doid_t> max_id("max", UINT_MAX, generate_config);
static InvalidDoidConstraint min_not_invalid(min_id);
static InvalidDoidConstraint max_not_invalid(max_id);
static ReservedDoidConstraint min_not_reserved(min_id);
static ReservedDoidConstraint max_not_reserved(max_id);

class DBOperationImpl : public DBOperation
{
	public:
		DBOperationImpl(DatabaseServer *db) : m_dbserver(db) { }

		virtual bool initialize(channel_t sender, uint16_t msg_type, DatagramIterator &dgi) = 0;

		bool populate_set_fields(DatagramIterator &dgi)
		{
			uint16_t field_count = dgi.read_uint16();
			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)
				{
					// TODO: Error!
					return false;
				}
				if(field->has_keyword("db"))
				{
					dgi.unpack_field(field, m_set_fields[field]);
				}
				else
				{
					// TODO: Warning!
					dgi.skip_field(field);
				}
			}

			return true;
		}

		DatabaseServer *m_dbserver;
		channel_t m_sender;
};

class DBOperationImpl_Create : public DBOperationImpl
{
	public:
		DBOperationImpl_Create(DatabaseServer *db) : DBOperationImpl(db) { }

		virtual bool initialize(channel_t sender, uint16_t msg_type, DatagramIterator &dgi)
		{
			m_sender = sender;

			m_type = CREATE_OBJECT;
			m_context = dgi.read_uint32();

			uint16_t dclass_id = dgi.read_uint16();
			m_dclass = g_dcf->get_class_by_id(dclass_id);
			if(!m_dclass)
			{
				// TODO: Error!
				on_failure();
				return false;
			}

			if(!populate_set_fields(dgi))
			{
				on_failure();
				return false;
			}

			return true;
		}

		virtual void 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);

			delete this;
		}

		virtual void on_failure()
		{
			// We just send back an invalid response...
			on_complete(INVALID_DO_ID);
		}

		uint32_t m_context;
};

class DBOperationImpl_Delete : public DBOperationImpl
{
	public:
		DBOperationImpl_Delete(DatabaseServer *db) : DBOperationImpl(db) { }

		virtual bool initialize(channel_t sender, uint16_t msg_type, DatagramIterator &dgi)
		{
			m_sender = sender;

			m_type = DELETE_OBJECT;
			m_doid = dgi.read_doid();

			return true;
		}

		virtual void on_failure()
		{
			delete this;
		}

		virtual void on_complete()
		{
			delete this;
		}
};

DatabaseServer::DatabaseServer(RoleConfig roleconfig) : Role(roleconfig),
	m_control_channel(control_channel.get_rval(roleconfig)),
	m_min_id(min_id.get_rval(roleconfig)),
	m_max_id(max_id.get_rval(roleconfig)),
	m_broadcast(broadcast_updates.get_rval(roleconfig))
{
	ConfigNode generate = dbserver_config.get_child_node(generate_config, roleconfig);
	ConfigNode backend = dbserver_config.get_child_node(db_backend_config, roleconfig);
	m_db_backend = DBBackendFactory::singleton().instantiate_backend(
		db_backend_type.get_rval(backend), backend,
{'fraction_non_alphanumeric': 0.10343968095712862, 'fraction_numerical': 0.007228315054835494, 'mean_word_length': 5.254871395167576, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2467513', 'n_tokens_mistral': 3131, 'n_tokens_neox': 2757, 'n_words': 488}