mirror of
https://github.com/joyieldInc/predixy.git
synced 2026-02-05 01:42:24 +08:00
fix scan parse buf
This commit is contained in:
parent
b059744c5f
commit
83e887fc77
112
src/Handler.cpp
112
src/Handler.cpp
@ -841,53 +841,77 @@ void Handler::handleResponse(ConnectConnection* s, Request* req, Response* res)
|
|||||||
}
|
}
|
||||||
} else if (req->type() == Command::Scan && s && res->type() == Reply::Array) {
|
} else if (req->type() == Command::Scan && s && res->type() == Reply::Array) {
|
||||||
SegmentStr<64> str(res->body());
|
SegmentStr<64> str(res->body());
|
||||||
if (const char* p = strchr(str.data() + sizeof("*2\r\n$"), '\n')) {
|
// SCAN response format: *2\r\n$<len>\r\n<cursor>\r\n*<count>\r\n...
|
||||||
// Use 128-bit integer to handle large cursor values (Kvrocks may return cursor close to 64-bit limit)
|
// Skip "*2\r\n$" (5 bytes) and find the first '\n' after the length number
|
||||||
__uint128_t cursor = 0;
|
// Add boundary check to prevent buffer overflow
|
||||||
const char* cursorStr = p + 1;
|
const char* start = str.data();
|
||||||
const char* cursorStart = cursorStr;
|
int len = str.length();
|
||||||
while (*cursorStr >= '0' && *cursorStr <= '9') {
|
if (len >= 5) {
|
||||||
cursor = cursor * 10 + (*cursorStr - '0');
|
const char* end = start + len;
|
||||||
cursorStr++;
|
const char* p = start + 5; // Skip "*2\r\n$" (5 bytes, not sizeof which returns 8!)
|
||||||
|
|
||||||
|
// Find '\n' within buffer boundary (safer than strchr)
|
||||||
|
while (p < end && *p != '\n') {
|
||||||
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug log: cursor received from backend server
|
if (p < end) { // Found '\n'
|
||||||
char serverCursorBuf[64];
|
// Use 128-bit integer to handle large cursor values (Kvrocks may return cursor close to 64-bit limit)
|
||||||
int serverCursorLen = cursorStr - cursorStart;
|
__uint128_t cursor = 0;
|
||||||
if (serverCursorLen > 0 && serverCursorLen < 64) {
|
const char* cursorStr = p + 1;
|
||||||
memcpy(serverCursorBuf, cursorStart, serverCursorLen);
|
const char* cursorStart = cursorStr;
|
||||||
serverCursorBuf[serverCursorLen] = '\0';
|
|
||||||
} else {
|
// Parse cursor digits within buffer boundary
|
||||||
strcpy(serverCursorBuf, "0");
|
while (cursorStr < end && *cursorStr >= '0' && *cursorStr <= '9') {
|
||||||
}
|
cursor = cursor * 10 + (*cursorStr - '0');
|
||||||
|
cursorStr++;
|
||||||
auto g = s->server()->group();
|
}
|
||||||
int currentGroupId = g ? g->id() : -1;
|
|
||||||
|
// Debug log: cursor received from backend server
|
||||||
if (cursor != 0 || (g = sp->getGroup(g->id() + 1)) != nullptr) {
|
char serverCursorBuf[64];
|
||||||
// Use 128-bit integer for left shift, will not overflow
|
int serverCursorLen = cursorStr - cursorStart;
|
||||||
cursor <<= Const::ServGroupBits;
|
if (serverCursorLen > 0 && serverCursorLen < 64) {
|
||||||
cursor |= g->id();
|
memcpy(serverCursorBuf, cursorStart, serverCursorLen);
|
||||||
if ((p = strchr(p, '*')) != nullptr) {
|
serverCursorBuf[serverCursorLen] = '\0';
|
||||||
// Convert 128-bit integer to string
|
} else {
|
||||||
char buf[64]; // 128-bit needs at most 39 decimal digits
|
strcpy(serverCursorBuf, "0");
|
||||||
int n = Util::uint128ToString(cursor, buf);
|
}
|
||||||
|
|
||||||
// Debug log: cursor to be sent to client
|
auto g = s->server()->group();
|
||||||
logDebug("h %d SCAN cursor from server: %s, group: %d, cursor to client: %s",
|
int currentGroupId = g ? g->id() : -1;
|
||||||
id(), serverCursorBuf, g->id(), buf);
|
|
||||||
|
if (cursor != 0 || (g = sp->getGroup(g->id() + 1)) != nullptr) {
|
||||||
res->head().fset(nullptr,
|
// Use 128-bit integer for left shift, will not overflow
|
||||||
"*2\r\n"
|
cursor <<= Const::ServGroupBits;
|
||||||
"$%d\r\n"
|
cursor |= g->id();
|
||||||
"%s\r\n",
|
|
||||||
n, buf);
|
// Find '*' within buffer boundary
|
||||||
res->body().cut(p - str.data());
|
const char* asteriskPos = p + 1;
|
||||||
|
while (asteriskPos < end && *asteriskPos != '*') {
|
||||||
|
asteriskPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asteriskPos < end) { // Found '*'
|
||||||
|
// Convert 128-bit integer to string
|
||||||
|
char buf[64]; // 128-bit needs at most 39 decimal digits
|
||||||
|
int n = Util::uint128ToString(cursor, buf);
|
||||||
|
|
||||||
|
// Debug log: cursor to be sent to client
|
||||||
|
logDebug("h %d SCAN cursor from server: %s, group: %d, cursor to client: %s",
|
||||||
|
id(), serverCursorBuf, g->id(), buf);
|
||||||
|
|
||||||
|
res->head().fset(nullptr,
|
||||||
|
"*2\r\n"
|
||||||
|
"$%d\r\n"
|
||||||
|
"%s\r\n",
|
||||||
|
n, buf);
|
||||||
|
res->body().cut(asteriskPos - start);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Scan completed, return 0 to client
|
||||||
|
logDebug("h %d SCAN cursor from server: %s, group: %d, cursor to client: 0 (scan complete)",
|
||||||
|
id(), serverCursorBuf, currentGroupId);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Scan completed, return 0 to client
|
|
||||||
logDebug("h %d SCAN cursor from server: %s, group: %d, cursor to client: 0 (scan complete)",
|
|
||||||
id(), serverCursorBuf, currentGroupId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user