Skip to content

Connecting

The aerospike object represents a single cluster. To connect to a cluster, you must configure an aerospike object and initialize the client. However, depending on how you wish to connect (plaintext versus encrypted with TLS), the steps you take to configure your aerospike object will differ.

Connecting over plaintext connections

Configuring the client

To configure the client to connect over a plaintext connection, initialize an as_config object to its default value using as_config_init():

as_config config;
as_config_init(&config);

You need at least one host configuration to seed the client. The client attempts to connect to each seed you specify, until it succeeds. Once successful, the host establishes a connection to the cluster and automatically discovers the remaining cluster nodes, if any.

as_config_add_host(&config, "127.0.0.1", 3000);

Initializing a client

Before connecting to the cluster, initialize an aerospike client object using your configuration.

aerospike as;
aerospike_init(&as, &config);

On success, aerospike_init returns a pointer to the initialized aerospike object; otherwise it answers with NULL.

Establishing a connection

After initializing an aerospike instance, you can connect to the cluster using aerospike_connect. Connecting might result in an error, so it is required to pass an as_error instance as an output parameter. Similar to exceptions in other programming languages, this allows the client library to provide additional context about the error.

as_error err;
if (aerospike_connect(&as, &err) != AEROSPIKE_OK) {
fprintf(stderr, "err(%d) %s at [%s:%d]\n", err.code, err.message, err.file, err.line);
}

The value of err.code equals the return code from aerospike_connect. If AEROSPIKE_OK is not the return value, an error occurred. Check the err object for information.

An aerospike object internally contains the cluster status and maintains the connection pools to the cluster. The application can reuse the aerospike object for database operations to a given cluster.

If the application needs to connect to multiple Aerospike clusters, it must create multiple aerospike objects, one for each cluster.

Closing a connection

When the application no longer requires the client connections to the cluster, close the connection with aerospike_close():

as_error err;
if (aerospike_close(&as, &err) != AEROSPIKE_OK) {
fprintf(stderr, "err(%d) %s at [%s:%d]\n", err.code, err.message, err.file, err.line);
}

Cleaning up resources

Use aerospike_destroy() to destroy the client and release all of its resources:

aerospike_destroy(&as);

Connecting over a public key infrastructure (PKI) TLS Connection

Connecting over TLS requires you to perform all of the steps you’d normally perform for a plaintext connection. However, there are additional steps you need to perform in order to provide the required security information to establish a TLS encrypted session.

Basic configuration for the client

Start by initializing and adding the seed host to a configuration, as with a plaintext connection. Note that we use a different port for TLS connections.

as_config config;
as_config_init(&config);
as_config_add_host(&config, "127.0.0.1", 4333);

Initializing a client

Before connecting to the cluster, you need to initialize an aerospike client object using your configuration.

  1. You need to inform the Aerospike client that you are attempting to use TLS to connect.

    as_config config;
    config.tls.enable = true;
  2. You’ll want to provide a CA certificate file suitable for the server you wish to connect to. How to acquire this certificate file is beyond the scope of this tutorial; however, if you need initial direction for learning more about this in a hands-on way, you may want to look into the Aerolab project. Aerolab makes deploying and managing clusters for educational purposes easier.

    as_config config;
    as_config_tls_set_cafile(&config, "/home/project_acct/.config/aerospike/CA/cacert.pem");
  3. Iterate through all the hosts in the cluster, setting each host’s TLS name. Recall that attaching to a seed host allows the client to discover the topology of the cluster as a whole. However, it isn’t clear to the client how you wish to connect yet. The data retrieved thus assumes you’re planning on connecting over a plaintext connection. Since we desire a PKI connection, we must update the client’s knowledge of the host constellation to use TLS as well. You may recall that TLS configuration involves setting a “TLS name” to identify a given TLS configuration.

    as_config config;
    for (int i = 0; i < config.hosts->capacity; i++) {
    as_host* host = (as_host*)as_vector_get(config.hosts, i);
    if (! host->tls_name) {
    host->tls_name = strdup("tls1");
    }
    }
  4. Resume the connection process exactly like we would a plaintext connection.

    aerospike as;
    aerospike_init(&as, &config);
    if (aerospike_connect(&as, &err) != AEROSPIKE_OK) {
    fprintf(stderr, "err(%d) %s at [%s:%d]\n", err.code, err.message, err.file, err.line);
    }

Closing a connection

When the application no longer requires the client connections to the cluster, close the connection with aerospike_close():

as_error err;
if (aerospike_close(&as, &err) != AEROSPIKE_OK) {
fprintf(stderr, "err(%d) %s at [%s:%d]\n", err.code, err.message, err.file, err.line);
}

Cleaning up resources

Use aerospike_destroy() to destroy the client and release all of its resources:

aerospike_destroy(&as);

C listing

The following example illustrates how to connect to a server over plaintext or PKI TLS connections, providing a more complete illustration of what real code should look like in practice. Depending on which command-line options you specify, it may perform either a plaintext or a PKI TLS connection.

#include <errno.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <aerospike/aerospike.h>
////// Parse command-line arguments
// The result of parsing arguments from the CLI.
typedef struct program_options_s {
char* hostname;
uint16_t port;
bool tls_options_given;
char* cafile;
char* tls_name;
} program_options;
// If you alter any of these assignments, be sure to update
// `optstring` below as well.
enum {
OPT_DONE = -1,
OPT_HELP = 'h',
OPT_HOST = 'r',
OPT_PORT = 'p',
OPT_CAFILE = 'a',
OPT_TLS_NAME = 't',
};
static const struct option longopts[] = {
{"help", no_argument, NULL, OPT_HELP},
{"host", required_argument, NULL, OPT_HOST},
{"port", required_argument, NULL, OPT_PORT},
{"ca-file", required_argument, NULL, OPT_CAFILE},
{"cluster-name", required_argument, NULL, OPT_TLS_NAME},
{NULL, 0, NULL, 0},
};
static const char* optstring = "h?r:p:a:t:";
static void
program_options_init(program_options* po)
{
if(po) {
memset(po, 0, sizeof(program_options));
po->hostname = "127.0.0.1";
po->port = 3000;
}
}
static void
print_usage(const char* cmdname)
{
printf("%s [options] "
"-r|--host <remote host> "
"-p|--port <port>\n\n", cmdname);
printf("where [options] can be one or more of:\n");
printf(" -?,-h --help Displays this message and quits.\n");
printf(" -a --ca-file <path> Gives path to CA Certificate file\n");
printf(" -t --tls-name <name> Gives the TLS cluster name\n");
printf("\nNote that, at a minimum, -a and -t must be specified for "
"TLS to work.\n");
}
void
program_options_parse(program_options* po, int argc, char* argv[])
{
program_options_init(po);
for (int done = 0; !done; ) {
int res = getopt_long(argc, argv, optstring, longopts, NULL);
switch(res) {
default:
printf("Unknown getopt_long() result: %u\n", res);
// fall through intended.
case OPT_DONE:
done++;
break;
case '?':
case OPT_HELP:
print_usage(argv[0]);
exit(EXIT_SUCCESS);
case OPT_HOST:
po->hostname = strdup(optarg);
break;
case OPT_PORT:
errno = 0;
unsigned long p = strtoul(optarg, NULL, 10);
if(errno != 0) {
perror("strtoul");
exit(EXIT_FAILURE);
}
if(!((0 <= p) && (p < 65536))) {
fprintf(stderr,
"Port must fall between 0 "
"and 65535 inclusive.\n");
exit(EXIT_FAILURE);
}
po->port = (uint16_t)p;
break;
case OPT_CAFILE:
po->cafile = strdup(optarg);
break;
case OPT_TLS_NAME:
po->tls_name = strdup(optarg);
break;
}
}
// Set tls_options_given only if the minimum set of parameters
// are given.
po->tls_options_given = po->cafile && po->tls_name;
}
////// Example code
void
check_error(const char* operation, as_error* err)
{
if (err->code != AEROSPIKE_OK) {
fprintf(stderr,
"Aerospike client failed while %s: "
"err(%d) %s at [%s:%d]\n",
operation,
err->code, err->message, err->file, err->line);
exit(EXIT_FAILURE);
}
}
void
connect_to_aerospike(aerospike* as, program_options* po, as_error* err)
{
as_config config;
as_config_init(&config);
// This adds the provided host as a seed. This may yield a number
// of additional hosts if the cluster size is greater than one.
as_config_add_host(&config, po->hostname, po->port);
if (po->tls_options_given) {
config.tls.enable = true;
as_config_tls_set_cafile(&config, po->cafile);
// After discovering the complete set of hosts in the cluster,
// we need to configure each of them with the TLS name we wish
// to connect to. Failing to do that will yield connection
// failures when attempting to connect.
for (int i = 0; i < config.hosts->capacity; i++) {
as_host* host = (as_host*)as_vector_get(config.hosts, i);
if( !host->tls_name) {
host->tls_name = strdup(po->tls_name);
}
}
}
aerospike_init(as, &config);
aerospike_connect(as, err);
check_error("connecting", err);
}
int
main(int argc, char* argv[])
{
program_options po;
program_options_parse(&po, argc, argv);
printf("Attempting to connect to host %s port %u\n", po.hostname, po.port);
if (po.tls_options_given) {
printf(" using TLS with the following settings:\n");
printf(" CA File: %s\n", po.cafile);
printf(" TLS Name: %s\n", po.tls_name);
}
else {
printf(" without using TLS.\n");
}
aerospike as;
as_error err;
as_error_init(&err);
connect_to_aerospike(&as, &po, &err);
printf("Connection successful.\n");
// ...
printf("Now closing connection.\n");
aerospike_close(&as, &err);
check_error("closing connection", &err);
return 0;
}
Feedback

Was this page helpful?

What type of feedback are you giving?

What would you like us to know?

+Capture screenshot

Can we reach out to you?