3 This library allows building C++ programs that interact with a Kinetic API implementation. It provides blocking and non-blocking styles of interaction depending on application needs.
7 The library can be built as a static or shared library. For examples of how to include the library in a CMake-based project see the examples repo at [https://github.com/Seagate/kinetic-cpp-examples](https://github.com/Seagate/kinetic-cpp-examples). Applications also need to add the `include/kinetic` directory to the include path and include `kinetic/kinetic.h`.
11 Before creating a connection, first create a `KineticConnectionFactory` using the handy helper method:
13 kinetic::KineticConnectionFactory kinetic_connection_factory = kinetic::NewKineticConnectionFactory();
15 A single `KineticConnectionFactory` can be used to create many connections. Deleting the connection factory won't affect existing connections.
17 Next, create a connection options object to indicate the IP, port, user identity, and so on:
19 kinetic::ConnectionOptions options;
20 options.host = my_host;
21 options.port = my_port;
22 options.user_id = my_user_id;
23 options.hmac_key = my_hmac_key;
25 Finally, open the connection:
27 std::unique_ptr<kinetic::NonblockingKineticConnection> connection;
28 kinetic::KineticStatus status = kinetic_connection_factory.NewNonblockingConnection(options, timeout_in_seconds, connection);
30 *Note*: If the connection needs to be shared between threads, call `NewThreadsafeNonblockingConnection` instead.
32 To check whether the connection succeeded, check the value of `status.ok()`. If it's false, additional error information is available by calling `status.statusCode()` and `status.message()`.
34 The factory can create threadasafe and non-threadsafe variants of blocking and nonblocking clients. Blocking clients can also be created from an existing nonblocking client using the `BlockingKineticClient` constructor which takes a `NonblockingKineticConnection`.
35 The benefit of this approach is that both clients will use the same underyling connection. This is not necessarily threadsafe. If you use a nonblocking and blocking client which use the same underlying connection, then there are no guarantees about which thread is will process callbacks.
37 Performing blocking GET/PUT operations
38 --------------------------------------
39 PUT and GET calls make use of the `kientic::KineticRecord` class, which bundles the value/version/tag/algorithm fourpule allows construction via a series of `shared_ptr` instances (avoiding a copy) or a series of `string`s (avoiding extra typing).
43 blocking_connection->Put(
46 kinetic::IGNORE_VERSION,
47 KineticRecord(value, version, tag, Message_Algorithm_SHA1));
49 Like most operations in the Kinetic C++ client, `Put` returns a `KineticStatus` object that indicates success and provides error information.
51 *Note*: The Kinetic C++ client makes extensive use of `shared_ptr` and `unique_ptr` to make memory transfer and ownership explicit while avoiding unnecessary copies. However, applications that prefer to avoid the complexity of `shared_ptr` and `unique_ptr` can just pass in `std::string` instances and accept the additional overhead.
53 GETting a key works similarly:
55 std::unique_ptr<KineticRecord> record;
56 blocking_connection->Get(key, record);
58 Performing non-blocking GET/PUT operations
59 ------------------------------------------
60 The blocking API is convenient for simplicity or thread-per-connection style designs, but many applications use a non-blocking event-driven design. For these applications, it makes more sense to use a non-blocking API. The Kinetic C++ client's non-blocking API is very similar to the blocking API, with two important differences. First, all methods take an additional callback parameter that will be called once the operation succeeds or fails. Secondly, to actually perform IO the `Run` method needs to be called repeatedly.
62 As a simple example to perform several writes, first create a callback
63 class to receive success and failure messages:
65 // PutCallback definition:
66 class PutCallback : public PutCallbackInterface {
71 void Failure(KineticStatus error) {
72 printf("Dismal failure!\n");
78 // PutCallback instantiation
79 auto callback = make_shared<PutCallback>();
81 Then enqueue a series of operations:
83 auto record = make_shared<KineticRecord>(value, version, tag, Message_Algorithm_SHA1);
84 nonblocking_connection->Put(key1, version, kinetic::IGNORE_VERSION, record, callback);
85 Message_Algorithm_SHA1);
86 nonblocking_connection->Put(key2, version, kinetic::IGNORE_VERSION, record, callback);
87 Message_Algorithm_SHA1);
88 nonblocking_connection->Put(key3, version, kinetic::IGNORE_VERSION, record, callback);
90 Finally, call `Run` repeatedly to actually execute the operations:
92 fd_set read_fds, write_fds;
94 nonblocking_connection->Run(&read_fds, &write_fds, &nfd);
95 while (there_is_work_to_do) {
96 while (select(nfd + 1, &read_fds, &write_fds, NULL, NULL) <= 0);
97 nonblocking_connection->.Run(&read_fds, &write_fds, &num_fds);
100 If desired, other fds can be added to the `fd_set`s so that the `select` call can wait for IO to be ready on fds controlled by the Kinetic API or other parts of the application.
102 GETs work very similarly. First, a callback implementation:
104 class GetCallback : public GetCallbackInterface {
106 void Success(const std::string &key, std::unique_ptr<KineticRecord> record) {
109 void Failure(KineticStatus error) {
116 // GetCallback instantiation
117 auto callback = make_shared<GetCallback>();
119 Next, enqueue some operations:
121 nonblocking_connection->Get(key_1, callback);
122 nonblocking_connection->Get(key_2, callback);
123 nonblocking_connection->Get(key_3, callback);
125 The `Run` loop works exactly the same way as it does for the PUT case. Multiple GET/PUT/management operations can all be enqueued and they will be executed one at a time in order by repeated `Run` calls.