This function is called every time, in the client structure 'c', there is * more query buffer to process, because we read more data from the socket * or because a client was blocked and later reactivated, so there could be * pending query buffer, already representing a full command, to process. */
| 2073 | * or because a client was blocked and later reactivated, so there could be |
| 2074 | * pending query buffer, already representing a full command, to process. */ |
| 2075 | void processInputBuffer(client *c) { |
| 2076 | /* Keep processing while there is something in the input buffer */ |
| 2077 | while(c->qb_pos < sdslen(c->querybuf)) { |
| 2078 | /* Immediately abort if the client is in the middle of something. */ |
| 2079 | if (c->flags & CLIENT_BLOCKED) break; |
| 2080 | |
| 2081 | /* Don't process more buffers from clients that have already pending |
| 2082 | * commands to execute in c->argv. */ |
| 2083 | if (c->flags & CLIENT_PENDING_COMMAND) break; |
| 2084 | |
| 2085 | /* Don't process input from the master while there is a busy script |
| 2086 | * condition on the slave. We want just to accumulate the replication |
| 2087 | * stream (instead of replying -BUSY like we do with other clients) and |
| 2088 | * later resume the processing. */ |
| 2089 | if (server.lua_timedout && c->flags & CLIENT_MASTER) break; |
| 2090 | |
| 2091 | /* CLIENT_CLOSE_AFTER_REPLY closes the connection once the reply is |
| 2092 | * written to the client. Make sure to not let the reply grow after |
| 2093 | * this flag has been set (i.e. don't process more commands). |
| 2094 | * |
| 2095 | * The same applies for clients we want to terminate ASAP. */ |
| 2096 | if (c->flags & (CLIENT_CLOSE_AFTER_REPLY|CLIENT_CLOSE_ASAP)) break; |
| 2097 | |
| 2098 | /* Determine request type when unknown. */ |
| 2099 | if (!c->reqtype) { |
| 2100 | if (c->querybuf[c->qb_pos] == '*') { |
| 2101 | c->reqtype = PROTO_REQ_MULTIBULK; |
| 2102 | } else { |
| 2103 | c->reqtype = PROTO_REQ_INLINE; |
| 2104 | } |
| 2105 | } |
| 2106 | |
| 2107 | if (c->reqtype == PROTO_REQ_INLINE) { |
| 2108 | if (processInlineBuffer(c) != C_OK) break; |
| 2109 | /* If the Gopher mode and we got zero or one argument, process |
| 2110 | * the request in Gopher mode. To avoid data race, Redis won't |
| 2111 | * support Gopher if enable io threads to read queries. */ |
| 2112 | if (server.gopher_enabled && !server.io_threads_do_reads && |
| 2113 | ((c->argc == 1 && ((char*)(c->argv[0]->ptr))[0] == '/') || |
| 2114 | c->argc == 0)) |
| 2115 | { |
| 2116 | processGopherRequest(c); |
| 2117 | resetClient(c); |
| 2118 | c->flags |= CLIENT_CLOSE_AFTER_REPLY; |
| 2119 | break; |
| 2120 | } |
| 2121 | } else if (c->reqtype == PROTO_REQ_MULTIBULK) { |
| 2122 | if (processMultibulkBuffer(c) != C_OK) break; |
| 2123 | } else { |
| 2124 | serverPanic("Unknown request type"); |
| 2125 | } |
| 2126 | |
| 2127 | /* Multibulk processing could see a <= 0 length. */ |
| 2128 | if (c->argc == 0) { |
| 2129 | resetClient(c); |
| 2130 | } else { |
| 2131 | /* If we are in the context of an I/O thread, we can't really |
| 2132 | * execute the command here. All we can do is to flag the client |
no test coverage detected