-
Language:
English
-
Language:
English
11.7. Hot Rod C++ Client
The Hot Rod C++ client enables C++ runtime applications to connect and interact with Red Hat JBoss Data Grid remote servers, and to read or write data to remote caches. The Hot Rod C++ client supports all three levels of client intelligence and is supported on the following platforms:
The Hot Rod C++ client is available as a Technology Preview on 64-bit Windows with Visual Studio 2015.
- Red Hat Enterprise Linux 6, 64-bit
- Red Hat Enterprise Linux 7, 64-bit
11.7.1. Hot Rod C++ Client Formats
The Hot Rod C++ client is available in the following two library formats:
- Static library
- Shared/Dynamic library
Static Library
The static library is statically linked to an application. This increases the size of the final executable. The application is self-contained and it does not need to ship a separate library.
Shared/Dynamic Library
Shared/Dynamic libraries are dynamically linked to an application at runtime. The library is stored in a separate file and can be upgraded separately from the application, without recompiling the application.
Note
This can only happen if the library's major version is equal to the one against which the application was linked at compile time, indicating that it is binary compatible.
11.7.2. Hot Rod C++ Client Prerequisites
The following table details requirements needed to use the Hot Rod C++ Client depending on the underlying OS:
Table 11.79. Hot Rod C++ Client Prerequisites by OS
Operating System | Hot Rod C++ Client Prerequisites |
---|---|
RHEL 6, 64-bit | C++ 03 compiler with support for shared_ptr TR1 (GCC 4.0+) |
RHEL 7, 64-bit | C++ 11 compiler (GCC 4.8.1) |
Windows 7 x64 | C++ 11 compiler (Visual Studio 2015, Microsoft Visual C++ 2013 Redistributable Package for the x64 platform) |
11.7.3. Hot Rod C++ Client Download
The Hot Rod C++ client is included in a separate zip file
jboss-datagrid-<version>-hotrod-cpp-client-<platform>.zip
under Red Hat JBoss Data Grid binaries on the Red Hat Customer Portal at https://access.redhat.com. Download the appropriate Hot Rod C++ client which applies to your operating system.
11.7.4. Utilizing the Protobuf Compiler with the Hot Rod C++ Client
11.7.4.1. Using the Protobuf Compiler in RHEL 7
The C++ Hot Rod client for RHEL 7 ships with the Protobuf compiler included. The following instructions detail using this compiler:
- Extract the
jboss-datagrid-<version>-hotrod-cpp-client-RHEL7-x86_64.zip
locally to the filesystem:unzip jboss-datagrid-<version>-hotrod-cpp-client-RHEL7-x86_64.zip
- Add the included protobuf libraries to the library path:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/jboss-datagrid-<version>-remote-cpp-client-RHEL7-x86_64/lib64
- Compile the desired protobuf files into C++ header and source files:
/path/to/jboss-datagrid-<version>-remote-cpp-client-RHEL7-x86_64/bin/protoc --cpp_out dllexport_decl=HR_PROTO_EXPORT:/path/to/output/ $FILE
Note
HR_PROTO_EXOPRT
is a macro defined within the Hot Rod client code, and will be expanded when the files are subsequently compiled. - The resulting header and source files will be generated in the designated output directory, allowing them to be referenced and compiled as normal with the specific application code.
For additional information on Protobuf refer to Section 17.5, “Protobuf Encoding”.
11.7.4.2. Using the Protobuf Compiler in Windows
The C++ Hot Rod client for Windows ships with the precompiled Hot Rod components along with the Protobuf compiler included. For many users the included components may be used without the need for additional compilation; however, should any .proto files require compiling the following instructions document this process:
- Extract the
jboss-datagrid-<version>-hotrod-cpp-client-WIN-x86_64.zip
locally to the filesystem. - Open a command prompt and navigate to the newly extracted directory.
- Compile the desired protobuf files into C++ header and source files:
bin\protoc --cpp_out dllexport_decl=HR_PROTO_EXPORT:path\to\output\ $FILE
Note
HR_PROTO_EXOPRT
is a macro defined within the Hot Rod client code, and will be expanded when the files are subsequently compiled. - The resulting header and source files will be generated in the designated output directory, allowing them to be referenced and compiled as normal with the specific application code.
For additional information on Protobuf refer to Section 17.5, “Protobuf Encoding”.
11.7.5. Hot Rod C++ Client Configuration
The Hot Rod C++ client interacts with a remote Hot Rod server using the RemoteCache API. To initiate communication with a particular Hot Rod server, configure RemoteCache and choose the specific cache on the Hot Rod server.
Use the ConfigurationBuilder API to configure:
- The initial set of servers to connect to.
- Connection pooling attributes.
- Connection/Socket timeouts and TCP nodelay.
- Hot Rod protocol version.
Sample C++ main executable file configuration
The following example shows how to use the ConfigurationBuilder to configure a RemoteCacheManager
and how to obtain the default remote cache:
Example 11.6. SimpleMain.cpp
#include "infinispan/hotrod/ConfigurationBuilder.h" #include "infinispan/hotrod/RemoteCacheManager.h" #include "infinispan/hotrod/RemoteCache.h" #include <stdlib.h> using namespace infinispan::hotrod; int main(int argc, char** argv) { ConfigurationBuilder b; b.addServer().host("127.0.0.1").port(11222); RemoteCacheManager cm(builder.build()); RemoteCache<std::string, std::string> cache = cm.getCache<std::string, std::string>(); return 0; }
11.7.6. Hot Rod C++ Client Asynchronous API
The Hot Rod C++ client offers asynchronous versions of many of the synchronous methods, allowing non-blocking methods for interacting with remote caches.
Important
Asynchronous methods are a Technology Preview feature of the Hot Rod C++ client in JBoss Data Grid 7.0.0.
These methods follow the same naming convention as the synchronous methods, except that
Async
is appended to the end of each method. Asynchronous methods return a std::future
containing the result of the operation. If a method were to return a std::string
, instead it will return a std::future < std::string* >
A list of asynchronous methods are below:
getAsync
putAsync
putAllAsync
replaceWithVersionAsync
Example 11.7. Hot Rod C++ Asynchronous API Example
The following example demonstrates using these methods:
#include "infinispan/hotrod/ConfigurationBuilder.h" #include "infinispan/hotrod/RemoteCacheManager.h" #include "infinispan/hotrod/RemoteCache.h" #include "infinispan/hotrod/Version.h" #include "infinispan/hotrod/JBasicMarshaller.h" #include <iostream> #include <thread> #include <future> using namespace infinispan::hotrod; int main(int argc, char** argv) { ConfigurationBuilder builder; builder.addServer().host(argc > 1 ? argv[1] : "127.0.0.1").port(argc > 2 ? atoi(argv[2]) : 11222).protocolVersion(Configuration::PROTOCOL_VERSION_24); RemoteCacheManager cacheManager(builder.build(), false); auto *km = new BasicMarshaller<std::string>(); auto *vm = new BasicMarshaller<std::string>(); auto cache = cacheManager.getCache<std::string, std::string>(km, &Marshaller<std::string>::destroy, vm, &Marshaller<std::string>::destroy ); cacheManager.start(); std::string ak1("asyncK1"); std::string av1("asyncV1"); std::string ak2("asyncK2"); std::string av2("asyncV2"); cache.clear(); // Put ak1,av1 in async thread std::future<std::string*> future_put= cache.putAsync(ak1,av1); // Get the value in this thread std::string* arv1= cache.get(ak1); // Now wait for put completion future_put.wait(); // All is synch now std::string* arv11= cache.get(ak1); if (!arv11 || arv11->compare(av1)) { std::cout << "fail: expected " << av1 << "got " << (arv11 ? *arv11 : "null") << std::endl; return 1; } // Read ak1 again, but in async way and test that the result is the same std::future<std::string*> future_ga= cache.getAsync(ak1); std::string* arv2= future_ga.get(); if (!arv2 || arv2->compare(av1)) { std::cerr << "fail: expected " << av1 << " got " << (arv2 ? *arv2 : "null") << std::endl; return 1; } // Now user pass a simple lambda func that set a flag to true when the put completes bool flag=false; std::future<std::string*> future_put1= cache.putAsync(ak2,av2,0,0,[&] (std::string *v){flag=true; return v;}); // The put is not completed here so flag must be false if (flag) { std::cerr << "fail: expected false got true" << std::endl; return 1; } // Now wait for put completion future_put1.wait(); // The user lambda must be executed so flag must be true if (!flag) { std::cerr << "fail: expected true got false" << std::endl; return 1; } // Same test for get flag=false; // Now user pass a simple lambda func that set a flag to true when the put completes std::future<std::string*> future_get1= cache.getAsync(ak2,[&] (std::string *v){flag=true; return v;}); // The get is not completed here so flag must be false if (flag) { std::cerr << "fail: expected false got true" << std::endl; return 1; } // Now wait for get completion future_get1.wait(); if (!flag) { std::cerr << "fail: expected true got false" << std::endl; return 1; } std::string* arv3= future_get1.get(); if (!arv3 || arv3->compare(av2)) { std::cerr << "fail: expected " << av2 << " got " << (arv3 ? *arv3 : "null") << std::endl; return 1; } cacheManager.stop(); }
11.7.7. Hot Rod C++ Client API
The RemoteCacheManager is a starting point to obtain a reference to a RemoteCache. The RemoteCache API can interact with a remote Hot Rod server and the specific cache on that server.
Using the RemoteCache reference obtained in the previous example, it is possible to put, get, replace and remove values in a remote cache. It is also possible to perform bulk operations, such as retrieving all of the keys, and clearing the cache.
When a RemoteCacheManager is stopped, all resources in use are released.
Example 11.8. SimpleMain.cpp
RemoteCache<std::string, std::string> rc = cm.getCache<std::string, std::string>(); std::string k1("key13"); std::string v1("boron"); // put rc.put(k1, v1); std::auto_ptr<std::string> rv(rc.get(k1)); rc.putIfAbsent(k1, v1); std::auto_ptr<std::string> rv2(rc.get(k1)); std::map<HR_SHARED_PTR<std::string>,HR_SHARED_PTR<std::string> > map = rc.getBulk(0); std::cout << "getBulk size" << map.size() << std::endl; .. . cm.stop();