kinetic-c  v0.12.0
Seagate Kinetic Protocol Client Library for C
get_nonblocking.c
Go to the documentation of this file.
1 /*
2 * kinetic-c
3 * Copyright (C) 2015 Seagate Technology.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20 #include "kinetic_client.h"
21 #include "kinetic_types.h"
22 #include "kinetic_semaphore.h"
23 #include <stdlib.h>
24 #include <sys/param.h>
25 #include <openssl/sha.h>
26 #include <pthread.h>
27 
28 typedef struct {
29  KineticSemaphore * sem;
30  KineticStatus status;
31 } GetStatus;
32 
33 static void get_finished(KineticCompletionData* kinetic_data, void* clientData);
34 
35 int main(int argc, char** argv)
36 {
37  (void)argc;
38  (void)argv;
39 
40  // Initialize kinetic-c and configure sessions
41  KineticSession* session;
42  KineticClientConfig clientConfig = {
43  .logFile = "stdout",
44  .logLevel = 1,
45  };
46  KineticClient * client = KineticClient_Init(&clientConfig);
47  if (client == NULL) { return 1; }
48  const char HmacKeyString[] = "asdfasdf";
49  KineticSessionConfig sessionConfig = {
50  .host = "localhost",
51  .port = KINETIC_PORT,
52  .clusterVersion = 0,
53  .identity = 1,
54  .hmacKey = ByteArray_CreateWithCString(HmacKeyString),
55  };
56  KineticStatus status = KineticClient_CreateSession(&sessionConfig, client, &session);
57  if (status != KINETIC_STATUS_SUCCESS) {
58  fprintf(stderr, "Failed connecting to the Kinetic device w/status: %s\n",
60  exit(1);
61  }
62 
63  // some dummy data to PUT
64  uint8_t value_data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
65  ByteBuffer value = ByteBuffer_MallocAndAppend(value_data, sizeof(value_data));
66 
67  // a dummy key
68  uint8_t key_data[] = {0x00, 0x01, 0x02, 0x03, 0x04};
69  ByteBuffer key = ByteBuffer_MallocAndAppend(key_data, sizeof(key_data));
70 
71  // Populate tag with SHA1
72  ByteBuffer tag = ByteBuffer_Malloc(20);
73  uint8_t sha1[20];
74  SHA1(value.array.data, value.bytesUsed, &sha1[0]);
75  ByteBuffer_Append(&tag, sha1, sizeof(sha1));
76 
77  KineticEntry entry = {
78  .key = key,
79  .tag = tag,
80  .algorithm = KINETIC_ALGORITHM_SHA1,
81  .value = value,
82  .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH,
83  };
84 
85  // Do a blocking put to make sure there is something there to read back
86  KineticStatus put_status = KineticClient_Put(session, &entry, NULL);
87 
88  if (put_status != KINETIC_STATUS_SUCCESS) {
89  fprintf(stderr, "Put failed w/status: %s\n", Kinetic_GetStatusDescription(put_status));
90  return 1;
91  }
92 
93  // Create structure to populate with GET status in callback
94  // a semaphore is used to notify the main thread that it's
95  // safe to proceed.
96  GetStatus get_status = {
97  .sem = KineticSemaphore_Create(),
98  .status = KINETIC_STATUS_INVALID,
99  };
100 
101  ByteBuffer getTag = ByteBuffer_Malloc(tag.bytesUsed);
102  ByteBuffer getValue = ByteBuffer_Malloc(value.bytesUsed);
103 
104  // Because I'm passing a pointer to this entry to KineticClient_Put(), this entry must not
105  // go out of scope until the GET completes
106  KineticEntry get_entry = {
107  .key = key,
108  .tag = getTag,
109  .algorithm = KINETIC_ALGORITHM_SHA1,
110  .value = getValue,
111  .force = true,
112  };
113 
114  status = KineticClient_Get(
115  session,
116  &get_entry,
118  .callback = get_finished,
119  .clientData = &get_status,
120  }
121  );
122  if (status != KINETIC_STATUS_SUCCESS) {
123  fprintf(stderr, "Get failed w/status: %s\n", Kinetic_GetStatusDescription(status));
124  return 1;
125  }
126 
127  // Wait for GET to finish
129 
130  if (get_status.status != KINETIC_STATUS_SUCCESS) {
131  fprintf(stderr, "GET failed w/status: %s\n", Kinetic_GetStatusDescription(get_status.status));
132  return 1;
133  }
134 
135  if ((value.bytesUsed == getValue.bytesUsed) &&
136  (memcmp(value.array.data, getValue.array.data, getValue.bytesUsed) != 0)) {
137  fprintf(stderr, "GET completed but returned unexpected value");
138  return 1;
139  }
140  printf("GET completed successfully!\n");
141 
142  // Free malloc'd buffers
143  ByteBuffer_Free(value);
144  ByteBuffer_Free(key);
145  ByteBuffer_Free(tag);
146 
147  ByteBuffer_Free(getValue);
148  ByteBuffer_Free(getTag);
149 
150 
151  // Shutdown client connection and cleanup
153  KineticClient_Shutdown(client);
154 
155  return 0;
156 }
157 
158 static void get_finished(KineticCompletionData* kinetic_data, void* clientData)
159 {
160  GetStatus * get_status = clientData;
161 
162  // Save GET result status
163  get_status->status = kinetic_data->status;
164  // Signal that we're done
165  KineticSemaphore_Signal(get_status->sem);
166 }
ByteBuffer * ByteBuffer_Append(ByteBuffer *buffer, const void *data, size_t len)
Definition: byte_array.c:135
Structure for an embedded ByteArray as a buffer.
Definition: byte_array.h:53
This request is made persistent before returning.
Definition: kinetic_types.h:93
ByteBuffer ByteBuffer_Malloc(size_t size)
Definition: byte_array.c:254
Operation successful.
KineticStatus KineticClient_CreateSession(KineticSessionConfig *const config, KineticClient *const client, KineticSession **session)
Creates a session with the Kinetic Device per specified configuration.
Structure used to specify the configuration for a session.
KineticStatus KineticClient_DestroySession(KineticSession *const session)
Closes the connection to a host.
int main(int argc, char **argv)
ByteArray array
ByteArray holding allocated array w/length = allocated size.
Definition: byte_array.h:54
Closure which can be specified for operations which support asynchronous mode.
Kinetic object instance.
char host[256]
Host name/IP address of Kinetic Device.
void KineticSemaphore_WaitForSignalAndDestroy(KineticSemaphore *sem)
Blocks until the given semaphore is signaled.
const char * Kinetic_GetStatusDescription(KineticStatus status)
Provides a string representation for a KineticStatus code.
Definition: kinetic_types.c:67
#define KINETIC_PORT
Default kinetic port.
Definition: kinetic_types.h:40
void KineticSemaphore_Signal(KineticSemaphore *sem)
Signals KineticSemaphore.
static void get_finished(KineticCompletionData *kinetic_data, void *clientData)
Completion data which will be provided to KineticCompletionClosure for asynchronous operations...
const char * logFile
Path to log file. Specify 'stdout' to log to STDOUT or NULL to disable logging.
ByteBuffer key
Key associated with the object stored on disk.
uint8_t * data
Pointer to an allocated array of data bytes.
Definition: byte_array.h:36
KineticStatus status
Resultant status of the operation.
Status not available (no reponse/status available)
KineticStatus KineticClient_Get(KineticSession *const session, KineticEntry *const entry, KineticCompletionClosure *closure)
Executes a GET operation to retrieve an entry from the Kinetic Device.
KineticStatus
Kinetic status codes.
KineticStatus KineticClient_Put(KineticSession *const session, KineticEntry *const entry, KineticCompletionClosure *closure)
Executes a PUT operation to store/update an entry on the Kinetic Device.
ByteBuffer ByteBuffer_MallocAndAppend(const void *data, size_t len)
Definition: byte_array.c:262
Configuration values for the KineticClient connection.
void KineticClient_Shutdown(KineticClient *const client)
Performs shutdown/cleanup of the kinetic-c client library.
KineticClient * KineticClient_Init(KineticClientConfig *config)
Initializes the Kinetic API and configures logging.
size_t bytesUsed
Reflects the number of bytes used from the array
Definition: byte_array.h:55
KineticSemaphore * KineticSemaphore_Create(void)
Creates a KineticSemaphore.
void ByteBuffer_Free(ByteBuffer buffer)
Definition: byte_array.c:272
ByteArray ByteArray_CreateWithCString(const char *str)
Definition: byte_array.c:38