-
Notifications
You must be signed in to change notification settings - Fork 976
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactoring ProxySQL Monitor Module #4063
Conversation
Asynchronous handling of Ping, Group replication, Replication Lag, Read Only and Galera if MySQL connection is available, else tasks will be delegated to Consumer Thread.
Added separate init code for async task handling. Code cleanup
* Initialized few uninitialized variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an initial review with feedback to open discussion, the are still parts that I would like to look into more detail for these changes, so I wouldn't call it a final review. But I think there is enough feedback to start a conversation about it.
lib/MySQL_Monitor.cpp
Outdated
} | ||
|
||
|
||
bool event_loop(int poll_timeout) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See previous comment on Monitor_Poll
class definition.
assert(my!=my1); | ||
assert(my->net.fd!=my1->net.fd); | ||
} | ||
if (my) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate on why this change is now required? I faced this during testing, but haven't had time for reasoning fully about it. A nice comment pointing to why this check is now required when checking for the MYSQL
connections objects would be great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If my is NULL in debug, it will crash here
assert(my->net.fd!=my1->net.fd);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! I experienced the same, that is what I meant by facing it during testing. But was asking if you knew the reason for that to happen in this rework but not in the previous impl, I haven't reasoned a lot about it yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously, some work was done in get_connection to close connection if not used for long time. It can now return null if there are no open connections left in container.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification, there is still missing a comment in this part of the code for it, I know this change was already merged, but the comment is missing, if you could please add it that would be great.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment added
retest this please |
assert(my!=my1); | ||
assert(my->net.fd!=my1->net.fd); | ||
} | ||
if (my) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! I experienced the same, that is what I meant by facing it during testing. But was asking if you knew the reason for that to happen in this rework but not in the previous impl, I haven't reasoned a lot about it yet.
* Break loop if shutdown flag is true. * Removed duplicate success flag and exit label. * Few typo fixed.
retest this please |
2 similar comments
retest this please |
retest this please |
retest this please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great. I think after a couple of points mentioned in this last comments, this is ready for merge!
TASK_RESULT_SUCCESS = Task executed successfully. | ||
TASK_RESULT_PENDING = Task is in pending state. | ||
*/ | ||
MySQL_Monitor_State_Data_Task_Result task_handler(short event_, short& wait_event); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please try to follow the Doxygen convention used in the rest of the project for comments, it's note required when adding notes, but for definitions or declarations would really help in the later run if everything is consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
// ** TASK_RESULT_TIMEOUT = mysql connection will be closed and error log will be generated. | ||
// ** TASK_RESULT_FAILED = mysql connection will be closed and error log will be generated. | ||
// Note: calling init_async is mandatory before executing tasks asynchronously. | ||
void monitor_ping_async(SQLite3_result* resultset); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as for task_handler
regarding documentation style. Obviously you don't need to repeat the same info in every handler function, but you can just point to your detailed comment in the others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
assert(my!=my1); | ||
assert(my->net.fd!=my1->net.fd); | ||
} | ||
if (my) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification, there is still missing a comment in this part of the code for it, I know this change was already merged, but the comment is missing, if you could please add it that would be great.
} | ||
|
||
void MySQL_Monitor_State_Data::mark_task_as_timeout(unsigned long long time) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are several places that hold this extra empty lines after declarations or if statements, but only happens sometimes, I don't know if there is a reason for them. Just mentioning it in case it's an editor thing, because they look "random".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's done intentionally to avoid code clutter.
#define NEXT_IMMEDIATE(new_st) do { async_state_machine_=new_st; goto __again; } while (0) | ||
|
||
short MySQL_Monitor_State_Data::next_event(MDB_ASYNC_ST new_st, int status) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same kind of empty line as mentioned in other comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's done intentionally to avoid code clutter.
ready_tasks.reserve(tasks_to_process_count); | ||
|
||
while (len_) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty line as mentioned in other comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's done intentionally to avoid code clutter.
|
||
std::vector<std::unique_ptr<MySQL_Monitor_State_Data>> mmsds; | ||
mmsds.reserve(resultset->rows_count); | ||
Monitor_Poll monitor_poll(resultset->rows_count); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a suggestion for improving the the usage pattern of Monitor_Poll
class, which I think it's a little odd right now regarding resource handling, as it could take much better advantage of the already used std::unique_ptr
.
As I see, the usage pattern right now in the PR for Monitor_Poll
is delegating the resource destruction of the created MySQL_Monitor_State_Data
over a std::vector<std::unique_ptr<MySQL_Monitor_State_Data>>
. This vector looks unused just for performing this resource handling, this creates a window for potential missuses of the class, since the manipulation of the data stored in the std::unique_ptr<>
doesn't happen in the same scope in which the std::unique_ptr<>
lives, instead, get()
is used, invalidating the protection offered by the container. You know, I think this is normally fine when passing the pointer to a legacy function (system API, etc...) that is going to return in the same scope, but in this case, we are creating another container with the results of this get()
which can have a completely different life-spam to the original std::unique_ptr<>
.
What I suggest is to make this already constructed vector an argument for Monitor_Poll
constructor, using move semantics
for the initialization of an internal member. The size()
member of the vector can be used for the same purpose as it's now used in the current constructor, initializing the real internal structure used for polling, and iterating it as it's done right now for calling: monitor_poll.add((POLLIN|POLLOUT|POLLPRI), mmsd.get())
. There is no reason for even changing the internal logic for add
, since its purpose will be the same, but since it won't have any external usage, we should probably declare it as private. With this change Monitor_Poll
will be well-formed resource wise since its construction, without worrying about scopes for the MySQL_Monitor_State_Data
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Monitor Poll has aggregation type association with mmsd. Putting vector inside monitor poll class will change this association. Regarding mmsd life-span, this will never outlive vector, at-least in this current design.
# Conflicts: # lib/MySQL_Monitor.cpp
Refactoring ProxySQL Monitor Module
Asynchronous handling of Ping, Group replication, Replication Lag, Read Only and Galera if MySQL connection is available, else tasks will be delegated to Consumer Thread.