Skip to content

Commit c1539bd

Browse files
namsicjhpark816
authored andcommitted
FEATURE: Add shutdown command
1 parent 3c7348c commit c1539bd

File tree

1 file changed

+67
-3
lines changed

1 file changed

+67
-3
lines changed

memcached.c

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ void UNLOCK_SETTING(void) {
8787

8888
static pthread_mutex_t shutdown_lock = PTHREAD_MUTEX_INITIALIZER;
8989
volatile sig_atomic_t memcached_shutdown=0;
90+
volatile int32_t shutdown_delay=0;
91+
volatile bool dynamic_shutdown=false;
9092

9193
/*
9294
* We keep the current time of day in a global variable that's updated by a
@@ -10068,6 +10070,41 @@ static void process_lqdetect_command(conn *c, token_t *tokens, size_t ntokens)
1006810070
}
1006910071
#endif
1007010072

10073+
static void process_shutdown_command(conn *c, token_t *tokens, size_t ntokens)
10074+
{
10075+
int32_t delay;
10076+
10077+
if (memcached_shutdown > 0 && shutdown_delay < 1000) {
10078+
out_string(c, "DENIED");
10079+
return;
10080+
}
10081+
10082+
if (ntokens == 2) {
10083+
delay = 2;
10084+
dynamic_shutdown = true;
10085+
} else {
10086+
if (! safe_strtol(tokens[1].value, &delay)) {
10087+
print_invalid_command(c, tokens, ntokens);
10088+
out_string(c, "CLIENT_ERROR bad command line format");
10089+
return;
10090+
} else if (delay < 0 || delay > 600) {
10091+
print_invalid_command(c, tokens, ntokens);
10092+
out_string(c, "CLIENT_ERROR invalid arguments");
10093+
return;
10094+
}
10095+
dynamic_shutdown = false;
10096+
}
10097+
mc_logger->log(EXTENSION_LOG_WARNING, c,
10098+
"shutdown scheduled (time=%d, dynamic=%d)\n", (int)delay, dynamic_shutdown);
10099+
shutdown_delay = delay * 1000;
10100+
pthread_mutex_lock(&shutdown_lock);
10101+
if (memcached_shutdown == 0) {
10102+
memcached_shutdown = 1;
10103+
}
10104+
pthread_mutex_unlock(&shutdown_lock);
10105+
out_string(c, "OK");
10106+
}
10107+
1007110108
static inline int get_coll_create_attr_from_tokens(token_t *tokens, const int ntokens,
1007210109
int coll_type, item_attr *attrp)
1007310110
{
@@ -13244,6 +13281,10 @@ static void process_command_ascii(conn *c, char *command, int cmdlen)
1324413281
#endif
1324513282
out_string(c, response);
1324613283
}
13284+
else if ((ntokens >= 2) && (strcmp(tokens[COMMAND_TOKEN].value, "shutdown") == 0))
13285+
{
13286+
process_shutdown_command(c, tokens, ntokens);
13287+
}
1324713288
else /* no matching command */
1324813289
{
1324913290
if (settings.extensions.ascii != NULL) {
@@ -14542,6 +14583,8 @@ static void remove_pidfile(const char *pid_file)
1454214583

1454314584
static void shutdown_server(void)
1454414585
{
14586+
shutdown_delay = 0;
14587+
dynamic_shutdown = false;
1454514588
pthread_mutex_lock(&shutdown_lock);
1454614589
if (memcached_shutdown == 0) {
1454714590
memcached_shutdown = 1;
@@ -15828,7 +15871,28 @@ int main (int argc, char **argv)
1582815871
close_listen_sockets();
1582915872
mc_logger->log(EXTENSION_LOG_INFO, NULL, "Listen sockets closed.\n");
1583015873

15831-
/* 4) shutdown all threads */
15874+
/* 4) wait until existing clients close */
15875+
unsigned int prev_conns = UINT_MAX;
15876+
while (shutdown_delay > 0) {
15877+
if (dynamic_shutdown) {
15878+
LOCK_STATS();
15879+
if (mc_stats.curr_conns > 0 && mc_stats.curr_conns < prev_conns) {
15880+
prev_conns = mc_stats.curr_conns;
15881+
} else {
15882+
mc_logger->log(EXTENSION_LOG_INFO, NULL,
15883+
"Client connections haven't been reduced. "
15884+
"Shuts down %dms earlier than scheduled time.\n",
15885+
shutdown_delay);
15886+
shutdown_delay = 0;
15887+
}
15888+
UNLOCK_STATS();
15889+
if (shutdown_delay <= 0) break;
15890+
}
15891+
usleep(200000); /* sleep 200ms */
15892+
shutdown_delay -= 200;
15893+
}
15894+
15895+
/* 5) shutdown all threads */
1583215896
pthread_mutex_lock(&shutdown_lock);
1583315897
memcached_shutdown = 2;
1583415898
pthread_mutex_unlock(&shutdown_lock);
@@ -15839,7 +15903,7 @@ int main (int argc, char **argv)
1583915903
}
1584015904
mc_logger->log(EXTENSION_LOG_INFO, NULL, "Worker threads terminated.\n");
1584115905

15842-
/* 5) destroy data structures */
15906+
/* 6) destroy data structures */
1584315907
#ifdef COMMAND_LOGGING
1584415908
cmdlog_final(); /* finalize command logging */
1584515909
#endif
@@ -15850,7 +15914,7 @@ int main (int argc, char **argv)
1585015914
mc_logger->log(EXTENSION_LOG_INFO, NULL, "Memcached engine destroyed.\n");
1585115915

1585215916
#ifdef ENABLE_ZK_INTEGRATION
15853-
/* 6) destroy cluster config structure */
15917+
/* 7) destroy cluster config structure */
1585415918
if (arcus_zk_cfg) {
1585515919
arcus_zk_destroy();
1585615920
free(arcus_zk_cfg);

0 commit comments

Comments
 (0)