MCPcopy Create free account
hub / github.com/Snapchat/KeyDB / clientsCron

Function clientsCron

src/server.cpp:1990–2052  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1988 */
1989#define CLIENTS_CRON_MIN_ITERATIONS 5
1990void clientsCron(int iel) {
1991 /* Try to process at least numclients/g_pserver->hz of clients
1992 * per call. Since normally (if there are no big latency events) this
1993 * function is called g_pserver->hz times per second, in the average case we
1994 * process all the clients in 1 second. */
1995 int numclients = listLength(g_pserver->clients);
1996 int iterations = numclients/g_pserver->hz;
1997 mstime_t now = mstime();
1998
1999 /* Process at least a few clients while we are at it, even if we need
2000 * to process less than CLIENTS_CRON_MIN_ITERATIONS to meet our contract
2001 * of processing each client once per second. */
2002 if (iterations < CLIENTS_CRON_MIN_ITERATIONS)
2003 iterations = (numclients < CLIENTS_CRON_MIN_ITERATIONS) ?
2004 numclients : CLIENTS_CRON_MIN_ITERATIONS;
2005
2006
2007 int curr_peak_mem_usage_slot = g_pserver->unixtime % CLIENTS_PEAK_MEM_USAGE_SLOTS;
2008 /* Always zero the next sample, so that when we switch to that second, we'll
2009 * only register samples that are greater in that second without considering
2010 * the history of such slot.
2011 *
2012 * Note: our index may jump to any random position if serverCron() is not
2013 * called for some reason with the normal frequency, for instance because
2014 * some slow command is called taking multiple seconds to execute. In that
2015 * case our array may end containing data which is potentially older
2016 * than CLIENTS_PEAK_MEM_USAGE_SLOTS seconds: however this is not a problem
2017 * since here we want just to track if "recently" there were very expansive
2018 * clients from the POV of memory usage. */
2019 int zeroidx = (curr_peak_mem_usage_slot+1) % CLIENTS_PEAK_MEM_USAGE_SLOTS;
2020 ClientsPeakMemInput[zeroidx] = 0;
2021 ClientsPeakMemOutput[zeroidx] = 0;
2022
2023
2024 while(listLength(g_pserver->clients) && iterations--) {
2025 client *c;
2026 listNode *head;
2027 /* Rotate the list, take the current head, process.
2028 * This way if the client must be removed from the list it's the
2029 * first element and we don't incur into O(N) computation. */
2030 listRotateTailToHead(g_pserver->clients);
2031 head = (listNode*)listFirst(g_pserver->clients);
2032 c = (client*)listNodeValue(head);
2033 if (c->iel == iel)
2034 {
2035 fastlock_lock(&c->lock);
2036 /* The following functions do different service checks on the client.
2037 * The protocol is that they return non-zero if the client was
2038 * terminated. */
2039 if (clientsCronHandleTimeout(c,now)) continue; // Client free'd so don't release the lock
2040 if (clientsCronResizeQueryBuffer(c)) goto LContinue;
2041 if (clientsCronTrackExpansiveClients(c, curr_peak_mem_usage_slot)) goto LContinue;
2042 if (clientsCronTrackClientsMemUsage(c)) goto LContinue;
2043 if (closeClientOnOutputBufferLimitReached(c, 0)) continue; // Client also free'd
2044 if (closeClientOnOverload(c)) continue;
2045 LContinue:
2046 fastlock_unlock(&c->lock);
2047 }

Callers 2

serverCronFunction · 0.85
serverCronLiteFunction · 0.85

Calls 11

listRotateTailToHeadFunction · 0.85
fastlock_lockFunction · 0.85
clientsCronHandleTimeoutFunction · 0.85
closeClientOnOverloadFunction · 0.85
fastlock_unlockFunction · 0.85
mstimeFunction · 0.70

Tested by

no test coverage detected