| 2154 | } |
| 2155 | |
| 2156 | void readQueryFromClient(connection *conn) { |
| 2157 | client *c = connGetPrivateData(conn); |
| 2158 | int nread, readlen; |
| 2159 | size_t qblen; |
| 2160 | |
| 2161 | /* Check if we want to read from the client later when exiting from |
| 2162 | * the event loop. This is the case if threaded I/O is enabled. */ |
| 2163 | if (postponeClientRead(c)) return; |
| 2164 | |
| 2165 | /* Update total number of reads on server */ |
| 2166 | atomicIncr(server.stat_total_reads_processed, 1); |
| 2167 | |
| 2168 | readlen = PROTO_IOBUF_LEN; |
| 2169 | /* If this is a multi bulk request, and we are processing a bulk reply |
| 2170 | * that is large enough, try to maximize the probability that the query |
| 2171 | * buffer contains exactly the SDS string representing the object, even |
| 2172 | * at the risk of requiring more read(2) calls. This way the function |
| 2173 | * processMultiBulkBuffer() can avoid copying buffers to create the |
| 2174 | * Redis Object representing the argument. */ |
| 2175 | if (c->reqtype == PROTO_REQ_MULTIBULK && c->multibulklen && c->bulklen != -1 |
| 2176 | && c->bulklen >= PROTO_MBULK_BIG_ARG) |
| 2177 | { |
| 2178 | ssize_t remaining = (size_t)(c->bulklen+2)-sdslen(c->querybuf); |
| 2179 | |
| 2180 | /* Note that the 'remaining' variable may be zero in some edge case, |
| 2181 | * for example once we resume a blocked client after CLIENT PAUSE. */ |
| 2182 | if (remaining > 0 && remaining < readlen) readlen = remaining; |
| 2183 | } |
| 2184 | |
| 2185 | qblen = sdslen(c->querybuf); |
| 2186 | if (c->querybuf_peak < qblen) c->querybuf_peak = qblen; |
| 2187 | c->querybuf = sdsMakeRoomFor(c->querybuf, readlen); |
| 2188 | nread = connRead(c->conn, c->querybuf+qblen, readlen); |
| 2189 | if (nread == -1) { |
| 2190 | if (connGetState(conn) == CONN_STATE_CONNECTED) { |
| 2191 | return; |
| 2192 | } else { |
| 2193 | serverLog(LL_VERBOSE, "Reading from client: %s",connGetLastError(c->conn)); |
| 2194 | freeClientAsync(c); |
| 2195 | return; |
| 2196 | } |
| 2197 | } else if (nread == 0) { |
| 2198 | serverLog(LL_VERBOSE, "Client closed connection"); |
| 2199 | freeClientAsync(c); |
| 2200 | return; |
| 2201 | } else if (c->flags & CLIENT_MASTER) { |
| 2202 | /* Append the query buffer to the pending (not applied) buffer |
| 2203 | * of the master. We'll use this buffer later in order to have a |
| 2204 | * copy of the string applied by the last command executed. */ |
| 2205 | c->pending_querybuf = sdscatlen(c->pending_querybuf, |
| 2206 | c->querybuf+qblen,nread); |
| 2207 | } |
| 2208 | |
| 2209 | sdsIncrLen(c->querybuf,nread); |
| 2210 | c->lastinteraction = server.unixtime; |
| 2211 | if (c->flags & CLIENT_MASTER) c->read_reploff += nread; |
| 2212 | atomicIncr(server.stat_net_input_bytes, nread); |
| 2213 | if (sdslen(c->querybuf) > server.client_max_querybuf_len) { |
no test coverage detected