Go to main content

man pages section 3: Extended Library Functions, Volume 4

Exit Print View

Updated: Thursday, June 13, 2019
 
 

sstore_batch_alloc (3SSTORE)

Name

sstore_batch_alloc, sstore_batch_call, sstore_batch_data_read, sstore_batch_free, sstore_batch_info_read, sstore_batch_iter_next, sstore_batch_namespace_list - TBD

Synopsis

     cc [ flag... ] file... -lsstore [ library... ]
     #include <libsstore.h>

     sstore_batch_t sstore_batch_alloc(void);

     void sstore_batch_free(sstore_batch_t b_hdl);

     sstore_err_t sstore_batch_data_read(sstore_handle_t hdl,
         sstore_batch_t b_hdl, void *cookie, const char **ids,
         uint32_t id_count, sstore_range_t range,
         sstore_walk_t walk);

     sstore_err_t sstore_batch_info_read(sstore_handle_t hdl,
         sstore_batch_t b_hdl, void *cookie, const char **ids,
         uint32_t id_count, sstore_range_t range);

     sstore_err_t sstore_batch_namespace_list(sstore_handle_t hdl,
         sstore_batch_t b_hdl, void *cookie, const char **ids,
         uint32_t id_count, sstore_range_t range);

     sstore_err_t sstore_batch_call(sstore_handle_t hdl,
         sstore_batch_t b_hdl, sstore_iter_t *b_iterp);

     sstore_err_t sstore_batch_iter_next(sstore_handle_t hdl,
         sstore_iter_t b_iter, void **cookiep,
         sstore_iter_t *iterp, sstore_result_type_t *typep);

Parameters

b_hdl

Handle to a batch object

hdl

Handle to libsstore

cookie

Cookie to associate the result with the request

ids

Array of ssids

id_count

Total number of statistics store identifiers

range

Time range or data range.

Passing NULL for range implies:

  • start-time = SS_TIME_NOW

  • end-time = SS_TIME_NOW

  • step = (None - raw data)

walk

Format of the iteration. The following formats are supported:

SSTORE_WALK_ID

Walks the data records by identifier

SSTORE_WALK_TS

Walks the data records by timestamps

id

Statistics store identifier

b_iterp

Address to store the starting address of the batch iterator

b_iter

Batch iterator

cookiep

Address to store the cookie associated with the batch request

iterp

Address to store the starting address of the iterator returned from batch request execution

typep

Address to store the result type of the batch request. Address can be one of the following values:

SSTORE_RESULT_TYPE_ITER

Request executed successfully and the result is an iterator

SSTORE_RESULT_TYPE_NONE

Request executed successfully and there is no data to be returned

SSTORE_RESULT_TYPE_ERROR

Request execution resulted in an error

Description

The batch interface provides a way to get a single iterator for the results of multiple requests. To do this, all the individual requests are queued up in a batch object using the interfaces for batching different types of request. A cookie can be provided while batching a request in order to associate the result of that request with the cookie. That batch object is then passed to sstore_batch_call(3SSTORE), which executes all the requests and generates an iterator that contains the result for all the requests in that batch object.

sstore_batch_alloc() allocates a batch handle.

sstore_batch_free() frees the batch handle.

The sstore_batch_data_read(), sstore_batch_info_read(), and sstore_batch_namespace_list() functions batch sstore_data_read(3SSTORE), sstore_info_read(3SSTORE), and sstore_namespace_list(3SSTORE) respectively to the batch object. These batch functions defer the execution of the corresponding non-batch functions until sstore_batch_call() is called with the given batch handle. Each of these batch functions takes a cookie that will be returned while iterating the result for the corresponding request. The caller is responsible for the memory management of this cookie. The remaining arguments are similar to the same arguments for the corresponding non-batch functions except that the batch functions do not return an iterator because they just add the request to the batch handle and defer the execution.

sstore_batch_call() executes all the requests added to the batch handle and returns an iterator that can be used to iterate over the results. The caller is responsible for freeing the returned iterator by using sstore_iter_free().

sstore_batch_iter_next() retrieves the result from the execution of the next batch request. It populates cookiep with the cookie that is passed when the batch request was added to the batch handle. It also populates typep with the appropriate enumerated value based on the result of the execution of the corresponding request. If no error occurs during the request execution, and if typep is set to SSTORE_RESULT_TYPE_ITER, then it populates iterp with the iterator. The caller should not free this iterator because the iterator will be freed when sstore_batch_iter_next() is called again or when the batch iterator itself is freed.

sstore_batch_iter_next() also caches any warnings set during the request execution in the given libsstore handle. If the request execution results in an error, then the error code, description, and action are cached in the given libsstore handle.

Authorizations

sstore_batch_data_read(), sstore_batch_info_read(), and sstore_batch_namespace_list() require the same authorizations as their non-batch counterparts.

Return Values

Upon successful completion, sstore_batch_alloc() returns an sstore_batch_t. Otherwise it returns NULL.

Upon successful completion, sstore_batch_data_read(), sstore_batch_info_read(), sstore_batch_namespace_list(), sstore_batch_call(), and sstore_batch_iter_next() return ESSTORE_OK. Otherwise they return an error code.

Except for sstore_batch_iter_next(), all of the batch APIs returning an sstore_err_t cache the error code and the corresponding description and action strings in the given libsstore handle.

Errors

The sstore_batch_alloc() function fails if:

ENOMEM

There is insufficient memory.

The sstore_batch_data_read(), sstore_batch_info_read() and sstore_batch_namespace_list() functions fail if:

ESSTORE_ARG_INVALID

The batch handle is invalid.

ESSTORE_HANDLE_INVALID

The libsstore handle is invalid.

ESSTORE_NOMEM

There is insufficient memory.

The sstore_batch_call() function fails if:

ESSTORE_ARG_INVALID

Some arguments are invalid.

ESSTORE_HANDLE_INVALID

The libsstore handle is invalid.

ESSTORE_CONNECTION_FAILED

Failed to connect to the sstored(8).

ESSTORE_NOMEM

No memory is available.

The sstore_batch_iter_next() function fails if:

ESSTORE_ARG_INVALID

Some arguments are invalid.

ESSTORE_HANDLE_INVALID

The libsstore handle is invalid.

ESSTORE_ITER_DONE

No more records remain.

Examples

Example 1 Performing data_read, info_read, and namespace_list on an ssid in a single batch call.
     #include <libsstore.h>
     #include <stdio.h>
     #include <unistd.h>

     #define FLOOR(ts)   (((ts) / 1000000) * 1000000)
     #define HFMT        "%-53s %-16s %s\n"
     #define IFMTU       "%-53s %16llu\n"
     #define IFMTS       "%-53s %-16s"

     /* List of ssids */
     const char *ids[] = {
         "//:class.cpu//:stat.xcalls//:part.cpu(1,2)"
     };

     uint32_t id_count = 1;

     sstore_handle_t hdl = NULL;

     void print_iter(sstore_iter_t);

     void
     print_error(void)
     {
         if (sstore_err_code(hdl) != ESSTORE_OK &&
             sstore_err_code(hdl) != ESSTORE_ITER_DONE) {
             fprintf(stderr, "%s. Error: %s\n", sstore_err_action(hdl),
                 sstore_err_description(hdl));
         }
     }

     /*
      * Prints the value in the value handle.
      */
     sstore_err_t
     print_value(sstore_value_t val)
     {
         uint64_t val_u64;
         char *val_str, **val_strarr, *dict_key;
         sstore_value_t dict_val;
         uint32_t count, i;

         if (val == NULL) {
             return (ESSTORE_OK);
         }

         switch(sstore_value_type(val)) {
         case SSTORE_VALUE_NUMBER:
             if (sstore_value_number(hdl, val, &val_u64) != ESSTORE_OK) {
                 break;
             }
             printf("%lu\n", val_u64);
             break;

         case SSTORE_VALUE_STRING:
             if (sstore_value_string(hdl, val, &val_str) != ESSTORE_OK) {
                 break;
             }
             printf("%s\n", val_str);
             break;

         case SSTORE_VALUE_STRING_ARRAY:
             if (sstore_value_string_array(hdl, val, &val_strarr,
                 &count) != ESSTORE_OK) {
                 break;
             }
             for (i = 0; i < count; i++) {
		     printf("%s ", val_strarr[i]);
             }
             printf("\n");
             break;

         case SSTORE_VALUE_DICTIONARY:
             printf("\n");
             while (sstore_value_dictionary_next(hdl, val, &dict_key,
                 &dict_val) == ESSTORE_OK) {
                     printf("%12s: ", dict_key);
                     print_value(dict_val);
             }
             printf("\n");       
             break;
    
         case SSTORE_VALUE_NODATA:
             printf("NO_DATA\n");
             break;

         default:
             printf("Unexpected value type %d\n", sstore_value_type(val));
         }

         return (sstore_err_code(hdl));
     }

     void
     print_data_iter(sstore_iter_t iter)
     {
         sstore_value_t val;
         sstore_err_t err;
         char *id;
         uint64_t ts;

         printf(HFMT, "IDENTIFIER", "TIMESTAMP", "VALUE");
         while (sstore_data_iter_next(hdl, iter, &id, &ts,
             &val) == ESSTORE_OK) {
                 /* Round down the time stamp */
                 ts = FLOOR(ts);
                 printf(IFMTU, id, ts);
                 err = print_value(val);
                 if (err != ESSTORE_OK && err != ESSTORE_ITER_DONE) {
                     break;
                 }
         }

         return;
     }

     void
     print_info_iter(sstore_iter_t iter)
     {
         sstore_value_t val;
         sstore_err_t err;
         char *id;
         uint64_t ts;

         printf(HFMT, "IDENTIFIER", "TIMESTAMP", "VALUE");
         while (sstore_info_iter_next(hdl, iter, &id, &ts,
             &val) == ESSTORE_OK) {
                 /* Round out the times */
                 ts = FLOOR(ts);
                 printf(IFMTU, id, ts);
                 err = print_value(val);
                 if (err != ESSTORE_OK && err != ESSTORE_ITER_DONE) {
                     break;
                 }
         }

         return;
     }

     void
     print_ns_iter(sstore_iter_t iter)
     {
         char *id;
         uint64_t start_ts, end_ts;
         char ts[16];

         printf(HFMT, "IDENTIFIER", "START", "END");
         while (sstore_namespace_iter_next(hdl, iter, &id, &start_ts,
             &end_ts) == ESSTORE_OK) {
                 /* Round out the times */
                 start_ts = FLOOR(start_ts);
                 end_ts = FLOOR(end_ts);
                 if (start_ts == 0) {
                     (void) snprintf(ts, sizeof (ts), "UNKNOWN");
                 } else {
                     (void) snprintf(ts, sizeof (ts), "%llu", start_ts);
                 }
                 printf(IFMTS, id, ts);

                 if (end_ts == 0) {
                     printf(" ACTIVE\n");
                 } else {
                     printf(" %lu\n", end_ts);
                 }
         }

         return;
     }

     void
     print_batch_iter(sstore_iter_t b_iter)
     {
         char *cookie;
         sstore_iter_t iter;
         sstore_result_type_t type;

         /* Iterate through all the batch requests and print results */
         while (sstore_batch_iter_next(hdl, b_iter, (void **)&cookie,
             &iter, &type) == ESSTORE_OK) {
                 printf("\nCOOKIE: %s\n", cookie);
             switch (type) {
             case SSTORE_RESULT_TYPE_ITER:
                 print_iter(iter);
                 break;

             case SSTORE_RESULT_TYPE_ERROR:
                 print_error();
                 break;
             }
         }
     }

     void
     print_iter(sstore_iter_t iter)
     {
         switch (sstore_iter_type(iter)) {
         case SSTORE_ITER_TYPE_DATA:
             print_data_iter(iter);
             break;

         case SSTORE_ITER_TYPE_INFO:
             print_info_iter(iter);
             break;

         case SSTORE_ITER_TYPE_NAMESPACE:
             print_ns_iter(iter);
             break;

         case SSTORE_ITER_TYPE_BATCH:
             print_batch_iter(iter);
             break;

         default:
             fprintf(stderr, "Invalid iterator type\n");
             return;
         }

         if (sstore_err_code(hdl) != ESSTORE_ITER_DONE) {
             print_error();
         }
     }
        

     int main()
     {
         sstore_batch_t b_hdl = NULL;
         sstore_iter_t b_iter = NULL;
         int ret = -1;

         /* Allocate a libsstore handle */
         if ((hdl = sstore_alloc()) == NULL ||
             (b_hdl = sstore_batch_alloc()) == NULL) {
                 fprintf(stderr, "Failed to allocate handle or batch\n");
                 goto end;
         }

         /* batch a data read request */ 
         if (sstore_batch_data_read(hdl, b_hdl, (void *)"Data Read", ids,
             id_count, NULL, SSTORE_WALK_ID) != ESSTORE_OK) {
                 goto end;
         }

         /* batch an info read request */ 
         if (sstore_batch_info_read(hdl, b_hdl, (void *)"Info Read", ids,
             id_count, NULL) != ESSTORE_OK) {
                 goto end;
         }

         /* batch a namespace list request */ 
         if (sstore_batch_namespace_list(hdl, b_hdl, (void *)"Namespace List",
             ids, id_count, NULL) != ESSTORE_OK) {
                 goto end;
         }

         /* Make the batch call */
         if (sstore_batch_call(hdl, b_hdl, &b_iter) != ESSTORE_OK) {
                 goto end;
         }

         /* Print the results from the batch call */ 
         print_iter(b_iter);

         /* Free the batch iterator */
         sstore_iter_free(b_iter);

         ret = 0;

     end:
         if (hdl != NULL) {
                 print_error();
         }

         /* Free the libsstore handle */
         sstore_free(hdl);
    
         /* Free the batch handle */
         sstore_batch_free(b_hdl);

         return (ret);
     }


     Output:

     COOKIE: Data Read
            IDENTIFIER TIMESTAMP VALUE
           //:class.cpu//:stat.xcalls//:part.cpu(1,2) 1424815727000000

              1: 269287.0
              2: 419032.0

     COOKIE: Info Read
            IDENTIFIER TIMESTAMP VALUE
           //:class.cpu//:stat.xcalls//:part.cpu(1,2) 1424815728000000

                $schema: //:stat
              copyright: Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
            description: number of cross calls
              stability: stable
                     id: //:class.cpu//:stat.xcalls
               localize: description
             partitions: core
             partitions: chip
             partitions: pg
             partitions: lgroup
                   type: counter
             multiplier: 1000000
                  units: calls

     COOKIE: Namespace List
            IDENTIFIER START END
           //:class.cpu//:stat.xcalls//:part.cpu(1,2) UNKNOWN ACTIVE

Attributes

See attributes(7) for descriptions of the following attributes:

ATTRIBUTE TYPE
ATTRIBUTE VALUE
Interface Stability
Committed
MT-Level
Safe

See Also

libsstore(3LIB), sstore_alloc(3SSTORE), sstore_data_read(3SSTORE), sstore_err_action(3SSTORE), sstore_info_read(3SSTORE), sstore_namespace_list(3SSTORE), sstore_range_alloc(3SSTORE), attributes(7), ssid(7)