Skip to content

Commit c62274b

Browse files
committed
WL#16572: Make caching_sha2 plugin use the event component APIs
* Converted the caching_sha2 plugin to use the event component APIs instead of the audit log plugin API * Fixed a design problem with the event component APIs allowing more than just the event API->audit plugin API bridge to always be called, even when the reference cache component is absent. It will now cache and call all event services that are registered by the server component (bridge included). * Added a new utility class My_registry_query to wrap around the registry_query service to find all implementations of a given service. * Fixed a bug in event_tracking_general_notify() causing a buffer overflow. * Fixed a test to sort its results properly. * Addressed Harin's comments Change-Id: Iee648a66a825765b6864ac736a3be40b5701d036
1 parent bad5a81 commit c62274b

15 files changed

+1050
-526
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/* Copyright (c) 2024, Oracle and/or its affiliates.
2+
3+
This program is free software; you can redistribute it and/or modify
4+
it under the terms of the GNU General Public License, version 2.0,
5+
as published by the Free Software Foundation.
6+
7+
This program is designed to work with certain software (including
8+
but not limited to OpenSSL) that is licensed under separate terms,
9+
as designated in a particular file or component or in included license
10+
documentation. The authors of MySQL hereby grant you an additional
11+
permission to link the program and your derivative works with the
12+
separately licensed software that they have either included with
13+
the program or referenced in the documentation.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU General Public License, version 2.0, for more details.
19+
20+
You should have received a copy of the GNU General Public License
21+
along with this program; if not, write to the Free Software
22+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23+
24+
#ifndef MY_REGISTRY_QUERY_H
25+
#define MY_REGISTRY_QUERY_H
26+
27+
#include <mysql/components/my_service.h>
28+
#include <mysql/components/service.h>
29+
#include <mysql/components/services/registry.h>
30+
#include <cstring>
31+
#include <string>
32+
#include <unordered_set>
33+
#include "scope_guard.h"
34+
35+
/**
36+
A registry query convenience class
37+
38+
Uses the registry query service to produce an unique set of service names
39+
that match the pattern supplied.
40+
41+
Typical use is:
42+
43+
@code
44+
My_registry_query_string string_list("foo", h_registry);
45+
if (string_list.init()) error_out();
46+
for (auto name : string_list) {
47+
<do stuff with names>
48+
}
49+
@endcode
50+
51+
@sa @ref My_registry_query_and_acquire
52+
*/
53+
class My_registry_query_string : public std::unordered_set<std::string> {
54+
const std::string m_service_name;
55+
SERVICE_TYPE(registry) * m_registry;
56+
SERVICE_TYPE(registry_query) * m_registry_query;
57+
my_h_service m_reg_query_handle{nullptr};
58+
59+
public:
60+
bool init() {
61+
this->erase(this->begin(), this->end());
62+
SERVICE_TYPE(registry_query) *svc = m_registry_query;
63+
if (svc == nullptr) {
64+
my_service<SERVICE_TYPE(registry_query)> msvc("registry_query",
65+
m_registry);
66+
if (!msvc.is_valid()) return true;
67+
svc = msvc.untie();
68+
}
69+
auto x = create_scope_guard([&] {
70+
if (svc != m_registry_query)
71+
m_registry->release(reinterpret_cast<my_h_service>(
72+
const_cast<SERVICE_TYPE_NO_CONST(registry_query) *>(svc)));
73+
});
74+
75+
my_h_service_iterator iter;
76+
if (!svc->create(m_service_name.c_str(), &iter)) {
77+
while (!svc->is_valid(iter)) {
78+
const char *name{nullptr};
79+
if (svc->get(iter, &name)) return true;
80+
if (name == nullptr) return true;
81+
size_t name_len = strlen(name);
82+
if (strncmp(name, m_service_name.c_str(), m_service_name.length()) ||
83+
name_len < m_service_name.length() ||
84+
(name[m_service_name.length()] != '.' &&
85+
name[m_service_name.length()] != 0))
86+
break;
87+
this->emplace(name);
88+
if (svc->next(iter)) break;
89+
}
90+
svc->release(iter);
91+
}
92+
return false;
93+
}
94+
95+
My_registry_query_string(const char *service_name,
96+
SERVICE_TYPE(registry) * reg,
97+
SERVICE_TYPE(registry_query) *reg_query = nullptr)
98+
: m_service_name(service_name),
99+
m_registry(reg),
100+
m_registry_query(reg_query) {
101+
if (m_registry_query == nullptr) {
102+
if (!reg->acquire("registry_query", &m_reg_query_handle)) {
103+
m_registry_query = reinterpret_cast<SERVICE_TYPE(registry_query) *>(
104+
m_reg_query_handle);
105+
}
106+
}
107+
}
108+
109+
My_registry_query_string(const My_registry_query_string &other) = delete;
110+
My_registry_query_string(My_registry_query_string &&other) = delete;
111+
~My_registry_query_string() {
112+
if (m_reg_query_handle) m_registry->release(m_reg_query_handle);
113+
}
114+
};
115+
116+
/**
117+
A service acquiring registry query convenience class
118+
119+
Uses the @ref My_registry_query_string class to get a list of
120+
service names matching the pattern, acquires references for these
121+
and keeps them until the instance's destruction.
122+
123+
Typical use pattern is:
124+
@code
125+
My_registry_query_and_acquire<SERVICE_TYPE(foo)> qry("foo", registry_ref);
126+
if (qry->init()) error_out();
127+
for (SERVICE_TYPE(foo) *x : qry) {
128+
x->method();
129+
}
130+
@endcode
131+
132+
@sa @ref My_registry_query_string
133+
*/
134+
135+
template <class ServiceType>
136+
class My_registry_query_and_acquire : public std::unordered_set<ServiceType *> {
137+
const std::string m_service_name;
138+
SERVICE_TYPE(registry) * m_registry;
139+
My_registry_query_string m_string_list;
140+
141+
public:
142+
My_registry_query_and_acquire(
143+
const char *service_name, SERVICE_TYPE(registry) * reg,
144+
SERVICE_TYPE(registry_query) *reg_query = nullptr)
145+
: m_service_name(service_name),
146+
m_registry(reg),
147+
m_string_list(service_name, reg, reg_query) {}
148+
149+
My_registry_query_and_acquire(const My_registry_query_and_acquire &other) =
150+
delete;
151+
My_registry_query_and_acquire(My_registry_query_and_acquire &&other) = delete;
152+
153+
~My_registry_query_and_acquire() { reset(); }
154+
155+
/**
156+
@brief Call this method to populate the data into the class
157+
158+
@retval true failure
159+
@retval false success
160+
*/
161+
bool init() {
162+
if (m_string_list.init()) return true;
163+
for (auto name : m_string_list) {
164+
my_h_service hsvc;
165+
if (m_registry->acquire(name.c_str(), &hsvc)) return true;
166+
auto res = this->insert(reinterpret_cast<ServiceType *>(hsvc));
167+
if (!res.second) m_registry->release(hsvc);
168+
}
169+
m_string_list.clear();
170+
return false;
171+
}
172+
173+
/**
174+
@brief Properly releases and disposes of all the references
175+
176+
Called by the destructor too
177+
*/
178+
void reset() {
179+
for (auto svc : *this) {
180+
m_registry->release(reinterpret_cast<my_h_service>(
181+
const_cast<void *>(reinterpret_cast<const void *>(svc))));
182+
}
183+
this->erase(this->begin(), this->end());
184+
}
185+
};
186+
#endif /* MY_REGISTRY_QUERY_H */

0 commit comments

Comments
 (0)