Skip to content

About

C++17 hotrod client for Infinispan cluster

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Infinispan Hot Rod Client - C++17

A cross-platform C++17 implementation of the Infinispan Hot Rod protocol client.

πŸŽ‰ Smart client - hash-aware routing, automatic failover, full CRUD + metadata ops, typed error handling and user-decided retry (keyed & keyless), and SASL/SCRAM authentication (SCRAM-SHA-1/256/512).

Quick Start

See the complete working example in examples/quickstart/:

cd examples/quickstart
./start-server.sh        # Start Infinispan 16.2
mkdir build && cd build
cmake .. && make
./quickstart             # Run the example

Example output:

=== Hot Rod C++ Client Quickstart ===
Connecting to Infinispan server...
Connected successfully!

--- PUT Operations ---
PUT: greeting = Hello, Infinispan!
PUT: language = C++17
PUT: version = 1.0.0

--- GET Operations ---
GET: greeting = Hello, Infinispan!
GET: language = C++17
GET: version = 1.0.0

--- REMOVE Operations ---
REMOVE: language deleted successfully

=== Quickstart Complete ===

The quickstart demonstrates:

  • Connecting to Infinispan
  • PUT operations (storing key-value pairs)
  • GET operations (reading values)
  • REMOVE operations (deleting entries)
  • Clean disconnect

A second example, retry.cpp, demonstrates the user-decided retry loop (cache.excluding(e) on a caught HotRodClientException) for both keyed operations and keyless ping.

See examples/quickstart/README.md for full documentation.

Building

Requirements

Build Requirements:

  • C++17 compatible compiler (GCC 7+, Clang 6+, MSVC 19.20+)
  • CMake 3.15+
  • OpenSSL 1.1.1+ or 3.x
  • Google Test (for testing)

Runtime Requirements:

  • Infinispan Server 16.0+ (tested with 16.2)
  • Docker (for integration tests and quickstart example)

Linux (Fedora/RHEL)

# Install dependencies
sudo dnf install cmake gcc-c++ openssl-devel gtest-devel

# Build
mkdir build && cd build
cmake ..
make -j$(nproc)

# Run tests
ctest --output-on-failure

Linux (Ubuntu/Debian)

# Install dependencies
sudo apt install cmake g++ libssl-dev libgtest-dev

# Build
mkdir build && cd build
cmake ..
make -j$(nproc)

# Run tests
ctest --output-on-failure

Windows (PowerShell)

# Install dependencies via vcpkg
vcpkg install openssl gtest

# Build
mkdir build
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=[path-to-vcpkg]/scripts/buildsystems/vcpkg.cmake
cmake --build . --config Release

# Run tests
ctest -C Release --output-on-failure

Testing

Unit Tests (250 tests)

cd build
./unit_tests

# Or via CTest
ctest -R UnitTests --output-on-failure

Integration Tests (92 tests, 19 suites)

Requires Docker to run Infinispan server:

cd build

# Run all integration tests (starts server automatically) β€” representative subset:
./ping_integration_tests
./get_integration_tests
./put_integration_tests
./remove_integration_tests
./topology_integration_tests            # Multi-node cluster tests
./hash_aware_routing_integration_tests  # Smart routing tests
./retryview_integration_tests           # User-decided retry (keyed)
./pingretry_integration_tests           # User-decided retry (keyless ping)

# Or run all via CTest
ctest --output-on-failure

Note: Integration tests use Docker Compose to manage multi-node Infinispan clusters (up to 4 nodes). Tests verify failover, rebalancing, and hash-aware routing.

Status

πŸ“Œ Live status lives in docs/STATUS.md β€” start there after any break. Design rationale is in docs/DECISIONS.md.

Current Progress: Full CRUD (PING/GET/PUT/REMOVE) + SCRAM auth + topology awareness + hash-aware routing + async multiplexing + metadata/version-based operations (Step 10) + typed error handling and user-decided retry, keyed and keyless (Step 11) + Hot Rod URI support (RemoteCache::fromUri, issue #9) β€” all shipped. Next: bulk operations (Step 12) or multiplexing benchmarks. See docs/STATUS.md for live status. Per-step milestone history (frozen at Step 9) is archived at docs/archive/PROGRESS.md.

(Step numbers follow ../hotrod-foundry/ROADMAP.md; docs/STATUS.md is authoritative for which steps are done β€” not any headline count.)

Test Results (verified 2026-10-09):

  • Unit Tests: 250/250 passing βœ…
  • Integration Tests: 92/92 passing βœ… across 19 suites (against live Infinispan via Docker)

Features

Implemented βœ…

  • βœ… Cross-platform support (Linux + Windows)
  • βœ… Wire format primitives (vInt, vLong, strings, byte arrays)
  • βœ… Protocol 4.0 headers (complete spec with all conditional fields)
  • βœ… Client Intelligence 0x03 (HASH_DISTRIBUTION_AWARE)
  • βœ… Hash-aware routing (keys route directly to primary owner)
  • βœ… Automatic failover (primary β†’ backup owners β†’ any server)
  • βœ… Topology awareness (cluster rebalancing, updates)
  • βœ… Consistent hashing (MurmurHash3 x64_32, segment-based routing)
  • βœ… Connection pooling (one connection per server)
  • βœ… Multiplexed connections (concurrent async operations on single connection per server)
  • βœ… Async operations (all operations return std::future for non-blocking execution)
  • βœ… PING operation (server connectivity check)
  • βœ… GET operation (read from cache with failover)
  • βœ… PUT operation (write to cache with lifespan/maxIdle)
  • βœ… REMOVE operation (delete from cache)
  • βœ… Metadata / version-based operations (getWithMetadata, putIfAbsent, replace, containsKey, removeWithVersion, replaceWithVersion) (Step 10)
  • βœ… Typed error handling (HotRodClientException with phase / server status / tried nodes) + isTransient / outcomeUncertain classification (Step 11a)
  • βœ… User-decided retry (cache.excluding(e) bound view) for keyed ops and keyless ping, with automatic before-send failover (Step 11b/11c)
  • βœ… SASL/SCRAM authentication (setAuthentication(...)) β€” end-to-end for the SCRAM family (SCRAM-SHA-1/SCRAM-SHA-256/SCRAM-SHA-512), applied to every connection; see documentation/topics/security.adoc
  • βœ… Hot Rod URI (RemoteCache::fromUri("hotrod://...")) β€” build a client from a connection string (hosts, credentials, sasl_mechanism/client_intelligence/ protocol_version params); hotrod:// only for now (TLS and more in issue #10)
  • βœ… Integration test framework (GoogleTest + Docker + multi-node clusters)

Full CRUD with Smart Routing and Async Operations

// Connect with hash-aware routing
RemoteCache cache("localhost", 11222, "my-cache");
cache.setClientIntelligence(ClientIntelligence::HASH_DISTRIBUTION_AWARE);
cache.connect();

// All operations are async (return std::future) and can run concurrently
// Multiple operations share a single multiplexed connection per server

// CREATE/UPDATE - routes to primary owner
auto putFuture = cache.put(key, value, lifespan, maxIdle);

// READ - automatic failover to backup if primary fails
auto getFuture = cache.get(key);

// DELETE - with automatic failover
auto removeFuture = cache.remove(key);

// PING
auto pingFuture = cache.ping();

// Wait for results when needed
auto result = getFuture.get();  // blocks until complete
if (result.has_value()) {
    ByteArray value = result.value();
}

// Or fire-and-forget for max throughput
for (int i = 0; i < 1000; i++) {
    cache.put(keys[i], values[i]);  // returns immediately, executes concurrently
}

Connect from a Hot Rod URI

// hotrod://[user:password@]host1[:port1][,host2[:port2]...][?k=v&...]
// Returns a configured, not-yet-connected client (RemoteCache owns a mutex, so
// it is non-movable β†’ unique_ptr). Call connect() yourself.
auto cache = RemoteCache::fromUri(
    "hotrod://user:pass@node1:11222,node2:11222"
    "?sasl_mechanism=SCRAM-SHA-256&client_intelligence=hash_distribution_aware",
    "my-cache");
cache->connect();

// v1 supports hotrod:// only; the first host seeds the topology, credentials
// enable SCRAM, and sasl_mechanism/client_intelligence/protocol_version (Java
// "4.0"/"4.1" form) are honoured. Userinfo and query values are percent-decoded
// (RFC 3986), so a reserved character in a password is written encoded β€” e.g. a
// password of p@ss is "...://admin:p%40ss@host". hotrods:// (TLS), timeouts, and
// other parameters throw for now (see issue #10).

Future

πŸ‘‰ The full, authoritative backlog lives in docs/STATUS.md β†’ πŸ“‹ Backlog, and the 1–3 immediate items in ⏭ Next steps. This is just a summary.

  • βœ… Step 10 β€” Metadata / version-based operations (shipped): getWithMetadata, replaceWithVersion, removeWithVersion, putIfAbsent, replace, containsKey
  • βœ… Step 11 β€” Error handling (shipped): ERROR response parsing, typed exception, user-decided retry (keyed + keyless)
  • Step 12 β€” Bulk operations (next): GET_ALL, PUT_ALL, BULK_GET
  • Also: multiplexing benchmarks, TLS/SSL support

Project Structure

cpp17-client/
β”œβ”€β”€ CMakeLists.txt               # Build configuration
β”œβ”€β”€ README.md                    # This file
β”œβ”€β”€ LICENSE                      # Apache 2.0
β”œβ”€β”€ include/hotrod/              # Public API headers
β”‚   β”œβ”€β”€ Types.h                  # Type definitions
β”‚   β”œβ”€β”€ Codec.h                  # Wire format primitives
β”‚   β”œβ”€β”€ HeaderCodec.h            # Protocol 4.0 headers
β”‚   β”œβ”€β”€ Connection.h             # TCP connection
β”‚   β”œβ”€β”€ RemoteCache.h            # High-level API (with hash-aware routing)
β”‚   β”œβ”€β”€ TopologyInfo.h           # Cluster tracking
β”‚   β”œβ”€β”€ ConsistentHash.h         # Smart routing
β”‚   └── MurmurHash3.h            # Hash function
β”œβ”€β”€ src/                         # Implementation
β”‚   β”œβ”€β”€ codec/                   # Encoding/decoding
β”‚   β”œβ”€β”€ transport/               # Network I/O
β”‚   β”œβ”€β”€ topology/                # Cluster tracking
β”‚   β”œβ”€β”€ hash/                    # MurmurHash3 + consistent hashing
β”‚   └── operations/              # Hot Rod operations (with failover)
β”œβ”€β”€ tests/                       # Test suite
β”‚   β”œβ”€β”€ unit/                    # 223 unit tests
β”‚   └── integration/             # 92 integration tests, 19 suites (multi-node clusters)
β”œβ”€β”€ documentation/               # AsciiDoc user guide (index.adoc + topics/)
β”œβ”€β”€ examples/                    # Usage examples
β”‚   └── quickstart/              # Simple GET/PUT/REMOVE + retry + auth examples
β”œβ”€β”€ scripts/                     # Test infrastructure
β”‚   β”œβ”€β”€ start_cluster.sh         # Start multi-node cluster
β”‚   β”œβ”€β”€ add_cluster_node.sh      # Add node dynamically
β”‚   └── remove_cluster_node.sh   # Remove node for failover tests
└── test-configs/                # Server configurations
    β”œβ”€β”€ docker-compose-cluster.yml  # Multi-node setup
    └── infinispan-cluster.xml      # No-auth config

Development

πŸ” Working on this project? Read docs/WORKFLOW.md β€” the per-session workflow (how to re-orient after a break, what to update before you stop, and which protocol sources are authoritative). It's built for intermittent, solo work.

This implementation follows the hotrod-foundry incremental approach:

  1. Test-driven development - Test vectors β†’ Unit tests β†’ Implementation
  2. Java reference - Study Java implementation for each step (MANDATORY) β€” it is the authoritative source for behavior and semantics (what each op does, statuses, edge cases)
  3. Byte-level validation - Compare with test vectors and the Kaitai wire-format schema (authoritative for byte layout); if the two disagree, stop and investigate
  4. Cross-platform - Linux + Windows support required
  5. Infrastructure-first - Steps 0-5 (foundation), then operations

Roadmap

See hotrod-foundry/ROADMAP.md for the complete step-by-step plan.

Java Reference

The authoritative source for protocol behavior and semantics β€” study it first for each step (see workflow above).

References

License

Apache 2.0 (matching Infinispan project)

Contributing

Start with docs/WORKFLOW.md β€” the per-session workflow. In short, following the hotrod-foundry porting guidelines:

  • One step at a time (complete step N before step N+1)
  • Update docs/STATUS.md before you stop each session (next steps + date)
  • Log design decisions in docs/DECISIONS.md as you make them
  • Validate against test vectors
  • Ensure cross-platform compatibility

Implementation Milestones

  • βœ… v0.1.0 (2026-06-11): Foundation complete (Steps 0-5)
  • βœ… v0.2.0 (2026-06-12): PING operation complete (Step 6)
  • βœ… v0.3.0 (2026-06-12): GET operation complete (Step 7)
  • βœ… v0.4.0 (2026-06-12): PUT operation complete (Step 8)
  • βœ… v0.5.0 (2026-06-12): REMOVE operation complete (Step 9) - Full CRUD!
  • βœ… v0.6.0 (2026-06-17): Topology awareness (Step 4)
  • βœ… v0.7.0 (2026-06-17): Hash-aware routing with failover - Smart Client!
  • βœ… v0.8.0 (2026-09-20): Metadata / version-based operations (Step 10)
  • βœ… v0.9.0 (2026-09-25): Typed error handling + user-decided retry, keyed & keyless (Step 11)
  • 🎯 v0.10.0 (upcoming): Bulk operations (Step 12)

Maintained by: rigazilla
Status: Active development
Current Step: Error handling + user-decided retry complete (Step 11, keyed & keyless). Next: bulk operations (Step 12). βœ…

About

C++17 hotrod client for Infinispan cluster

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages