-
Notifications
You must be signed in to change notification settings - Fork 7
Open
Labels
code healthImprove code readability, simplify maintenance and so onImprove code readability, simplify maintenance and so onrefactoringCode refactoringCode refactoring
Description
Currently, we have a bunch of free functions on ConnectionImpl and
Connection, such as hasSentBytes, hasNotRecvBytes, hasDataToSend,
hasDataToDecode, etc:
tntcxx/src/Client/Connection.hpp
Lines 485 to 604 in 2184427
| template<class BUFFER, class NetProvider> | |
| void | |
| hasSentBytes(Connection<BUFFER, NetProvider> &conn, size_t bytes) | |
| { | |
| //dropBack()/dropFront() interfaces require number of bytes be greater | |
| //than zero so let's check it first. | |
| if (bytes > 0) | |
| conn.impl->outBuf.dropFront(bytes); | |
| } | |
| template<class BUFFER, class NetProvider> | |
| void | |
| hasNotRecvBytes(Connection<BUFFER, NetProvider> &conn, size_t bytes) | |
| { | |
| if (bytes > 0) | |
| conn.impl->inBuf.dropBack(bytes); | |
| } | |
| template<class BUFFER, class NetProvider> | |
| bool | |
| hasDataToSend(Connection<BUFFER, NetProvider> &conn) | |
| { | |
| //We drop content of input buffer once it has been sent. So to detect | |
| //if there's any data to send it's enough to check buffer's emptiness. | |
| return !conn.impl->outBuf.empty(); | |
| } | |
| template<class BUFFER, class NetProvider> | |
| bool | |
| hasDataToDecode(Connection<BUFFER, NetProvider> &conn) | |
| { | |
| assert(conn.impl->endDecoded < conn.impl->inBuf.end() || | |
| conn.impl->endDecoded == conn.impl->inBuf.end()); | |
| return conn.impl->endDecoded != conn.impl->inBuf.end(); | |
| } | |
| template<class BUFFER, class NetProvider> | |
| static void | |
| inputBufGC(Connection<BUFFER, NetProvider> &conn) | |
| { | |
| if ((conn.gc_step++ % Connection<BUFFER, NetProvider>::GC_STEP_CNT) == 0) { | |
| TNT_LOG_DEBUG("Flushed input buffer of the connection %p", &conn); | |
| conn.impl->inBuf.flush(); | |
| } | |
| } | |
| template<class BUFFER, class NetProvider> | |
| DecodeStatus | |
| processResponse(Connection<BUFFER, NetProvider> &conn, int req_sync, Response<BUFFER> *result) | |
| { | |
| //Decode response. In case of success - fill in feature map | |
| //and adjust end-of-decoded data pointer. Call GC if needed. | |
| if (! conn.impl->inBuf.has(conn.impl->endDecoded, MP_RESPONSE_SIZE)) | |
| return DECODE_NEEDMORE; | |
| Response<BUFFER> response; | |
| response.size = conn.impl->dec.decodeResponseSize(); | |
| if (response.size < 0) { | |
| TNT_LOG_ERROR("Failed to decode response size"); | |
| //In case of corrupted response size all other data in the buffer | |
| //is likely to be decoded in the wrong way (since we don't | |
| // know how much bytes should be skipped). So let's simply | |
| //terminate here. | |
| std::abort(); | |
| } | |
| response.size += MP_RESPONSE_SIZE; | |
| if (! conn.impl->inBuf.has(conn.impl->endDecoded, response.size)) { | |
| //Response was received only partially. Reset decoder position | |
| //to the start of response to make this function re-entered. | |
| conn.impl->dec.reset(conn.impl->endDecoded); | |
| return DECODE_NEEDMORE; | |
| } | |
| if (conn.impl->dec.decodeResponse(response) != 0) { | |
| conn.setError("Failed to decode response, skipping bytes.."); | |
| conn.impl->endDecoded += response.size; | |
| return DECODE_ERR; | |
| } | |
| TNT_LOG_DEBUG("Header: sync=", response.header.sync, ", code=", response.header.code, | |
| ", schema=", response.header.schema_id); | |
| if (result != nullptr && response.header.sync == req_sync) { | |
| *result = std::move(response); | |
| } else { | |
| conn.impl->futures.insert({response.header.sync, | |
| std::move(response)}); | |
| } | |
| conn.impl->endDecoded += response.size; | |
| inputBufGC(conn); | |
| return DECODE_SUCC; | |
| } | |
| template<class BUFFER, class NetProvider> | |
| int | |
| decodeGreeting(Connection<BUFFER, NetProvider> &conn) | |
| { | |
| //TODO: that's not zero-copy, should be rewritten in that pattern. | |
| assert(conn.getInBuf().has(conn.impl->endDecoded, Iproto::GREETING_SIZE)); | |
| char greeting_buf[Iproto::GREETING_SIZE]; | |
| conn.impl->endDecoded.read({greeting_buf, sizeof(greeting_buf)}); | |
| conn.impl->dec.reset(conn.impl->endDecoded); | |
| if (parseGreeting(std::string_view{greeting_buf, Iproto::GREETING_SIZE}, | |
| conn.impl->greeting) != 0) | |
| return -1; | |
| conn.impl->is_greeting_received = true; | |
| TNT_LOG_DEBUG("Version: ", conn.impl->greeting.version_id); | |
| #ifndef NDEBUG | |
| //print salt in hex format. | |
| char hex_salt[Iproto::MAX_SALT_SIZE * 2 + 1]; | |
| const char *hex = "0123456789abcdef"; | |
| for (size_t i = 0; i < conn.impl->greeting.salt_size; i++) { | |
| uint8_t u = conn.impl->greeting.salt[i]; | |
| hex_salt[i * 2] = hex[u / 16]; | |
| hex_salt[i * 2 + 1] = hex[u % 16]; | |
| } | |
| hex_salt[conn.impl->greeting.salt_size * 2] = 0; | |
| TNT_LOG_DEBUG("Salt: ", hex_salt); | |
| #endif | |
| return 0; | |
| } |
All of them have a ConnectionImpl or Connection
as an argument. This is an anti-pattern, and these functions need to be
encapsulated in the corresponding classes.
Metadata
Metadata
Assignees
Labels
code healthImprove code readability, simplify maintenance and so onImprove code readability, simplify maintenance and so onrefactoringCode refactoringCode refactoring