Some rework of #7234.
This commit is contained in:
parent
9da134cd88
commit
8bf660af90
7
src/ae.c
7
src/ae.c
@ -370,6 +370,7 @@ static int processTimeEvents(aeEventLoop *eventLoop) {
|
||||
* if flags has AE_DONT_WAIT set the function returns ASAP until all
|
||||
* the events that's possible to process without to wait are processed.
|
||||
* if flags has AE_CALL_AFTER_SLEEP set, the aftersleep callback is called.
|
||||
* if flags has AE_CALL_BEFORE_SLEEP set, the beforesleep callback is called.
|
||||
*
|
||||
* The function returns the number of events processed. */
|
||||
int aeProcessEvents(aeEventLoop *eventLoop, int flags)
|
||||
@ -428,7 +429,7 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags)
|
||||
tvp = &tv;
|
||||
}
|
||||
|
||||
if (eventLoop->beforesleep != NULL)
|
||||
if (eventLoop->beforesleep != NULL && flags & AE_CALL_BEFORE_SLEEP)
|
||||
eventLoop->beforesleep(eventLoop);
|
||||
|
||||
/* Call the multiplexing API, will return only on timeout or when
|
||||
@ -525,7 +526,9 @@ int aeWait(int fd, int mask, long long milliseconds) {
|
||||
void aeMain(aeEventLoop *eventLoop) {
|
||||
eventLoop->stop = 0;
|
||||
while (!eventLoop->stop) {
|
||||
aeProcessEvents(eventLoop, AE_ALL_EVENTS|AE_CALL_AFTER_SLEEP);
|
||||
aeProcessEvents(eventLoop, AE_ALL_EVENTS|
|
||||
AE_CALL_BEFORE_SLEEP|
|
||||
AE_CALL_AFTER_SLEEP);
|
||||
}
|
||||
}
|
||||
|
||||
|
9
src/ae.h
9
src/ae.h
@ -47,11 +47,12 @@
|
||||
things to disk before sending replies, and want
|
||||
to do that in a group fashion. */
|
||||
|
||||
#define AE_FILE_EVENTS 1
|
||||
#define AE_TIME_EVENTS 2
|
||||
#define AE_FILE_EVENTS (1<<0)
|
||||
#define AE_TIME_EVENTS (1<<1)
|
||||
#define AE_ALL_EVENTS (AE_FILE_EVENTS|AE_TIME_EVENTS)
|
||||
#define AE_DONT_WAIT 4
|
||||
#define AE_CALL_AFTER_SLEEP 8
|
||||
#define AE_DONT_WAIT (1<<2)
|
||||
#define AE_CALL_BEFORE_SLEEP (1<<3)
|
||||
#define AE_CALL_AFTER_SLEEP (1<<4)
|
||||
|
||||
#define AE_NOMORE -1
|
||||
#define AE_DELETED_EVENT_ID -1
|
||||
|
@ -2863,8 +2863,9 @@ int processEventsWhileBlocked(void) {
|
||||
ProcessingEventsWhileBlocked = 1;
|
||||
while (iterations--) {
|
||||
int events = 0;
|
||||
events += aeProcessEvents(server.el, AE_FILE_EVENTS|AE_DONT_WAIT);
|
||||
events += handleClientsWithPendingWrites();
|
||||
events += aeProcessEvents(server.el,
|
||||
AE_FILE_EVENTS|AE_DONT_WAIT|
|
||||
AE_CALL_BEFORE_SLEEP|AE_CALL_AFTER_SLEEP);
|
||||
if (!events) break;
|
||||
count += events;
|
||||
}
|
||||
|
19
src/server.c
19
src/server.c
@ -2092,21 +2092,32 @@ extern int ProcessingEventsWhileBlocked;
|
||||
/* This function gets called every time Redis is entering the
|
||||
* main loop of the event driven library, that is, before to sleep
|
||||
* for ready file descriptors.
|
||||
*
|
||||
* Note: This function is (currently) called from two functions:
|
||||
* 1. aeMain - The main server loop
|
||||
* 2. processEventsWhileBlocked - Process clients during RDB/AOF load
|
||||
*
|
||||
* If it was called from processEventsWhileBlocked we don't want
|
||||
* to perform all actions (For example, we don't want to expire
|
||||
* keys), but we do need to perform some actions.
|
||||
*
|
||||
* The most important is freeClientsInAsyncFreeQueue but we also
|
||||
* call some other low-risk functions. */
|
||||
void beforeSleep(struct aeEventLoop *eventLoop) {
|
||||
UNUSED(eventLoop);
|
||||
|
||||
if (!ProcessingEventsWhileBlocked) {
|
||||
/* Just call a subset of vital functions in case we are re-entering
|
||||
* the event loop from processEventsWhileBlocked(). */
|
||||
if (ProcessingEventsWhileBlocked) {
|
||||
handleClientsWithPendingReadsUsingThreads();
|
||||
tlsProcessPendingData();
|
||||
handleClientsWithPendingWrites();
|
||||
freeClientsInAsyncFreeQueue();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle precise timeouts of blocked clients. */
|
||||
handleBlockedClientsTimeout();
|
||||
}
|
||||
|
||||
/* We should handle pending reads clients ASAP after event loop. */
|
||||
handleClientsWithPendingReadsUsingThreads();
|
||||
@ -2117,7 +2128,6 @@ void beforeSleep(struct aeEventLoop *eventLoop) {
|
||||
/* If tls still has pending unread data don't sleep at all. */
|
||||
aeSetDontWait(server.el, tlsHasPendingData());
|
||||
|
||||
if (!ProcessingEventsWhileBlocked) {
|
||||
/* Call the Redis Cluster before sleep function. Note that this function
|
||||
* may change the state of Redis Cluster (from ok to fail or vice versa),
|
||||
* so it's a good idea to call it before serving the unblocked clients
|
||||
@ -2166,7 +2176,6 @@ void beforeSleep(struct aeEventLoop *eventLoop) {
|
||||
|
||||
/* Write the AOF buffer on disk */
|
||||
flushAppendOnlyFile(0);
|
||||
}
|
||||
|
||||
/* Handle writes with pending output buffers. */
|
||||
handleClientsWithPendingWritesUsingThreads();
|
||||
@ -2174,12 +2183,10 @@ void beforeSleep(struct aeEventLoop *eventLoop) {
|
||||
/* Close clients that need to be closed asynchronous */
|
||||
freeClientsInAsyncFreeQueue();
|
||||
|
||||
if (!ProcessingEventsWhileBlocked) {
|
||||
/* Before we are going to sleep, let the threads access the dataset by
|
||||
* releasing the GIL. Redis main thread will not touch anything at this
|
||||
* time. */
|
||||
if (moduleCount()) moduleReleaseGIL();
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is called immadiately after the event loop multiplexing
|
||||
|
Loading…
x
Reference in New Issue
Block a user