Batched commands
Use the following calls to perform multiple record reads from the cluster in one command:
aerospike_batch_get()
— Return all bins of the specified records.aerospike_batch_exists()
— Return the metadata (such as, time-to-live and generation) for the specified records.
These examples are in examples/batch_examples/get in the Aerospike C client package.
To continue, the client must have an established the cluster connection.
Initializing a Batch Request
Before making a batch call, intialize an as_batch
object. This example initializes as_batch
with 1000 records to fetch:
as_batch batch;as_batch_inita(&batch, 1000);
Initializing Keys to Read
To initialize the keys to read:
for (uint32_t i = 0; i < 1000; i++) { as_key_init_int64(as_batch_keyat(&batch, i), "test", "demoset", (int64_t)i);}
This call sets up the 1000 keys using as_batch_keyat()
. The key data type is integer, in the range 0 to 1000. Different key data types such as string are allowed. The keys are made for the namespace test within set demoset.
Reading Records
To retrieve records:
if (aerospike_batch_get(&as, &err, NULL, &batch, batch_read_cb, NULL) != AEROSPIKE_OK) { LOG("aerospike_batch_get() returned %d - %s", err.code, err.message); cleanup(&as); exit(-1);}
This command groups keys based on which Aerospike server node can best handle the request and initiates one batch job for each node in the cluster. If the batch policy as_policy_batch.concurrent
is false (default), the batch jobs will be executed sequentially in the same command thread. If concurrent
is true, the batch jobs will be executed in parallel threads using the client thread pool. The client thread pool size can be configured on client initialization with as_config.thread_pool_size
(default 16).
Asynchronous batch commands use a different api (aerospike_batch_read_async()
), do not use the thread pool and the batch jobs are executed in parallel on the specified event loop.
Processing the Results
In the previous example, aerospike_batch_get()
takes a batch_read_cb
callback function as a parameter with the following type:
bool (* aerospike_batch_read_callback)(const as_batch_read * results, uint32_t n, void * udata);
This callback function is invoked after all records return from all the nodes, and in the same order as the keys are passed.
An application can examine the list as_batch_read
results and process each record. These records and values are only valid within the scope of the callback, and must explicitly be copied if needed outside the callback scope.
boolbatch_read_cb(const as_batch_read* results, uint32_t n, void* udata){
uint32_t n_found = 0;
for (uint32_t i = 0; i < n; i++) { LOG("index %u, key %" PRId64 ":", i, as_integer_getorelse((as_integer*)results[i].key->valuep, -1));
if (results[i].result == AEROSPIKE_OK) { LOG(" AEROSPIKE_OK"); n_found++; } else if (results[i].result == AEROSPIKE_ERR_RECORD_NOT_FOUND) { // The command succeeded but the record doesn't exist. LOG(" AEROSPIKE_ERR_RECORD_NOT_FOUND"); } else { // The command didn't succeed. LOG(" error %d", results[i].result); } }
return true;}
To pass a global object during the callback, supply a userdata
parameter in aerospike_batch_get()
.
Reading Record Metadata from Database
Instead of always reading the entire bin data of full records, the application can make an equivalent call to only return the metadata of the record (such as time-to-live and generation). This is preferred when the application only needs to determine if a record exists, and does not want to incur the cost of actually reading the data.
if (aerospike_batch_exists(&as, &err, NULL, &batch, batch_read_cb, NULL) != AEROSPIKE_OK) { LOG("aerospike_batch_exists() returned %d - %s", err.code, err.message); cleanup(&as); exit(-1);}
Cleaning Up Resources
Always clean up keys made with heap allocations.