Commit cbd6ccec authored by Greg Williams's avatar Greg Williams
Browse files

Merge branch 'develop'

parents ce18b07d 46551fdb
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -8,17 +8,21 @@ This repo contains code for producing C Kinetic clients which use the Seagate Ki

Getting Started
================

**Clone the repo**

    > git clone --recursive https://github.com/atomicobject/kinetic-c.git
    > cd kinetic-c
    > bundle install # Ensure you have all RubyGems at the proper versions

**Update to the latest version (previously cloned)**

    > git pull
    > git submodule update --init # Ensure submodules are up to date
    > bundle install # Ensure you have all RubyGems at the proper versions

**Build Kinetic-C and run all tests**

    > bundle exec rake

API Documentation
@@ -71,7 +75,7 @@ Examples
The following examples are provided for development reference and as utilities to aid development. In order to execute a given example, you must first do:

```
> cd build/artifacts/release`
> cd build/artifacts/release
```

You can then execute `kinetic-c` with a valid example name, optionally preceeded with any of the optional arguments.
+91 −31
Original line number Diff line number Diff line
TEAMCITY_BUILD = !ENV['TEAMCITY_PROJECT_NAME'].nil?

require 'kinetic-ruby'
KineticRuby::Rake::load_tasks()

KineticRuby::Rake::load_tasks
require 'ceedling'
Ceedling.load_project(config: './project.yml')

@@ -22,6 +19,7 @@ def execute_command(cmd, banner=nil)
  report_banner banner unless banner.nil?
  report "Executing: #{cmd}"
  sh cmd
  report
  report unless banner.nil?
end

@@ -124,6 +122,8 @@ end

namespace :java_sim do

  JAVA_HOME = ENV.fetch('JAVA_HOME', '/usr')
  JAVA_BIN = File.join(JAVA_HOME, 'bin/java')
  $java_sim = nil

  def java_sim_start
@@ -134,19 +134,15 @@ namespace :java_sim do

    java_sim_cleanup

    # Validate JAVA_HOME
    java_home = ENV.fetch('JAVA_HOME', '/usr')
    java = File.join(java_home, 'bin/java')

    # Find the java simulator jar
    jars = Dir["vendor/kinetic-java/kinetic-simulator*.jar"]
    raise "No Kinetic Java simulator .jar files found!" if jars.empty?

    # Configure the classpath
    ENV['CLASSPATH'] = '' unless ENV['CLASSPATH']
    jars += [File.join(java_home, 'lib/tools.jar')]
    jars += [File.join(JAVA_HOME, 'lib/tools.jar')]
    jars.each {|jar| ENV['CLASSPATH'] += ':' + jar }
    $java_sim = spawn("#{java} -classpath #{ENV['CLASSPATH']} com.seagate.kinetic.simulator.internal.SimulatorRunner")
    $java_sim = spawn("#{JAVA_BIN} -classpath #{ENV['CLASSPATH']} com.seagate.kinetic.simulator.internal.SimulatorRunner")
    sleep 5 # wait for simulator to start up and server ready to receive connections
    # TODO: use netstat or something to just wait until the server opens the port
    #       since it might take longer than the hardcoded sleep(x) above :-/
@@ -163,6 +159,11 @@ namespace :java_sim do
    end
  end

  def java_sim_erase_drive
    java_sim_start
    sh "#{JAVA_BIN} -classpath #{ENV['CLASSPATH']} com.seagate.kinetic.admin.cli.KineticAdminCLI -setup -erase true"
  end

  def java_sim_cleanup
    # Ensure stray simulators are not still running
    `ps -ef | grep kinetic-simulator`.each_line do |l|
@@ -185,6 +186,11 @@ namespace :java_sim do
    java_sim_shutdown
  end

  desc "Erase Java simulator contents"
  task :erase do
    java_sim_erase_drive
  end

end

namespace :ruby_sim do
@@ -212,8 +218,13 @@ namespace :ruby_sim do
  end
end

task 'test/integration/test_kinetic_socket.c' => ['ruby_sim:start']
task 'test/system/test_kinetic_api_system.c' => ['ruby_sim:shutdown', 'java_sim:start']
# Setup ruby and java simulators for integration and system tests
Dir['test/integration/test_*.c'].each do |test_file|
  task test_file => ['java_sim:shutdown', 'ruby_sim:start']
end
Dir['test/system/test_*.c'].each do |test_file|
  task test_file => ['ruby_sim:shutdown', 'java_sim:erase', 'java_sim:start']
end

namespace :system do
  desc "Run system tests w/KineticRuby for message inspection"
@@ -226,11 +237,10 @@ namespace :system do
      Rake::Task[task].invoke
    end

    [
      'test/system/test_kinetic_api_system.c'
    ].each do |task|
      Rake::Task[task].clear_prerequisites
      Rake::Task[task].invoke
    Dir['test/system/test_*.c'].each do |test_task|
      p test_task
      Rake::Task[test_task].clear_prerequisites
      Rake::Task[test_task].invoke
    end

  end
@@ -266,7 +276,8 @@ task :default => [
]


namespace :test do
namespace :tests do

  desc "Run unit tests"
  task :unit do
    report_banner "Running Unit Tests"
@@ -284,35 +295,84 @@ namespace :test do
    shutdown_ruby_server
  end

  namespace :integration do
    task :noop do
      ####### ???
    end
  end

  desc "Run system tests"
  task :system => ['java_sim:start'] do
    report_banner "Running System Tests"
    shutdown_ruby_server
    java_sim_erase_drive
    java_sim_start
    Rake::Task['test:path'].reenable
    Rake::Task['test:path'].invoke('test/system')
    java_sim_shutdown
  end

  namespace :system do
    FileList['test/system/test_*.c'].each do |test|
      basename = File.basename(test, '.*')
      desc "Run system test #{basename}"
      task basename do
        shutdown_ruby_server
        java_sim_erase_drive
        java_sim_start
        Rake::Task[test].reenable
        Rake::Task[test].invoke
      end
    end
  end

  desc "Run Kinetic Client Utility tests"
  task :utility => ['ruby_sim:shutdown'] do
    report_banner "Running Kinetic Client Utility Tests"
  task :utility => [
    'release',
    'ruby_sim:shutdown',
    'tests:utility:noop',
    'tests:utility:put',
  ]

  namespace :utility do

    def with_test_server(banner)
      report_banner(banner)
      shutdown_ruby_server
      java_sim_start
    Rake::Task['release'].invoke
      cd "./build/artifacts/release/" do
        yield if block_given?
      end
    end

    task :noop => ['release', 'ruby_sim:shutdown'] do
      java_sim_erase_drive
      with_test_server("Testing NoOp Operation") do
        execute_command "./kinetic-c noop"
        execute_command "./kinetic-c --host localhost noop"
        execute_command "./kinetic-c --host 127.0.0.1 noop"
        execute_command "./kinetic-c --blocking --host 127.0.0.1 noop"
      end
    end

    task :put => ['release', 'ruby_sim:shutdown'] do
      java_sim_erase_drive
      with_test_server("Testing Put operation") do
        execute_command "./kinetic-c put"
      end
    end

task :test_all => ['test:unit', 'test:integration', 'test:system', 'test:utility'] do
  report_banner "Finished executing all test suites!"
  end

end

task :test_all => [
  'tests:unit',
  'tests:integration',
  'tests:system',
  'tests:utility'
]

desc "Build all and run test utility"
task :all => [
  'cppcheck',
+3 −3
Original line number Diff line number Diff line
@@ -21,10 +21,10 @@
#ifndef KINETIC_H_
#define KINETIC_H_

#include "kinetic_types.h"
#include "kinetic_api.h"
#include "protobuf-c.h"
#include "kinetic_proto.h"
#include "kinetic_logger.h"
#include "kinetic_connection.h"
#include "protobuf-c.h"
#include "kinetic_client.h"

#endif /* KINETIC_H_ */
+72 −56
Original line number Diff line number Diff line
@@ -18,112 +18,112 @@
*
*/

#include "kinetic_api.h"
#include "kinetic_client.h"
#include "kinetic_connection.h"
#include "kinetic_message.h"
#include "kinetic_pdu.h"
#include "kinetic_logger.h"
#include <stdio.h>

void KineticApi_Init(const char* logFile)
void KineticClient_Init(const char* logFile)
{
    KineticLogger_Init(logFile);
}

bool KineticApi_Connect(
bool KineticClient_Connect(
    KineticConnection* connection,
    const char* host,
    int port,
    bool blocking)
    bool nonBlocking,
    int64_t clusterVersion,
    int64_t identity,
    const char* key)
{
    KineticConnection_Init(connection);

    if (!KineticConnection_Connect(connection, host, port, blocking))
    if (connection == NULL)
    {
        connection->connected = false;
        connection->socketDescriptor = -1;
        char message[64];
        sprintf(message, "Failed creating connection to %s:%d", host, port);
        LOG(message);
        LOG("Specified KineticConnection is NULL!");
        return false;
    }

    connection->connected = true;

    return true;
    if (host == NULL)
    {
        LOG("Specified host is NULL!");
        return false;
    }

bool KineticApi_ConfigureExchange(
    KineticExchange* exchange,
    KineticConnection* connection,
    int64_t clusterVersion,
    int64_t identity,
    const char* key,
    size_t keyLength)
{
    if (exchange == NULL)
    if (key == NULL)
    {
        LOG("Specified KineticExchange is NULL!");
        LOG("Specified HMAC key is NULL!");
        return false;
    }

    if (key == NULL)
    if (strlen(key) < 1)
    {
        LOG("Specified Kinetic Protocol key is NULL!");
        LOG("Specified HMAC key is empty!");
        return false;
    }

    if (keyLength == 0)
    if (!KineticConnection_Connect(connection, host, port, nonBlocking,
        clusterVersion, identity, key))
    {
        LOG("Specified Kinetic Protocol key length is NULL!");
        connection->connected = false;
        connection->socketDescriptor = -1;
        char message[64];
        sprintf(message, "Failed creating connection to %s:%d", host, port);
        LOG(message);
        return false;
    }

    KineticExchange_Init(exchange, identity, key, keyLength, connection);
    KineticExchange_SetClusterVersion(exchange, clusterVersion);
    KineticExchange_ConfigureConnectionID(exchange);
    connection->connected = true;

    return true;
}

KineticOperation KineticApi_CreateOperation(
    KineticExchange* exchange,
void KineticClient_Disconnect(
    KineticConnection* connection)
{
   KineticConnection_Disconnect(connection);
}

KineticOperation KineticClient_CreateOperation(
    KineticConnection* connection,
    KineticPDU* request,
    KineticMessage* requestMsg,
    KineticPDU* response)
{
    KineticOperation op;

    if (exchange == NULL)
    if (connection == NULL)
    {
        LOG("Specified KineticExchange is NULL!");
        assert(exchange != NULL);
        LOG("Specified KineticConnection is NULL!");
        assert(connection != NULL);
    }

    if (request == NULL)
    {
        LOG("Specified request KineticPDU is NULL!");
        LOG("Specified KineticPDU request is NULL!");
        assert(request != NULL);
    }

    if (requestMsg == NULL)
    {
        LOG("Specified request KineticMessage is NULL!");
        LOG("Specified KineticMessage request is NULL!");
        assert(requestMsg != NULL);
    }

    if (response == NULL)
    {
        LOG("Specified response KineticPDU is NULL!");
        LOG("Specified KineticPDU response is NULL!");
        assert(response != NULL);
    }

    KineticMessage_Init(requestMsg);
    KineticPDU_Init(request, exchange, requestMsg, NULL, 0);
    KineticPDU_Init(request, connection, requestMsg, NULL, 0);

    // KineticMessage_Init(responseMsg);
    KineticPDU_Init(response, exchange, NULL, NULL, 0);
    KineticPDU_Init(response, connection, NULL, NULL, 0);

    op.exchange = exchange;
    op.connection = connection;
    op.request = request;
    op.request->message = requestMsg;
    op.response = response;
@@ -133,55 +133,71 @@ KineticOperation KineticApi_CreateOperation(
    return op;
}

KineticProto_Status_StatusCode KineticApi_NoOp(KineticOperation* operation)
KineticProto_Status_StatusCode KineticClient_NoOp(KineticOperation* operation)
{
    KineticProto_Status_StatusCode status =
        KINETIC_PROTO_STATUS_STATUS_CODE_INVALID_STATUS_CODE;

    assert(operation->exchange != NULL);
    assert(operation->exchange->connection != NULL);
    assert(operation->connection != NULL);
    assert(operation->request != NULL);
    assert(operation->request->message != NULL);
    assert(operation->response != NULL);
    assert(operation->response->message == NULL);

    // Initialize request
    KineticExchange_IncrementSequence(operation->exchange);
    KineticConnection_IncrementSequence(operation->connection);
    KineticOperation_BuildNoop(operation);

    // Send the request
    KineticPDU_Send(operation->request);

    // Associate response with same exchange as request
    operation->response->exchange = operation->request->exchange;
    operation->response->connection = operation->request->connection;

    // Receive the response
    if (KineticPDU_Receive(operation->response))
    {
        status = operation->response->proto->command->status->code;
        status = KineticPDU_Status(operation->response);
    }

	return status;
}

KineticProto_Status_StatusCode KineticApi_Put(
    KineticOperation* operation,
KineticProto_Status_StatusCode KineticClient_Put(KineticOperation* operation,
    char* newVersion,
    char* key,
    char* dbVersion,
    char* tag,
    uint8_t* value,
    int64_t len)
{
    KineticProto_Status_StatusCode status =
        KINETIC_PROTO_STATUS_STATUS_CODE_INVALID_STATUS_CODE;

    assert(operation->exchange != NULL);
    assert(operation->exchange->connection != NULL);
    assert(operation->connection != NULL);
    assert(operation->request != NULL);
    assert(operation->request->message != NULL);
    assert(operation->response != NULL);
    assert(operation->response->message == NULL);
    assert(value != NULL);
    assert(len < 1024*1024);
    assert(len <= PDU_VALUE_MAX_LEN);

    // Initialize request
    KineticConnection_IncrementSequence(operation->connection);
    KineticOperation_BuildPut(operation, value, len);
    KineticMessage_ConfigureKeyValue(operation->request->message, newVersion, key, dbVersion, tag);

    // Send the request
    KineticPDU_Send(operation->request);

    // Associate response with same exchange as request
    operation->response->connection = operation->request->connection;

    // TODO: Make it happen!!!
    // Receive the response
    if (KineticPDU_Receive(operation->response))
    {
        status = KineticPDU_Status(operation->response);
    }

    return status;
}
+27 −39
Original line number Diff line number Diff line
@@ -18,11 +18,10 @@
*
*/

#ifndef _KINETIC_API_H
#define _KINETIC_API_H
#ifndef _KINETIC_CLIENT_H
#define _KINETIC_CLIENT_H

#include "kinetic_types.h"
#include "kinetic_exchange.h"
#include "kinetic_pdu.h"
#include "kinetic_operation.h"

@@ -31,57 +30,48 @@
 *
 * @param logFile Path to log file. Specify NULL to log to STDOUT.
 */
void KineticApi_Init(
    const char* logFile);
void KineticClient_Init(const char* logFile);

/**
 * @brief Establishes a Kinetic protocol socket connection to a host.
 * @brief Configures the session and establishes a socket connection to a Kinetic Device
 *
 * @param connection        KineticConnection instance to configure with connection info
 * @param host              Host name or IP address to connect to
 * @param port              Port to establish socket connection on
 * @param blocking          Set to true for blocking or false for non-bloocking I/O
 * @param nonBlocking       Set to true for non-blocking or false for blocking I/O
 * @param clusterVersion    Cluster version to use for the session
 * @param identity          Identity to use for the session
 * @param key               Key to use for HMAC calculations (NULL-terminated string)
 *
 * @return                  Returns true if connection succeeded
 */
bool KineticApi_Connect(
    KineticConnection* connection,
bool KineticClient_Connect(KineticConnection* connection,
    const char* host,
    int port,
    bool blocking);
    bool nonBlocking,
    int64_t clusterVersion,
    int64_t identity,
    const char* key);

/**
 * @brief Initializes and configures a Kinetic exchange.
 *
 * @param exchange          KineticExchange instance to configure with exchange info
 * @param connection        KineticConnection to associate with exchange
 * @param clusterVersion    Cluster version for the exchange
 * @param identity          Identity to use for the exchange
 * @param key               Key to use for HMAC calculations
 * @param keyLength         Length of HMAC key
 * @brief Closes the socket connection to a host.
 *
 * @return                  Returns true if configuration succeeded
 * @param connection        KineticConnection instance
 */
bool KineticApi_ConfigureExchange(
    KineticExchange* exchange,
    KineticConnection* connection,
    int64_t clusterVersion,
    int64_t identity,
    const char* key,
    size_t keyLength);
void KineticClient_Disconnect(KineticConnection* connection);

/**
 * @brief Creates and initializes a Kinetic operation.
 *
 * @param exchange          KineticExchange instance to populate with exchange info
 * @param connection        KineticConnection instance to associate with operation
 * @param request           KineticPDU instance to use for request
 * @param requestMsg        KineticMessage instance to use for request
 * @param response          KineticPDU instance to use for reponse
 *
 * @return                  Returns a configured operation instance
 */
KineticOperation KineticApi_CreateOperation(
    KineticExchange* exchange,
KineticOperation KineticClient_CreateOperation(
    KineticConnection* connection,
    KineticPDU* request,
    KineticMessage* requestMsg,
    KineticPDU* response);
@@ -93,23 +83,21 @@ KineticOperation KineticApi_CreateOperation(
 *
 * @return                  Returns the resultant status code
 */
KineticProto_Status_StatusCode KineticApi_NoOp(
    KineticOperation* operation
    );
KineticProto_Status_StatusCode KineticClient_NoOp(KineticOperation* operation);

/**
 * @brief Executes a PUT command to write data to the Kinetic Device
 *
 * @param operation         KineticOperation instance to use for the operation
 * @param value             Value payload buffer
 * @param valueLength       Value payload length (in bytes)
 *
 * @return                  Returns the resultant status code
 */
KineticProto_Status_StatusCode KineticApi_Put(
    KineticOperation* operation,
KineticProto_Status_StatusCode KineticClient_Put(KineticOperation* operation,
    char* newVersion,
    char* key,
    char* dbVersion,
    char* tag,
    uint8_t* value,
    int64_t len
    );
    int64_t len);

#endif // _KINETIC_API_H
#endif // _KINETIC_CLIENT_H
Loading