Skip to content

C++ client: add thread-safe SessionPool, enable RPC compression, and harden buffers#17800

Open
SpriCoder wants to merge 4 commits into
masterfrom
cPerformance
Open

C++ client: add thread-safe SessionPool, enable RPC compression, and harden buffers#17800
SpriCoder wants to merge 4 commits into
masterfrom
cPerformance

Conversation

@SpriCoder
Copy link
Copy Markdown
Contributor

Summary

This PR improves the C++ client (iotdb-client/client-cpp) along three axes — concurrency, read/write performance, and safety/correctness. It is split into four logically separate commits.

1. Thread-safe SessionPool (new feature)

A single Session is not safe to use from multiple threads concurrently (it owns one Thrift transport/client). Previously the C++ client had no pooling, forcing callers to either serialize all requests through one session or hand-roll connection management.

  • New SessionPool + SessionPoolBuilder lend each Session to exactly one borrower at a time and reclaim it afterwards, so many application threads can share a bounded set of connections without external locking.
  • getSession() returns an RAII PooledSession handle that returns the session to the pool on scope exit and works with any Session method; a generic execute([](Session&){...}) plus convenience wrappers (insertTablet, insertRecord, executeQueryStatement, …) cover common operations.
  • New sessions are constructed outside the pool lock so a handshake never blocks other borrowers; getSession() blocks up to a configurable timeout when the pool is exhausted.
  • Query results are returned as a PooledSessionDataSet that keeps the session leased until the result set is fully read — necessary because SessionDataSet lazily fetches further blocks over the same connection. Sessions that raise IoTDBConnectionException are evicted instead of recycled.

2. Enable RPC compression that was silently ignored (performance)

Session::open(bool enableRPCCompression) and the builder's enableRPCCompression flag were never propagated to SessionConnection, whose flag was hardcoded to false, so the compact Thrift protocol never took effect. The flag is now threaded from the builder/open() into both the data SessionConnection and the node-discovery NodesSupplier client, reducing bytes on the wire for both reads and writes.

3. Safety / correctness hardening

  • Tablet::addValue formatted out-of-range diagnostics with sprintf into a fixed 100-byte stack buffer; switched to snprintf bounded by sizeof(buffer) to remove the overflow risk.
  • MyStringBuffer::putOrderedByte used str.assign on big-endian hosts, which overwrote the whole buffer on every numeric write and corrupted previously serialized content; changed to str.append to match the little-endian path.

Commits

  1. Wire RPC compression flag through Session to its connections
  2. Use snprintf for Tablet bounds-check error messages
  3. Append big-endian bytes in MyStringBuffer instead of overwriting
  4. Add thread-safe SessionPool to the C++ client

Test plan

  • All changed/new sources compile cleanly against the project's Thrift/Boost headers (g++ -std=c++11 -fsyntax-only, 0 errors); new code conforms to the repo .clang-format (2-space, 100-col).
  • Run the C++ client integration tests against a live IoTDB on 127.0.0.1:6667 (session_tests), including the new [sessionPool] cases: basic borrow/insert/query, concurrent writers, and exhaustion-timeout. These require a running server and were not executed in the authoring environment.

SpriCoder added 4 commits May 31, 2026 11:42
The enableRPCCompression option set via Session::open(bool) or the session
builder was never propagated to SessionConnection, whose flag was hardcoded
to false, so the compact Thrift protocol never took effect. Thread the flag
from the builder/open() into both the data SessionConnection and the
node-discovery NodesSupplier client so compression actually applies.
Tablet::addValue and the OBJECT-value overload formatted out-of-range
diagnostics with sprintf into a fixed 100-byte stack buffer, risking an
overflow. Switch to snprintf bounded by sizeof(buffer) and cast the size_t
arguments to long to match the %ld format.
On big-endian hosts MyStringBuffer::putOrderedByte used str.assign, which
replaced the whole buffer with each numeric write and corrupted previously
serialized content. Use str.append so bytes accumulate, matching the
little-endian path.
Introduce SessionPool and SessionPoolBuilder so multiple threads can share a
bounded set of connections without external locking. A single Session is not
safe to use concurrently, so the pool lends each Session to one borrower at a
time via an RAII PooledSession handle and reclaims it on scope exit. Sessions
are created outside the lock to avoid blocking other borrowers during the
handshake, and getSession() blocks up to a configurable timeout when the pool
is exhausted.

Query results are returned as a PooledSessionDataSet that keeps the Session
leased until the result set is fully read, since SessionDataSet lazily fetches
further blocks over the same connection. Connections that raise
IoTDBConnectionException are evicted rather than recycled. Add integration
tests covering basic borrow/insert/query, concurrent writers, and
exhaustion-timeout behavior.
@sonarqubecloud
Copy link
Copy Markdown

@codecov
Copy link
Copy Markdown

codecov Bot commented May 31, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 40.82%. Comparing base (0848379) to head (6e635c3).

Additional details and impacted files
@@            Coverage Diff            @@
##             master   #17800   +/-   ##
=========================================
  Coverage     40.82%   40.82%           
+ Complexity     2611     2610    -1     
=========================================
  Files          5184     5184           
  Lines        350965   350965           
  Branches      44895    44895           
=========================================
+ Hits         143276   143279    +3     
+ Misses       207689   207686    -3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant