MXS-1929: Make filters configurable at runtime
The filters can now be altered at runtime. Currently, the filter usage uses a service level lock. The next is to allocate a per-service key to the worker local data and use that to orchestrate the storage of the filter lists.
This commit is contained in:
parent
1d92eabb91
commit
7d6338d65b
@ -58,8 +58,42 @@ public:
|
||||
*/
|
||||
bool update_basic_parameter(const std::string& name, const std::string& value);
|
||||
|
||||
std::vector<SFilterDef> filters; /**< Ordered list of filters */
|
||||
/**
|
||||
* Set the list of filters for this service
|
||||
*
|
||||
* @param filters Filters to set
|
||||
*
|
||||
* @return True if filters were all found and were valid
|
||||
*/
|
||||
bool set_filters(const std::string& filters);
|
||||
|
||||
/**
|
||||
* Get the list of filters this service uses
|
||||
*
|
||||
* @note This locks the service
|
||||
*
|
||||
* @return A list of filters or an empty list of no filters are in use
|
||||
*/
|
||||
std::vector<SFilterDef> get_filters() const;
|
||||
|
||||
inline bool has_filters() const
|
||||
{
|
||||
/**
|
||||
* Note: Temporarily used to check whether filters are available. This is
|
||||
* not thread-safe but can be replaced with a check to worker local data to
|
||||
* make it so.
|
||||
*/
|
||||
return !m_filters.empty();
|
||||
}
|
||||
|
||||
// TODO: Make JSON output internal (could iterate over get_filters() but that takes the service lock)
|
||||
json_t* json_relationships(const char* host) const;
|
||||
|
||||
// TODO: Make private
|
||||
mutable std::mutex lock;
|
||||
|
||||
private:
|
||||
std::vector<SFilterDef> m_filters; /**< Ordered list of filters */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1048,20 +1048,11 @@ int service_enable_root(Service *svc, int action)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the filters used by the service
|
||||
*
|
||||
* @param service The service itself
|
||||
* @param filters The filters to use separated by the pipe character |
|
||||
*
|
||||
* @return True if loading and creating all filters was successful. False if a
|
||||
* filter module was not found or the instance creation failed.
|
||||
*/
|
||||
bool service_set_filters(Service* service, const char* filters)
|
||||
bool Service::set_filters(const std::string& filters)
|
||||
{
|
||||
bool rval = true;
|
||||
std::vector<SFilterDef> flist;
|
||||
uint64_t capabilities = 0;
|
||||
uint64_t my_capabilities = 0;
|
||||
|
||||
for (auto& f : mxs::strtok(filters, "|"))
|
||||
{
|
||||
@ -1073,30 +1064,50 @@ bool service_set_filters(Service* service, const char* filters)
|
||||
|
||||
const MXS_MODULE* module = get_module(def->module.c_str(), MODULE_FILTER);
|
||||
ss_dassert(module);
|
||||
capabilities |= module->module_capabilities;
|
||||
my_capabilities |= module->module_capabilities;
|
||||
|
||||
if (def->obj->getCapabilities)
|
||||
{
|
||||
capabilities |= def->obj->getCapabilities(def->filter);
|
||||
my_capabilities |= def->obj->getCapabilities(def->filter);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Unable to find filter '%s' for service '%s'", f.c_str(), service->name);
|
||||
MXS_ERROR("Unable to find filter '%s' for service '%s'", f.c_str(), name);
|
||||
rval = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (rval)
|
||||
{
|
||||
Guard guard(service->lock);
|
||||
service->filters = flist;
|
||||
service->capabilities |= capabilities;
|
||||
Guard guard(lock);
|
||||
m_filters = flist;
|
||||
capabilities |= my_capabilities;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
std::vector<SFilterDef> Service::get_filters() const
|
||||
{
|
||||
Guard guard(lock);
|
||||
return m_filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the filters used by the service
|
||||
*
|
||||
* @param service The service itself
|
||||
* @param filters The filters to use separated by the pipe character |
|
||||
*
|
||||
* @return True if loading and creating all filters was successful. False if a
|
||||
* filter module was not found or the instance creation failed.
|
||||
*/
|
||||
bool service_set_filters(Service* service, const char* filters)
|
||||
{
|
||||
return service->set_filters(filters);
|
||||
}
|
||||
|
||||
Service* service_internal_find(const char *name)
|
||||
{
|
||||
Guard guard(service_spin);
|
||||
@ -1178,11 +1189,13 @@ void dprintService(DCB *dcb, SERVICE *svc)
|
||||
asctime_r(localtime_r(&service->stats.started, &result), timebuf));
|
||||
dcb_printf(dcb, "\tRoot user access: %s\n",
|
||||
service->enable_root ? "Enabled" : "Disabled");
|
||||
if (!service->filters.empty())
|
||||
auto filters = service->get_filters();
|
||||
|
||||
if (!filters.empty())
|
||||
{
|
||||
dcb_printf(dcb, "\tFilter chain: ");
|
||||
const char* sep = "";
|
||||
for (const auto& f : service->filters)
|
||||
for (const auto& f : filters)
|
||||
{
|
||||
dcb_printf(dcb, "%s %s ", f->name.c_str(), sep);
|
||||
sep = "|";
|
||||
@ -1692,12 +1705,12 @@ bool service_filter_in_use(const SFilterDef& filter)
|
||||
|
||||
for (Service* service : all_services)
|
||||
{
|
||||
Guard guard(service->lock);
|
||||
|
||||
if (std::find(service->filters.begin(),
|
||||
service->filters.end(), filter) != service->filters.end())
|
||||
for (const auto& f : service->get_filters())
|
||||
{
|
||||
return true;
|
||||
if (filter == f)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2055,18 +2068,16 @@ json_t* service_attributes(const SERVICE* service)
|
||||
return attr;
|
||||
}
|
||||
|
||||
json_t* service_relationships(const SERVICE* svc, const char* host)
|
||||
json_t* Service::json_relationships(const char* host) const
|
||||
{
|
||||
const Service* service = static_cast<const Service*>(svc);
|
||||
|
||||
/** Store relationships to other objects */
|
||||
json_t* rel = json_object();
|
||||
|
||||
if (!service->filters.empty())
|
||||
if (!m_filters.empty())
|
||||
{
|
||||
json_t* filters = mxs_json_relationship(host, MXS_JSON_API_FILTERS);
|
||||
|
||||
for (const auto& f : service->filters)
|
||||
for (const auto& f : m_filters)
|
||||
{
|
||||
mxs_json_add_relation(filters, f->name.c_str(), CN_FILTERS);
|
||||
}
|
||||
@ -2074,11 +2085,11 @@ json_t* service_relationships(const SERVICE* svc, const char* host)
|
||||
json_object_set_new(rel, CN_FILTERS, filters);
|
||||
}
|
||||
|
||||
if (have_active_servers(service))
|
||||
if (have_active_servers(this))
|
||||
{
|
||||
json_t* servers = mxs_json_relationship(host, MXS_JSON_API_SERVERS);
|
||||
|
||||
for (SERVER_REF* ref = service->dbref; ref; ref = ref->next)
|
||||
for (SERVER_REF* ref = dbref; ref; ref = ref->next)
|
||||
{
|
||||
if (SERVER_REF_IS_ACTIVE(ref))
|
||||
{
|
||||
@ -2101,7 +2112,7 @@ json_t* service_json_data(const SERVICE* svc, const char* host)
|
||||
json_object_set_new(rval, CN_ID, json_string(service->name));
|
||||
json_object_set_new(rval, CN_TYPE, json_string(CN_SERVICES));
|
||||
json_object_set_new(rval, CN_ATTRIBUTES, service_attributes(service));
|
||||
json_object_set_new(rval, CN_RELATIONSHIPS, service_relationships(service, host));
|
||||
json_object_set_new(rval, CN_RELATIONSHIPS, service->json_relationships(host));
|
||||
json_object_set_new(rval, CN_LINKS, mxs_json_self_link(host, CN_SERVICES, service->name));
|
||||
|
||||
return rval;
|
||||
@ -2162,9 +2173,7 @@ json_t* service_relations_to_filter(const SFilterDef& filter, const char* host)
|
||||
|
||||
for (Service* service : all_services)
|
||||
{
|
||||
Guard guard(service->lock);
|
||||
|
||||
for (const auto& f : service->filters)
|
||||
for (const auto& f : service->get_filters())
|
||||
{
|
||||
if (f == filter)
|
||||
{
|
||||
@ -2321,7 +2330,8 @@ bool Service::is_basic_parameter(const std::string& name)
|
||||
CN_STRIP_DB_ESC,
|
||||
CN_USER,
|
||||
CN_VERSION_STRING,
|
||||
CN_WEIGHTBY
|
||||
CN_WEIGHTBY,
|
||||
CN_FILTERS
|
||||
};
|
||||
|
||||
return names.find(name) != names.end();
|
||||
@ -2415,6 +2425,10 @@ bool Service::update_basic_parameter(const std::string& key, const std::string&
|
||||
retry_start = config_truth_value(value.c_str());
|
||||
valid = true;
|
||||
}
|
||||
else if (key == CN_FILTERS)
|
||||
{
|
||||
valid = set_filters(value);
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
@ -657,20 +657,21 @@ session_setup_filters(MXS_SESSION *session)
|
||||
MXS_UPSTREAM *tail;
|
||||
int i = 0;
|
||||
|
||||
if (service->filters.empty())
|
||||
if (!service->has_filters())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((session->filters = (SESSION_FILTER*)MXS_CALLOC(service->filters.size(),
|
||||
sizeof(SESSION_FILTER))) == NULL)
|
||||
auto filters = service->get_filters();
|
||||
|
||||
if ((session->filters = (SESSION_FILTER*)MXS_CALLOC(filters.size(), sizeof(SESSION_FILTER))) == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
session->n_filters = service->filters.size();
|
||||
session->n_filters = filters.size();
|
||||
|
||||
for (auto r = service->filters.rbegin(); r != service->filters.rend(); r++)
|
||||
for (auto r = filters.rbegin(); r != filters.rend(); r++)
|
||||
{
|
||||
if ((head = filter_apply(*r, session, &session->head)) == NULL)
|
||||
{
|
||||
@ -686,7 +687,7 @@ session_setup_filters(MXS_SESSION *session)
|
||||
MXS_FREE(head);
|
||||
}
|
||||
|
||||
for (auto r = service->filters.begin(); r != service->filters.end(); r++)
|
||||
for (auto r = filters.begin(); r != filters.end(); r++)
|
||||
{
|
||||
if ((tail = filter_upstream(*r, session->filters[i].session, &session->tail)) == NULL)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user