void* store_data(void* args) { write_args* thread_args = (write_args*)args; KineticEntry* entry = &(thread_args->entry); int32_t objIndex; for (objIndex = 0; ByteBuffer_BytesRemaining(thread_args->data) > 0; objIndex++) { // Configure meta-data char keySuffix[8]; snprintf(keySuffix, sizeof(keySuffix), "%02d", objIndex); entry->key.bytesUsed = strlen(thread_args->keyPrefix); ByteBuffer_AppendCString(&entry->key, keySuffix); entry->synchronization = KINETIC_SYNCHRONIZATION_WRITEBACK; // Prepare the next chunk of data to store ByteBuffer_AppendArray(&entry->value, ByteBuffer_Consume(&thread_args->data, KINETIC_OBJ_SIZE)); // Store the data slice KineticStatus status = KineticClient_Put(thread_args->session, entry, NULL); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Failed writing entry %d to disk w/status: %s", objIndex+1, Kinetic_GetStatusDescription(status)); return (void*)NULL; } } printf("File stored successfully to Kinetic device across %d entries!\n", objIndex); return (void*)NULL; }
void setUp(void) { SystemTestSetup(1, false); uint8_t version_data[DEFAULT_SIZE], tag_data[DEFAULT_SIZE]; ByteBuffer version_buffer, tag_buffer; version_buffer = ByteBuffer_CreateAndAppendCString(version_data, sizeof(version_data), "v1.0"); tag_buffer = ByteBuffer_CreateAndAppendCString(tag_data, sizeof(tag_data), "SomeTagValue"); ByteBuffer key_buffers[TOTAL_PUT_KEYS]; ByteBuffer value_buffers[TOTAL_PUT_KEYS]; unsigned int i; for (i=0; i<TOTAL_PUT_KEYS; i++) { key_buffers[i] = generate_entry_key_by_index(i); printf("key: %s", (char *)key_buffers[i].array.data); value_buffers[i] = generate_entry_value_by_index(i); KineticEntry putEntry = { .key = key_buffers[i], .tag = tag_buffer, .newVersion = version_buffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = value_buffers[i], .force = true, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; KineticStatus status = KineticClient_Put(Fixture.session, &putEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); ByteBuffer_Free(key_buffers[i]); ByteBuffer_Free(value_buffers[i]); } } void tearDown(void) { SystemTestShutDown(); } void test_media_scan_should_succeed_for_existing_key_range(void) { KineticMediaScan_Operation mediascan_operation = {"my_key 1","my_key 5", true, true}; KineticCommand_Priority priority = PRIORITY_NORMAL; KineticStatus status = KineticAdminClient_MediaScan(Fixture.session, &mediascan_operation, priority); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); }
void test_KineticClient_Put_should_execute_PUT_operation(void) { ByteArray value = ByteArray_CreateWithCString("Four score, and seven years ago"); KineticEntry entry = {.value = ByteBuffer_CreateWithArray(value)}; KineticOperation operation; operation.session = &Session; KineticAllocator_NewOperation_ExpectAndReturn(&Session, &operation); KineticBuilder_BuildPut_ExpectAndReturn(&operation, &entry, KINETIC_STATUS_SUCCESS); KineticController_ExecuteOperation_ExpectAndReturn(&operation, NULL, KINETIC_STATUS_VERSION_MISMATCH); KineticStatus status = KineticClient_Put(&Session, &entry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_VERSION_MISMATCH, status); }
void* kinetic_put(void* kinetic_arg) { struct kinetic_thread_arg* arg = kinetic_arg; KineticEntry* entry = &(arg->entry); int32_t objIndex = 0; while (ByteBuffer_BytesRemaining(arg->data) > 0) { // Configure meta-data char keySuffix[8]; snprintf(keySuffix, sizeof(keySuffix), "_%02d", objIndex); entry->key.bytesUsed = arg->keyPrefixLength; ByteBuffer_AppendCString(&entry->key, keySuffix); // Move dbVersion back to newVersion, since successful PUTs do this // in order to sync with the actual entry on disk if (entry->newVersion.array.data == NULL) { entry->newVersion = entry->dbVersion; entry->dbVersion = BYTE_BUFFER_NONE; } // Prepare the next chunk of data to store ByteBuffer_AppendArray( &entry->value, ByteBuffer_Consume( &arg->data, MIN(ByteBuffer_BytesRemaining(arg->data), KINETIC_OBJ_SIZE) ) ); // Store the data slice LOGF("Storing a data slice (%u bytes)", entry->value.bytesUsed); KineticStatus status = KineticClient_Put(arg->sessionHandle, entry); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); LOGF("KineticClient put to disk success, ip:%s", arg->ip); objIndex++; } return (void*)0; }
void store_data(write_args* args) { KineticEntry* entry = &(args->entry); int32_t objIndex = 0; while (ByteBuffer_BytesRemaining(args->data) > 0) { // Configure entry meta-data ByteBuffer_Reset(&entry->key); ByteBuffer_AppendCString(&entry->key, args->keyPrefix); char keySuffix[8]; snprintf(keySuffix, sizeof(keySuffix), "%02d", objIndex); ByteBuffer_AppendCString(&entry->key, keySuffix); // Prepare entry with the next object to store ByteBuffer_Reset(&entry->value); ByteBuffer_AppendArray( &entry->value, ByteBuffer_Consume( &args->data, MIN(ByteBuffer_BytesRemaining(args->data), KINETIC_OBJ_SIZE)) ); // Store the object KineticStatus status = KineticClient_Put(args->session, entry, NULL); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Kinetic PUT of object %d to host %s failed w/ status: %s\n", objIndex, args->ip, Kinetic_GetStatusDescription(status)); exit(-1); } objIndex++; } printf("File stored on Kinetic Device across %d entries\n", objIndex); }
void test_Flush_should_flush_pending_PUTs_and_DELETEs(void) { // Arguments shared between entries uint8_t TagData[1024]; ByteBuffer tagBuffer = ByteBuffer_CreateAndAppendCString(TagData, sizeof(TagData), "tag_val"); uint8_t key1[10]; ByteBuffer keyBuffer1 = ByteBuffer_CreateAndAppendCString(key1, sizeof(key1), "key1"); uint8_t value1[10]; ByteBuffer valueBuffer1 = ByteBuffer_CreateAndAppendCString(value1, sizeof(value1), "value1"); uint8_t key2[10]; ByteBuffer keyBuffer2 = ByteBuffer_CreateAndAppendCString(key2, sizeof(key2), "key2"); uint8_t value2[10]; ByteBuffer valueBuffer2 = ByteBuffer_CreateAndAppendCString(value2, sizeof(value2), "value2"); // Do a blocking PUT ("key1" => "value1") so we can delete it later KineticEntry Entry = (KineticEntry) { .key = keyBuffer1, .tag = tagBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = valueBuffer1, .synchronization = KINETIC_SYNCHRONIZATION_WRITEBACK, .force = true, }; KineticStatus status = KineticClient_Put(Fixture.session, &Entry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); Entry = (KineticEntry) { .key = keyBuffer2, .tag = tagBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = valueBuffer2, .synchronization = KINETIC_SYNCHRONIZATION_WRITEBACK, .force = true, }; status = KineticClient_Put(Fixture.session, &Entry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); // Do an async DELETE so we can flush to complete it KineticEntry deleteEntry = { .key = keyBuffer1, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; KineticCompletionClosure no_op_closure = { .callback = &no_op_callback, }; status = KineticClient_Delete(Fixture.session, &deleteEntry, &no_op_closure); /* Now do a blocking flush and confirm that (key1,value1) has been * DELETEd and (key2,value2) have been PUT. */ status = KineticClient_Flush(Fixture.session, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); // GET key1 --> expect NOT FOUND KineticEntry getEntry1 = { .key = keyBuffer1, .tag = tagBuffer, .value = valueBuffer1, }; status = KineticClient_Get(Fixture.session, &getEntry1, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_NOT_FOUND, status); // GET key2 --> present KineticEntry getEntry2 = { .key = keyBuffer2, .tag = tagBuffer, .value = valueBuffer2, }; status = KineticClient_Get(Fixture.session, &getEntry2, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); }
void setUp(void) { SystemTestSetup(0, true); KeyBuffer = ByteBuffer_CreateAndAppendCString(KeyData, sizeof(KeyData), strKey); ExpectedKeyBuffer = ByteBuffer_CreateAndAppendCString(ExpectedKeyData, sizeof(ExpectedKeyData), strKey); TagBuffer = ByteBuffer_CreateAndAppendCString(TagData, sizeof(TagData), "SomeTagValue"); ExpectedTagBuffer = ByteBuffer_CreateAndAppendCString(ExpectedTagData, sizeof(ExpectedTagData), "SomeTagValue"); TestValue = ByteArray_CreateWithCString("lorem ipsum... blah blah blah... etc."); ValueBuffer = ByteBuffer_CreateAndAppendArray(ValueData, sizeof(ValueData), TestValue); // Setup to write some test data KineticEntry putEntry = { .key = KeyBuffer, .tag = TagBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = ValueBuffer, .force = true, .synchronization = KINETIC_SYNCHRONIZATION_FLUSH, }; KineticStatus status = KineticClient_Put(Fixture.session, &putEntry, NULL); if (status != KINETIC_STATUS_SUCCESS) { failing = true; TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); } // Validate the object exists initially KineticEntry getEntry = { .key = KeyBuffer, .tag = TagBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = ValueBuffer, .force = true, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; status = KineticClient_Get(Fixture.session, &getEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL_ByteArray(putEntry.key.array, getEntry.key.array); TEST_ASSERT_EQUAL_ByteArray(putEntry.tag.array, getEntry.tag.array); TEST_ASSERT_EQUAL(putEntry.algorithm, getEntry.algorithm); TEST_ASSERT_EQUAL_ByteBuffer(putEntry.value, getEntry.value); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); // Set the erase PIN to something non-empty strcpy(NewPinData, SESSION_PIN); OldPin = ByteArray_Create(OldPinData, 0); NewPin = ByteArray_Create(NewPinData, strlen(NewPinData)); status = KineticAdminClient_SetErasePin(Fixture.adminSession, OldPin, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); } void tearDown(void) { KineticStatus status = KINETIC_STATUS_INVALID; if (failing) { return; } // Validate the object no longer exists KineticEntry regetEntryMetadata = { .key = KeyBuffer, .tag = TagBuffer, .metadataOnly = true, }; status = KineticClient_Get(Fixture.session, ®etEntryMetadata, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_NOT_FOUND, status); TEST_ASSERT_ByteArray_EMPTY(regetEntryMetadata.value.array); SystemTestShutDown(); } void test_SecureErase_should_erase_device_contents(void) { KineticStatus status = KineticAdminClient_SecureErase(Fixture.adminSession, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); } void test_InstantErase_should_erase_device_contents(void) { KineticStatus status = KineticAdminClient_InstantErase(Fixture.adminSession, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); }
void setUp(void) { NewPinSet = false; Locked = false; SystemTestSetup(1, true); KeyBuffer = ByteBuffer_CreateAndAppendCString(KeyData, sizeof(KeyData), strKey); ExpectedKeyBuffer = ByteBuffer_CreateAndAppendCString(ExpectedKeyData, sizeof(ExpectedKeyData), strKey); TagBuffer = ByteBuffer_CreateAndAppendCString(TagData, sizeof(TagData), "SomeTagValue"); ExpectedTagBuffer = ByteBuffer_CreateAndAppendCString(ExpectedTagData, sizeof(ExpectedTagData), "SomeTagValue"); TestValue = ByteArray_CreateWithCString("lorem ipsum... blah blah blah... etc."); ValueBuffer = ByteBuffer_CreateAndAppendArray(ValueData, sizeof(ValueData), TestValue); // Setup to write some test data KineticEntry putEntry = { .key = KeyBuffer, .tag = TagBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = ValueBuffer, .force = true, .synchronization = KINETIC_SYNCHRONIZATION_FLUSH, }; KineticStatus status = KineticClient_Put(Fixture.session, &putEntry, NULL); // Validate the object exists initially KineticEntry getEntry = { .key = KeyBuffer, .tag = TagBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = ValueBuffer, .force = true, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; status = KineticClient_Get(Fixture.session, &getEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL_ByteArray(putEntry.key.array, getEntry.key.array); TEST_ASSERT_EQUAL_ByteArray(putEntry.tag.array, getEntry.tag.array); TEST_ASSERT_EQUAL(putEntry.algorithm, getEntry.algorithm); TEST_ASSERT_EQUAL_ByteBuffer(putEntry.value, getEntry.value); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); // Set the erase PIN to something non-empty strcpy(NewPinData, SESSION_PIN); OldPin = ByteArray_Create(OldPinData, 0); NewPin = ByteArray_Create(NewPinData, strlen(NewPinData)); status = KineticAdminClient_SetLockPin(Fixture.adminSession, OldPin, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); NewPinSet = true; } void tearDown(void) { KineticStatus status; // Unlock if for some reason we are still locked in order to // prevent the device from staying in a locked/unusable state if (Locked) { status = KineticAdminClient_UnlockDevice(Fixture.adminSession, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); Locked = false; } // Set the lock PIN back to empty if (NewPinSet) { status = KineticAdminClient_SetLockPin(Fixture.adminSession, NewPin, OldPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); NewPinSet = false; } SystemTestShutDown(); } void test_KineticAdmin_should_lock_and_unlock_a_device(void) { KineticStatus status; status = KineticAdminClient_LockDevice(Fixture.adminSession, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); Locked = true; /* Currently, the device appears to just hang up on us rather than * returning DEVICE_LOCKED (unlike the simulator). Some sort of * command here to confirm that the device lock succeeded would * be a better test. We need to check if the drive has another * interface that exposes this. */ if (SystemTestIsUnderSimulator()) { // Validate the object cannot being accessed while locked KineticEntry getEntry = { .key = KeyBuffer, .tag = TagBuffer, .value = ValueBuffer, .force = true, }; status = KineticClient_Get(Fixture.session, &getEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_DEVICE_LOCKED, status); } status = KineticAdminClient_UnlockDevice(Fixture.adminSession, NewPin); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); Locked = false; }
status = KineticAdminClient_CreateSession(&peerAdminConfig, client, &peerAdminSession); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); // Create some test entries to have content to copy TagBuffer = ByteBuffer_Create(dummyTagData, sizeof(dummyTagData), sizeof(dummyTagData)); Key1Buffer = ByteBuffer_Create(key1Data, sizeof(key1Data), sizeof(key1Data)); Value1Buffer = ByteBuffer_Create(value1Data, sizeof(value1Data), sizeof(value1Data)); KineticEntry putEntry1 = { .key = Key1Buffer, .tag = TagBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = Value1Buffer, .force = true, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; status = KineticClient_Put(session, &putEntry1, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); Key2Buffer = ByteBuffer_Create(key2Data, sizeof(key2Data), sizeof(key2Data)); Value2Buffer = ByteBuffer_Create(value2Data, sizeof(value2Data), sizeof(value2Data)); KineticEntry putEntry2 = { .key = Key2Buffer, .tag = TagBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = Value2Buffer, .force = true, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; status = KineticClient_Put(session, &putEntry2, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); ReadValueBuffer = ByteBuffer_Create(readValueData, sizeof(readValueData), 0);
static void do_put_and_getkeyrange(KineticSession * const session) { for (int i = 0; i < 5; i++) { char key[] = "keyX"; key[3] = '0' + i; ByteBuffer put_key_buf = ByteBuffer_MallocAndAppend(key, strlen(key)); uint8_t value[] = "valueX"; value[5] = '0' + i; ByteBuffer put_value_buf = ByteBuffer_MallocAndAppend(value, sizeof(value)); /* Populate tag with SHA1 of value */ ByteBuffer put_tag_buf = ByteBuffer_Malloc(20); uint8_t sha1[20]; SHA1(put_value_buf.array.data, put_value_buf.bytesUsed, &sha1[0]); ByteBuffer_Append(&put_tag_buf, sha1, sizeof(sha1)); KineticEntry put_entry = { .key = put_key_buf, .value = put_value_buf, .tag = put_tag_buf, .algorithm = KINETIC_ALGORITHM_SHA1, /* Set sync to WRITETHROUGH, which will wait to complete * until the drive has persistend the write. (WRITEBACK * returns as soon as the drive has buffered the write.) */ .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; /* Put "keyX" => "valueX", where 'X' is 0..4. * This will block, because the callback field (arg 3) is NULL. */ KineticStatus status = KineticClient_Put(session, &put_entry, NULL); printf("Put status: %s\n", Kinetic_GetStatusDescription(status)); ByteBuffer_Free(put_key_buf); ByteBuffer_Free(put_value_buf); ByteBuffer_Free(put_tag_buf); } const size_t max_key_count = 5; const size_t max_key_length = 64; uint8_t first_key[max_key_length]; uint8_t last_key[max_key_length]; KineticKeyRange range = { .startKey = ByteBuffer_CreateAndAppendCString(first_key, sizeof(first_key), "key"), .endKey = ByteBuffer_CreateAndAppendCString(last_key, sizeof(last_key), "key\xFF"), .startKeyInclusive = true, .endKeyInclusive = true, .maxReturned = max_key_count, }; uint8_t key_mem[max_key_count][max_key_length]; memset(key_mem, 0, sizeof(key_mem)); ByteBuffer key_buffers[max_key_count]; for (size_t i = 0; i < max_key_count; i++) { key_buffers[i] = ByteBuffer_Create(&key_buffers[i], max_key_length, 0); } ByteBufferArray keys = { .buffers = key_buffers, .count = max_key_count, }; /* Request the key range as specified in &range, populating the keys in &keys. */ KineticStatus status = KineticClient_GetKeyRange(session, &range, &keys, NULL); printf("GetKeyRange status: %s\n", Kinetic_GetStatusDescription(status)); if (status == KINETIC_STATUS_SUCCESS) { for (size_t i = 0; i < max_key_count; i++) { printf("%zd: %s\n", i, key_buffers[i].array.data); } } /* No cleanup necessary */ } int main(int argc, char** argv) { (void)argc; (void)argv; // Initialize kinetic-c and configure sessions KineticSession* session; KineticClientConfig clientConfig = { .logFile = "stdout", .logLevel = 1, }; KineticClient * client = KineticClient_Init(&clientConfig); if (client == NULL) { return 1; } const char HmacKeyString[] = "asdfasdf"; KineticSessionConfig sessionConfig = { .host = "localhost", .port = KINETIC_PORT, .clusterVersion = 0, .identity = 1, .hmacKey = ByteArray_CreateWithCString(HmacKeyString), }; KineticStatus status = KineticClient_CreateSession(&sessionConfig, client, &session); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Failed connecting to the Kinetic device w/status: %s\n", Kinetic_GetStatusDescription(status)); exit(1); } do_put_and_getkeyrange(session); // Shutdown client connection and cleanup KineticClient_DestroySession(session); KineticClient_Shutdown(client); return 0; }
KineticStatus ExecuteOperation( struct UtilConfig * cfg) { KineticStatus status = KINETIC_STATUS_INVALID; KineticLogInfo * logInfo; ByteArray tmpArray; switch (cfg->opID) { case OPT_NOOP: status = KineticClient_NoOp(cfg->session); if (status == KINETIC_STATUS_SUCCESS) { printf("NoOp operation completed successfully." " Kinetic Device is alive and well!\n"); } break; case OPT_PUT: status = KineticClient_Put(cfg->session, &cfg->entry, NULL); if (status == KINETIC_STATUS_SUCCESS) { printf("Put operation completed successfully." " Your data has been stored!\n"); PrintEntry(&cfg->entry); } break; case OPT_GET: status = KineticClient_Get(cfg->session, &cfg->entry, NULL); if (status == KINETIC_STATUS_SUCCESS) { printf("Get executed successfully.\n"); PrintEntry(&cfg->entry); } break; case OPT_GETNEXT: status = KineticClient_GetNext(cfg->session, &cfg->entry, NULL); if (status == KINETIC_STATUS_SUCCESS) { printf("GetNext executed successfully.\n"); PrintEntry(&cfg->entry); } break; case OPT_GETPREVIOUS: status = KineticClient_GetPrevious(cfg->session, &cfg->entry, NULL); if (status == KINETIC_STATUS_SUCCESS) { printf("GetPrevious executed successfully.\n"); PrintEntry(&cfg->entry); } break; case OPT_DELETE: status = KineticClient_Delete(cfg->session, &cfg->entry, NULL); if (status == KINETIC_STATUS_SUCCESS) { printf("Delete executed successfully. The entry has been destroyed!\n"); PrintEntry(&cfg->entry); } break; case OPT_GETLOG: status = KineticAdminClient_GetLog(cfg->adminSession, cfg->logType, &logInfo, NULL); if (status == KINETIC_STATUS_SUCCESS) { printf("GetLog executed successfully.\n" "The device log info has been retrieved!\n"); PrintLogInfo(cfg->logType, logInfo); } break; case OPT_GETDEVICESPECIFICLOG: if (strlen(cfg->deviceLogName) == 0) { fprintf(stderr, "Device-specific log type requires '--devicelogname' to be set!\n"); exit(1); } tmpArray.data = (uint8_t*)cfg->deviceLogName; tmpArray.len = strlen(cfg->deviceLogName); status = KineticAdminClient_GetDeviceSpecificLog(cfg->adminSession, tmpArray, &logInfo, NULL); if (status == KINETIC_STATUS_SUCCESS) { printf("GetDeviceSpecificLog executed successfully." "The device-specific device log info has been retrieved!\n"); printf("Device-Specific Log Info:\n"); char* dev = calloc(1, logInfo->device->name.len + 1); memcpy(dev, logInfo->device->name.data, logInfo->device->name.len); printf(" %s\n", dev); free(dev); } else if (status == KINETIC_STATUS_NOT_FOUND) { fprintf(stderr, "The specified device-specific log '%s' was not found on the device!\n", cfg->deviceLogName); status = KINETIC_STATUS_SUCCESS; } break; case OPT_SETERASEPIN: status = KineticAdminClient_SetErasePin(cfg->adminSession, ByteArray_Create(cfg->pin, strlen(cfg->pin)), ByteArray_Create(cfg->newPin, strlen(cfg->newPin))); if (status == KINETIC_STATUS_SUCCESS) { printf("SetErasePin executed successfully.\n" "The kinetic device erase pin has been changed!\n"); } break; case OPT_INSTANTERASE: status = KineticAdminClient_InstantErase(cfg->adminSession, ByteArray_Create(cfg->pin, strlen(cfg->pin))); if (status == KINETIC_STATUS_SUCCESS) { printf("InstantErase executed successfully.\n" "The kinetic device has been erased!\n"); } break; case OPT_SECUREERASE: status = KineticAdminClient_SecureErase(cfg->adminSession, ByteArray_Create(cfg->pin, strlen(cfg->pin))); if (status == KINETIC_STATUS_SUCCESS) { printf("SecureErase executed successfully.\n" "The kinetic device has been erased!\n"); } break; case OPT_SETLOCKPIN: status = KineticAdminClient_SetLockPin(cfg->adminSession, ByteArray_Create(cfg->pin, strlen(cfg->pin)), ByteArray_Create(cfg->newPin, strlen(cfg->newPin))); if (status == KINETIC_STATUS_SUCCESS) { printf("SetLockPin executed successfully.\n" "The kinetic device lock/unlock pin has been changed!\n"); } break; case OPT_LOCKDEVICE: status = KineticAdminClient_LockDevice(cfg->adminSession, ByteArray_Create(cfg->pin, strlen(cfg->pin))); if (status == KINETIC_STATUS_SUCCESS) { printf("LockDevice executed successfully.\n" "The kinetic device is now locked!\n"); } break; case OPT_UNLOCKDEVICE: status = KineticAdminClient_UnlockDevice(cfg->adminSession, ByteArray_Create(cfg->pin, strlen(cfg->pin))); if (status == KINETIC_STATUS_SUCCESS) { printf("UnlockDevice executed successfully.\n" "The kinetic device is now unlocked!\n"); } break; case OPT_SETCLUSTERVERSION: status = KineticAdminClient_SetClusterVersion(cfg->adminSession, cfg->newClusterVersion); if (status == KINETIC_STATUS_SUCCESS) { printf("SetClusterVersion executed successfully.\n" "The kinetic device's cluster version has been updated!\n"); } break; case OPT_SETACL: status = KineticAdminClient_SetACL(cfg->adminSession, cfg->file); if (status == KINETIC_STATUS_SUCCESS) { printf("SetACL executed successfully.\n" "The kinetic device ACLs have been replaced!\n"); } break; case OPT_UPDATEFIRMWARE: status = KineticAdminClient_UpdateFirmware(cfg->session, cfg->file); if (status == KINETIC_STATUS_SUCCESS) { printf("SecureErase executed successfully.\n" "The kinetic device has been restored to empty status!\n"); } break; default: fprintf(stderr, "Specified operation '%d' is invalid!\n", (int)cfg->opID); exit(-1); }; // Print out status code description if operation was not successful if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "\nERROR: Operation '%s' failed with status '%s'\n", GetOptString(cfg->opID), Kinetic_GetStatusDescription(status)); } return status; }
static bool add_keys(int count) { static const ssize_t sz = 10; char key_buf[sz]; char tag_buf[sz]; char value_buf[sz]; for (int i = 0; i < count; i++) { KineticEntry entry = { .key = ByteBuffer_CreateAndAppendFormattedCString(key_buf, sz, "key_%d", i), .tag = ByteBuffer_CreateAndAppendFormattedCString(tag_buf, sz, "tag_%d", i), .value = ByteBuffer_CreateAndAppendFormattedCString(value_buf, sz, "val_%d", i), .algorithm = KINETIC_ALGORITHM_SHA1, .force = true, }; KineticStatus status = KineticClient_Put(Fixture.session, &entry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); } return true; } typedef enum { CMD_NEXT, CMD_PREVIOUS } GET_CMD; static void compare_against_offset_key(GET_CMD cmd, bool metadataOnly) { static const ssize_t sz = 10; char key_buf[sz]; char tag_buf[sz]; char value_buf[sz]; char key_exp_buf[sz]; char value_exp_buf[sz]; const int count = 3; TEST_ASSERT_TRUE(add_keys(count)); /* add keys [key_X -> test_X] */ int low = 0; int high = count; int8_t offset = 0; switch (cmd) { case CMD_NEXT: low = 1; offset = -1; break; case CMD_PREVIOUS: high = count - 1; offset = +1; break; default: TEST_ASSERT(false); } for (int i = low; i < high; i++) { ByteBuffer keyBuffer = ByteBuffer_CreateAndAppendFormattedCString(key_buf, sz, "key_%d", i + offset); ByteBuffer tagBuffer = ByteBuffer_CreateAndAppendFormattedCString(tag_buf, sz, "tag_%d", i + offset); ByteBuffer valueBuffer = ByteBuffer_Create(value_buf, sz, 0); printf("KEY '%s'\n", key_buf); KineticEntry entry = { .key = keyBuffer, .tag = tagBuffer, .value = valueBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, .metadataOnly = metadataOnly, }; KineticStatus status = KINETIC_STATUS_INVALID; switch (cmd) { case CMD_NEXT: status = KineticClient_GetNext(Fixture.session, &entry, NULL); break; case CMD_PREVIOUS: status = KineticClient_GetPrevious(Fixture.session, &entry, NULL); break; default: TEST_ASSERT(false); } TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); ByteBuffer expectedKeyBuffer = ByteBuffer_CreateAndAppendFormattedCString(key_exp_buf, sz, "key_%d", i); ByteBuffer expectedValueBuffer = ByteBuffer_CreateAndAppendFormattedCString(value_exp_buf, sz, "val_%d", i); TEST_ASSERT_EQUAL_ByteBuffer(expectedKeyBuffer, entry.key); if (!metadataOnly) { TEST_ASSERT_EQUAL_ByteBuffer(expectedValueBuffer, entry.value); } } } void test_GetNext_should_retrieve_object_and_metadata_from_device(void) { compare_against_offset_key(CMD_NEXT, false); }
int main(int argc, char** argv) { (void)argc; (void)argv; // Initialize kinetic-c and configure sessions KineticSession* session; KineticClientConfig clientConfig = { .logFile = "stdout", .logLevel = 1, }; KineticClient * client = KineticClient_Init(&clientConfig); if (client == NULL) { return 1; } const char HmacKeyString[] = "asdfasdf"; KineticSessionConfig sessionConfig = { .host = "localhost", .port = KINETIC_PORT, .clusterVersion = 0, .identity = 1, .hmacKey = ByteArray_CreateWithCString(HmacKeyString), }; KineticStatus status = KineticClient_CreateSession(&sessionConfig, client, &session); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Failed connecting to the Kinetic device w/status: %s\n", Kinetic_GetStatusDescription(status)); exit(1); } // some dummy data to PUT uint8_t value_data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; ByteBuffer value = ByteBuffer_MallocAndAppend(value_data, sizeof(value_data)); // a dummy key uint8_t key_data[] = {0x00, 0x01, 0x02, 0x03, 0x04}; ByteBuffer key = ByteBuffer_MallocAndAppend(key_data, sizeof(key_data)); // Populate tag with SHA1 ByteBuffer tag = ByteBuffer_Malloc(20); uint8_t sha1[20]; SHA1(value.array.data, value.bytesUsed, &sha1[0]); ByteBuffer_Append(&tag, sha1, sizeof(sha1)); KineticEntry entry = { .key = key, .tag = tag, .algorithm = KINETIC_ALGORITHM_SHA1, .value = value, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; // Do a blocking put to make sure there is something there to read back KineticStatus put_status = KineticClient_Put(session, &entry, NULL); if (put_status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Put failed w/status: %s\n", Kinetic_GetStatusDescription(put_status)); return 1; } // Create structure to populate with GET status in callback // a semaphore is used to notify the main thread that it's // safe to proceed. GetStatus get_status = { .sem = KineticSemaphore_Create(), .status = KINETIC_STATUS_INVALID, }; ByteBuffer getTag = ByteBuffer_Malloc(tag.bytesUsed); ByteBuffer getValue = ByteBuffer_Malloc(value.bytesUsed); // Because I'm passing a pointer to this entry to KineticClient_Put(), this entry must not // go out of scope until the GET completes KineticEntry get_entry = { .key = key, .tag = getTag, .algorithm = KINETIC_ALGORITHM_SHA1, .value = getValue, .force = true, }; status = KineticClient_Get( session, &get_entry, &(KineticCompletionClosure) { .callback = get_finished, .clientData = &get_status, } ); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Get failed w/status: %s\n", Kinetic_GetStatusDescription(status)); return 1; } // Wait for GET to finish KineticSemaphore_WaitForSignalAndDestroy(get_status.sem); if (get_status.status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "GET failed w/status: %s\n", Kinetic_GetStatusDescription(get_status.status)); return 1; } if ((value.bytesUsed == getValue.bytesUsed) && (memcmp(value.array.data, getValue.array.data, getValue.bytesUsed) != 0)) { fprintf(stderr, "GET completed but returned unexpected value"); return 1; } printf("GET completed successfully!\n"); // Free malloc'd buffers ByteBuffer_Free(value); ByteBuffer_Free(key); ByteBuffer_Free(tag); ByteBuffer_Free(getValue); ByteBuffer_Free(getTag); // Shutdown client connection and cleanup KineticClient_DestroySession(session); KineticClient_Shutdown(client); return 0; } static void get_finished(KineticCompletionData* kinetic_data, void* clientData) { GetStatus * get_status = clientData; // Save GET result status get_status->status = kinetic_data->status; // Signal that we're done KineticSemaphore_Signal(get_status->sem); }
static void do_put_and_get(KineticSession *session) { const char key[] = "key"; ByteBuffer put_key_buf = ByteBuffer_MallocAndAppend(key, strlen(key)); const uint8_t value[] = "value\x01\x02\x03\x04"; ByteBuffer put_value_buf = ByteBuffer_MallocAndAppend(value, sizeof(value)); /* Populate tag with SHA1 of value */ ByteBuffer put_tag_buf = ByteBuffer_Malloc(20); uint8_t sha1[20]; SHA1(put_value_buf.array.data, put_value_buf.bytesUsed, &sha1[0]); ByteBuffer_Append(&put_tag_buf, sha1, sizeof(sha1)); KineticEntry put_entry = { .key = put_key_buf, .value = put_value_buf, .tag = put_tag_buf, .algorithm = KINETIC_ALGORITHM_SHA1, /* Set sync to WRITETHROUGH, which will wait to complete * until the drive has persistend the write. (WRITEBACK * returns as soon as the drive has buffered the write.) */ .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; /* Put "key" => "value\x01\x02\x03\x04". * This will block, because the callback field (arg 3) is NULL. */ KineticStatus status = KineticClient_Put(session, &put_entry, NULL); printf("Put status: %s\n", Kinetic_GetStatusDescription(status)); /* Allocate a tag large enough for the SHA1. */ ByteBuffer get_tag_buf = ByteBuffer_Malloc(put_tag_buf.bytesUsed); /* Allocate a buffer large enough for the value. */ ByteBuffer get_value_buf = ByteBuffer_Malloc(put_value_buf.bytesUsed); KineticEntry get_entry = { .key = put_key_buf, .value = get_value_buf, .tag = get_tag_buf, .algorithm = KINETIC_ALGORITHM_SHA1, }; status = KineticClient_Get(session, &get_entry, NULL); printf("Get status: %s\n", Kinetic_GetStatusDescription(status)); printf("Get value: %zd bytes\n ", get_entry.value.bytesUsed); for (size_t i = 0; i < get_entry.value.bytesUsed; i++) { printf("%02x ", get_entry.value.array.data[i]); } printf(" "); for (size_t i = 0; i < get_entry.value.bytesUsed; i++) { char c = get_entry.value.array.data[i]; printf("%c", isprint(c) ? c : '.'); } printf("\n"); /* Cleanup */ ByteBuffer_Free(put_key_buf); ByteBuffer_Free(put_value_buf); ByteBuffer_Free(put_tag_buf); ByteBuffer_Free(get_entry.value); ByteBuffer_Free(get_tag_buf); }
static void do_put_and_getprevious_getnext(KineticSession *session) { for (int i = 0; i < 3; i++) { char key[] = "keyX"; key[3] = '0' + i; ByteBuffer put_key_buf = ByteBuffer_MallocAndAppend(key, strlen(key)); uint8_t value[] = "valueX"; value[5] = '0' + i; ByteBuffer put_value_buf = ByteBuffer_MallocAndAppend(value, sizeof(value)); /* Populate tag with SHA1 of value */ ByteBuffer put_tag_buf = ByteBuffer_Malloc(20); uint8_t sha1[20]; SHA1(put_value_buf.array.data, put_value_buf.bytesUsed, &sha1[0]); ByteBuffer_Append(&put_tag_buf, sha1, sizeof(sha1)); KineticEntry put_entry = { .key = put_key_buf, .value = put_value_buf, .tag = put_tag_buf, .algorithm = KINETIC_ALGORITHM_SHA1, /* Set sync to WRITETHROUGH, which will wait to complete * until the drive has persistend the write. (WRITEBACK * returns as soon as the drive has buffered the write.) */ .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; /* Put "keyX" => "valueX", where 'X' is 0..4. * This will block, because the callback field (arg 3) is NULL. */ KineticStatus status = KineticClient_Put(session, &put_entry, NULL); printf("Put status: %s\n", Kinetic_GetStatusDescription(status)); ByteBuffer_Free(put_key_buf); ByteBuffer_Free(put_value_buf); ByteBuffer_Free(put_tag_buf); } printf("\n\n\n"); for (int i = 1; i < 3; i++) { KineticStatus status = KINETIC_STATUS_INVALID; static const ssize_t sz = 100; char key_buf[sz]; char tag_buf[sz]; char value_buf[sz]; ByteBuffer keyBuffer = ByteBuffer_CreateAndAppendFormattedCString(key_buf, sz, "key%d", i); ByteBuffer tagBuffer = ByteBuffer_CreateAndAppendFormattedCString(tag_buf, sz, "tag%d", i); ByteBuffer valueBuffer = ByteBuffer_Create(value_buf, sz, 0); KineticEntry entry = { .key = keyBuffer, .tag = tagBuffer, .value = valueBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, }; if (i > 0) { status = KineticClient_GetPrevious(session, &entry, NULL); printf("GetPrevious status: %s\n", Kinetic_GetStatusDescription(status)); if (status == KINETIC_STATUS_SUCCESS) { printf("Previous key before 'key%d': '%s', value '%s'\n", i, key_buf, value_buf); } } } for (int i = 0; i < 2; i++) { KineticStatus status = KINETIC_STATUS_INVALID; static const ssize_t sz = 100; char key_buf[sz]; char tag_buf[sz]; char value_buf[sz]; ByteBuffer keyBuffer = ByteBuffer_CreateAndAppendFormattedCString(key_buf, sz, "key%d", i); ByteBuffer tagBuffer = ByteBuffer_CreateAndAppendFormattedCString(tag_buf, sz, "tag%d", i); ByteBuffer valueBuffer = ByteBuffer_Create(value_buf, sz, 0); KineticEntry entry = { .key = keyBuffer, .tag = tagBuffer, .value = valueBuffer, .algorithm = KINETIC_ALGORITHM_SHA1, }; if (i < 2) { status = KineticClient_GetNext(session, &entry, NULL); printf("GetNext status: %s\n", Kinetic_GetStatusDescription(status)); if (status == KINETIC_STATUS_SUCCESS) { printf("Next key after 'key%d': '%s', value '%s'\n", i, key_buf, value_buf); } } } /* No cleanup necessary */ }
TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_VERSION_MISMATCH, status); } void test_KineticClient_Put_should_allow_NULL_pointer_to_value_data_if_length_is_zero(void) { ByteArray value = {.data = NULL, .len = 0}; KineticEntry entry = {.value = ByteBuffer_CreateWithArray(value)}; KineticOperation operation; operation.session = &Session; KineticAllocator_NewOperation_ExpectAndReturn(&Session, &operation); KineticBuilder_BuildPut_ExpectAndReturn(&operation, &entry, KINETIC_STATUS_SUCCESS); KineticController_ExecuteOperation_ExpectAndReturn(&operation, NULL, KINETIC_STATUS_VERSION_MISMATCH); KineticStatus status = KineticClient_Put(&Session, &entry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_VERSION_MISMATCH, status); } void test_KineticClient_Put_should_return_BUFFER_OVERRUN_if_object_value_too_long(void) { ByteArray value = ByteArray_CreateWithCString("Four score, and seven years ago"); KineticEntry entry = {.value = ByteBuffer_CreateWithArray(value)}; KineticOperation operation; operation.session = &Session; KineticAllocator_NewOperation_ExpectAndReturn(&Session, &operation); KineticBuilder_BuildPut_ExpectAndReturn(&operation, &entry, KINETIC_STATUS_BUFFER_OVERRUN); KineticAllocator_FreeOperation_Expect(&operation);
void test_put_get_delete_one_entry_by_one_entry(void) { uint8_t version_data[DEFAULT_BUFFER_SIZE], tag_data[DEFAULT_BUFFER_SIZE], value_data[DEFAULT_BUFFER_SIZE]; ByteBuffer version_buffer, tag_buffer, value_buffer; version_buffer = ByteBuffer_CreateAndAppendCString(version_data, sizeof(version_data), "v1.0"); ExpectedVersionBuffer = ByteBuffer_CreateAndAppendCString(version_data, sizeof(version_data), "v1.0"); tag_buffer = ByteBuffer_CreateAndAppendCString(tag_data, sizeof(tag_data), "SomeTagValue"); ExpectedTagBuffer = ByteBuffer_CreateAndAppendCString(tag_data, sizeof(tag_data), "SomeTagValue"); value_buffer = ByteBuffer_Create(value_data, DEFAULT_BUFFER_SIZE, 0); unsigned int i; for (i=0; i<KV_PAIRS_PER_GROUP; i++) { // put object KineticEntry putEntry = { .key = generate_entry_key_by_index(i), .tag = tag_buffer, .newVersion = version_buffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = generate_entry_value_by_index(i), .force = true, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; KineticStatus status = KineticClient_Put(Fixture.session, &putEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); ByteBuffer_Reset(&value_buffer); // get object value_buffer = ByteBuffer_Create(value_data, DEFAULT_BUFFER_SIZE, 0); KineticEntry getEntry = { .key = generate_entry_key_by_index(i), .dbVersion = version_buffer, .tag = tag_buffer, .value = value_buffer, }; status = KineticClient_Get(Fixture.session, &getEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL_ByteBuffer(ExpectedVersionBuffer, getEntry.dbVersion); TEST_ASSERT_ByteBuffer_NULL(getEntry.newVersion); TEST_ASSERT_EQUAL_ByteBuffer(generate_entry_key_by_index(i), getEntry.key); TEST_ASSERT_EQUAL_ByteBuffer(ExpectedTagBuffer, getEntry.tag); TEST_ASSERT_EQUAL(KINETIC_ALGORITHM_SHA1, getEntry.algorithm); TEST_ASSERT_EQUAL_ByteBuffer(generate_entry_value_by_index(i), getEntry.value); TEST_ASSERT_EQUAL_ByteBuffer(ExpectedVersionBuffer, version_buffer); // delete object KineticEntry deleteEntry = { .key = generate_entry_key_by_index(i), .dbVersion = version_buffer, }; TEST_ASSERT_EQUAL_ByteBuffer(ExpectedVersionBuffer, version_buffer); status = KineticClient_Delete(Fixture.session, &deleteEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL(0, deleteEntry.value.bytesUsed); // get object again status = KineticClient_Get(Fixture.session, &getEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_NOT_FOUND, status); } } void test_put_get_delete_one_group_by_one_group(void) { uint8_t version_data[DEFAULT_BUFFER_SIZE], tag_data[DEFAULT_BUFFER_SIZE], value_data[DEFAULT_BUFFER_SIZE]; ByteBuffer version_buffer, tag_buffer, value_buffer; version_buffer = ByteBuffer_CreateAndAppendCString(version_data, sizeof(version_data), "v1.0"); ExpectedVersionBuffer = ByteBuffer_CreateAndAppendCString(version_data, sizeof(version_data), "v1.0"); tag_buffer = ByteBuffer_CreateAndAppendCString(tag_data, sizeof(tag_data), "SomeTagValue"); ExpectedTagBuffer = ByteBuffer_CreateAndAppendCString(tag_data, sizeof(tag_data), "SomeTagValue"); value_buffer = ByteBuffer_Create(value_data, DEFAULT_BUFFER_SIZE, 0); unsigned int i, j; for (i =0; i<TOTAL_GROUPS; i++) { KineticStatus status; // put a group of entries for (j=0; j<KV_PAIRS_PER_GROUP; j++) { KineticEntry putEntry = { .key = generate_entry_key_by_index(i*KV_PAIRS_PER_GROUP + j), .tag = tag_buffer, .newVersion = version_buffer, .algorithm = KINETIC_ALGORITHM_SHA1, .value = generate_entry_value_by_index(i*KV_PAIRS_PER_GROUP + j), .force = true, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; status = KineticClient_Put(Fixture.session, &putEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); } // get key_range KineticKeyRange range = { .startKey = generate_entry_key_by_index(i*KV_PAIRS_PER_GROUP), .endKey = generate_entry_key_by_index(i*KV_PAIRS_PER_GROUP + KV_PAIRS_PER_GROUP -1), .startKeyInclusive = true, .endKeyInclusive = true, .maxReturned = KV_PAIRS_PER_GROUP, }; ByteBuffer keyBuff[KV_PAIRS_PER_GROUP]; uint8_t keysData[KV_PAIRS_PER_GROUP][DEFAULT_BUFFER_SIZE]; for (j = 0; j < KV_PAIRS_PER_GROUP; j++) { memset(&keysData[j], 0, DEFAULT_BUFFER_SIZE); keyBuff[j] = ByteBuffer_Create(&keysData[j], DEFAULT_BUFFER_SIZE, 0); } ByteBufferArray keys = {.buffers = keyBuff, .count = KV_PAIRS_PER_GROUP, .used = 0}; status = KineticClient_GetKeyRange(Fixture.session, &range, &keys, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL(KV_PAIRS_PER_GROUP, keys.used); for (j = 0; j < KV_PAIRS_PER_GROUP; j++) { TEST_ASSERT_EQUAL_ByteBuffer(generate_entry_key_by_index(i*KV_PAIRS_PER_GROUP + j), keys.buffers[j]); } // delete a group of entries for (j=0; j<KV_PAIRS_PER_GROUP; j++) { ByteBuffer_Reset(&value_buffer); // get object value_buffer = ByteBuffer_Create(value_data, DEFAULT_BUFFER_SIZE, 0); KineticEntry getEntry = { .key = generate_entry_key_by_index(i*KV_PAIRS_PER_GROUP + j), .dbVersion = version_buffer, .tag = tag_buffer, .value = value_buffer, }; status = KineticClient_Get(Fixture.session, &getEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL_ByteBuffer(ExpectedVersionBuffer, getEntry.dbVersion); TEST_ASSERT_ByteBuffer_NULL(getEntry.newVersion); TEST_ASSERT_EQUAL_ByteBuffer(generate_entry_key_by_index(i*KV_PAIRS_PER_GROUP + j), getEntry.key); TEST_ASSERT_EQUAL_ByteBuffer(ExpectedTagBuffer, getEntry.tag); TEST_ASSERT_EQUAL(KINETIC_ALGORITHM_SHA1, getEntry.algorithm); TEST_ASSERT_EQUAL_ByteBuffer(generate_entry_value_by_index(i*KV_PAIRS_PER_GROUP + j), getEntry.value); TEST_ASSERT_EQUAL_ByteBuffer(ExpectedVersionBuffer, version_buffer); } // delete a group of entries for (j=0; j<KV_PAIRS_PER_GROUP; j++) { // delete object KineticEntry deleteEntry = { .key = generate_entry_key_by_index(i*KV_PAIRS_PER_GROUP + j), .dbVersion = version_buffer, }; TEST_ASSERT_EQUAL_ByteBuffer(ExpectedVersionBuffer, version_buffer); status = KineticClient_Delete(Fixture.session, &deleteEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_SUCCESS, status); TEST_ASSERT_EQUAL(0, deleteEntry.value.bytesUsed); // get object again ByteBuffer_Reset(&value_buffer); // get object value_buffer = ByteBuffer_Create(value_data, DEFAULT_BUFFER_SIZE, 0); KineticEntry getEntry = { .key = generate_entry_key_by_index(i*KV_PAIRS_PER_GROUP + j), .dbVersion = version_buffer, .tag = tag_buffer, .value = value_buffer, }; status = KineticClient_Get(Fixture.session, &getEntry, NULL); TEST_ASSERT_EQUAL_KineticStatus(KINETIC_STATUS_NOT_FOUND, status); } } }
int main(int argc, char** argv) { (void)argc; (void)argv; // Initialize kinetic-c and configure sessions KineticSession* session; KineticClientConfig clientConfig = { .logFile = "stdout", .logLevel = 1, }; KineticClient * client = KineticClient_Init(&clientConfig); if (client == NULL) { return 1; } const char HmacKeyString[] = "asdfasdf"; KineticSessionConfig sessionConfig = { .host = "localhost", .port = KINETIC_PORT, .clusterVersion = 0, .identity = 1, .hmacKey = ByteArray_CreateWithCString(HmacKeyString), }; KineticStatus status = KineticClient_CreateSession(&sessionConfig, client, &session); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "Failed connecting to the Kinetic device w/status: %s\n", Kinetic_GetStatusDescription(status)); exit(1); } // Create some entries so that we can query the keys printf("Storing some entries on the device...\n"); const size_t numKeys = 3; if (!create_entries(session, numKeys)) { return 2; } // Query a range of keys const size_t keyLen = 64; uint8_t startKeyData[keyLen], endKeyData[keyLen]; KineticKeyRange range = { .startKey = ByteBuffer_CreateAndAppendCString(startKeyData, sizeof(startKeyData), "key_prefix_00"), .endKey = ByteBuffer_CreateAndAppendCString(endKeyData, sizeof(endKeyData), "key_prefix_01"), .startKeyInclusive = true, .endKeyInclusive = true, .maxReturned = 3, }; uint8_t keysData[numKeys][keyLen]; ByteBuffer keyBuff[] = { ByteBuffer_Create(&keysData[0], keyLen, 0), ByteBuffer_Create(&keysData[1], keyLen, 0), ByteBuffer_Create(&keysData[2], keyLen, 0), }; ByteBufferArray keys = {.buffers = &keyBuff[0], .count = numKeys}; status = KineticClient_GetKeyRange(session, &range, &keys, NULL); if (status != KINETIC_STATUS_SUCCESS) { fprintf(stderr, "FAILURE: Failed retrieving key range from device!\n"); return 3; } if (keys.used != 2) { fprintf(stderr, "FAILURE: Unexpected number of keys in returned range!\n"); return 4; }; if (keyBuff[0].bytesUsed != strlen("key_prefix_00")) { fprintf(stderr, "FAILURE: Key 0 length check failed!\n"); return 4; } if (keyBuff[1].bytesUsed != strlen("key_prefix_01")) { fprintf(stderr, "FAILURE: Key 1 length check failed!\n"); return 4; } if (keyBuff[2].bytesUsed != 0) { fprintf(stderr, "FAILURE: Key 2 was not empty as expected!\n"); return 4; } // Shutdown client connection and cleanup KineticClient_DestroySession(session); KineticClient_Shutdown(client); printf("Key range retrieved successfully!\n"); return 0; } static bool create_entries(KineticSession * const session, const int count) { static const ssize_t sz = 20; char key_buf[sz]; char value_buf[sz]; for (int i = 0; i < count; i++) { ByteBuffer KeyBuffer = ByteBuffer_CreateAndAppendFormattedCString(key_buf, sz, "key_prefix_%02d", i); ByteBuffer ValueBuffer = ByteBuffer_CreateAndAppendFormattedCString(value_buf, sz, "val_%02d", i); /* Populate tag with SHA1 of value */ ByteBuffer put_tag_buf = ByteBuffer_Malloc(20); uint8_t sha1[20]; SHA1(ValueBuffer.array.data, ValueBuffer.bytesUsed, &sha1[0]); ByteBuffer_Append(&put_tag_buf, sha1, sizeof(sha1)); KineticEntry entry = { .key = KeyBuffer, .value = ValueBuffer, .tag = put_tag_buf, .algorithm = KINETIC_ALGORITHM_SHA1, .force = true, .synchronization = KINETIC_SYNCHRONIZATION_WRITETHROUGH, }; KineticStatus status = KineticClient_Put(session, &entry, NULL); if (KINETIC_STATUS_SUCCESS != status) { return false; } } return true; }