svcadm(8)을 검색하려면 섹션에서 8 을 선택하고, 맨 페이지 이름에 svcadm을 입력하고 검색을 누른다.
sstore_data_read(3sstore)
Solaris Statistics Store Library Functions sstore_data_read(3SSTORE)
NAME
sstore_data_read, sstore_data_iter_next - Read statistics and events
SYNOPSIS
cc [ flag... ] file... -lsstore [ library... ]
#include <libsstore.h>
sstore_err_t sstore_data_read(sstore_handle_t hdl,
const char **ids, uint32_t id_count,
sstore_range_t range, sstore_walk_t walk,
sstore_iter_t *iterp);
sstore_err_t sstore_data_iter_next(sstore_handle_t hdl,
sstore_iter_t iter, char **idp, uint64_t *timep,
sstore_value_t *valp);
PARAMETERS
hdl Handle to libsstore
ids Array of Statistics Store identifiers
id_count Total number of Statistics Store identifiers
range Time range or data range.
Passing NULL for range implies:
o start-time = SS_TIME_NOW
o end-time = SS_TIME_NOW
o step = (None - raw data)
walk Format of the iteration. The following formats are sup‐
ported:
SSTORE_WALK_ID Walks the data records by identifier
SSTORE_WALK_TS Walks the data records by timestamps
iterp Address to store the starting address of the iterator
returned from batch request execution
iter Iterator returned from the sstore_data_read() function.
idp Address to store the starting address of the Statistics
Store identifier.
timep Address to store the time in microseconds since epoch.
valp Address to store the handle to a typed value.
DESCRIPTION
The sstore_data_read() function retrieves the statistics and events
associated with the given identifiers and range. The retrieved data is
returned in the form of an iterator that can be used to read the data
records. Once all the data records have been read from the iterator,
the iterator must be freed using the sstore_iter_free(3SSTORE) func‐
tion.
If the start-time or end-time in the given range is SS_TIME_NOW, indi‐
cating that the range includes current time, then the
sstore_data_read() function also starts recording data for the ssids in
the ids array if they are not being recorded already. The
sstore_data_read() function continues to record this data for 300 sec‐
onds after the last sstore_data_read() function call for the given
ssids with a range that includes current time.
Data point interpolation may be applied for non-zero values of the step
parameter (gives the granularity in seconds). For more information, see
the sstore_range_alloc(3SSTORE) man page.
The value of the walk parameter determines the order in which the data
records are returned when you walk the iterator. The walk parameter can
have the following values:
SSTORE_WALK_ID Walks the result by Statistics Store identifier. For
each identifier, walks all the data records associ‐
ated with that identifier.
SSTORE_WALK_TS Walks the result by the time stamp of the data
records in chronological order.
The sstore_data_iter_next(3SSTORE) function retrieves the next data
record of the iteration. Each data record consists of an ssid, a time
stamp, and a value. The reference pointers passed to this call are pop‐
ulated if the call succeeds. The identifier, time stamp, and value pop‐
ulated on success do not need to be freed. They are freed on the next
call to the sstore_data_iter_next(3SSTORE) function.
AUTHORIZATIONS
See the sstore-security(7) man page for a description of the authoriza‐
tions required to read statistics.
RETURN VALUES
Upon successful completion, the sstore_data_read() and
sstore_data_iter_next() functions return ESSTORE_OK. Otherwise, they
return an error code, which is also cached in the given libsstore han‐
dle.
ERRORS
The sstore_data_read() function might return ESSTORE_ARG_INVALID,
ESSTORE_HANDLE_INVALID, ESSTORE_RETRY, ESSTORE_CONNECTION_FAILED,
ESSTORE_UNAUTHORIZED, ESSTORE_TOO_BIG, or ESSTORE_NOMEM.
The sstore_data_iter_next() function might return ESSTORE_ARG_INVALID,
ESSTORE_HANDLE_INVALID, or ESSTORE_ITER_DONE.
ESSTORE_NOMEM There is insufficient memory.
ESSTORE_ARG_INVALID One of the following reasons:
o Required arguments are missing.
o The format is not valid.
o The range is not valid.
ESSTORE_HANDLE_INVALID The libsstore handle is invalid.
ESSTORE_CONNECTION_FAILED Failed to connect to the statistics store
daemon.
ESSTORE_RETRY The statistics store daemon is busy. Retry
later.
ESSTORE_TOO_BIG The total size of all the resulting sta‐
tistics records is larger than the maximum
size limit set in libsstore handle.
WARNINGS
The sstore_data_read() function might set the following:
SS_WARN_INVALID SSID This is syntactically or semantically invalid.
SS_WARN_NOENT Unable to resolve the ssid.
EXAMPLES
Example 1 Reading CPU Statistics at Intervals
Read CPU statistics for CPU 0 for count times and sleep for interval
seconds between each read as follows:
#include <libsstore.h>
#include <stdio.h>
#include <unistd.h>
/* List of statistical identifiers */
const char *ids[] = {
"//:class.cpu//:stat.xcalls",
"//:class.cpu//:stat.usage//:part.mode(idle)",
"//:class.cpu//:stat.interrupt-//:s.[count,time]",
};
/* Total number of statistical identifiers */
uint32_t id_count = 3;
/* Number of seconds to sleep between 2 reads */
int interval = 1;
/* Number of times the statistics need to be read */
int count = 3;
sstore_handle_t hdl = NULL;
/*
* Prints the value in the value handle.
*/
int print_value(sstore_value_t val)
{
uint64_t val_u64;
char *keyp;
sstore_value_t valp;
switch(sstore_value_type(val)) {
case SSTORE_VALUE_NUMBER:
if (sstore_value_number(hdl, val, &val_u64) != ESSTORE_OK) {
return (sstore_err_code(hdl));
}
printf("%llu\n", val_u64);
break;
case SSTORE_VALUE_DICTIONARY:
while (sstore_value_dictionary_next(hdl, val, &keyp,
&valp) == ESSTORE_OK) {
(void) printf("%s ", keyp);
(void) print_value(valp);
}
break;
case SSTORE_VALUE_NODATA:
printf("NO_DATA\n");
break;
default:
printf("Invalid value type %d\n", sstore_value_type(val));
}
return (ESSTORE_OK);
}
/*
* Reads and iterate through the statistics for the given identifiers
* every second for 'count' number of times.
*/
void read_data()
{
sstore_iter_t iter = NULL;
sstore_value_t val;
int i = 0;
char *id, *desc;
uint64_t ts;
printf("%-58s %-16s %s\n", "IDENTIFIER", "TIMESTAMP", "VALUE");
while (i++ < count) {
/* Read the most recent value for the given identifiers */
if (sstore_data_read(hdl, ids, id_count, NULL, SSTORE_WALK_ID,
&iter) != ESSTORE_OK)
break;
/* Check and print any warnings */
while (sstore_warning_next(hdl, &id, &desc) != SS_WARN_OK) {
fprintf(stderr, "Failed to read stats for %s. Error: %s\n",
id, desc);
}
/* Iterate and print the returned statistical records */
while (sstore_data_iter_next(hdl, iter, &id, &ts,
&val) == ESSTORE_OK) {
printf("%-58s %16llu ", id, ts);
if (print_value(val) != ESSTORE_OK)
break;
}
/* Free the iterator */
sstore_iter_free(iter);
iter = NULL;
/* Check if the iteration was successful */
if (sstore_err_code(hdl) != ESSTORE_ITER_DONE)
break;
sleep(interval);
printf("\n");
}
/* Check for errors */
if (sstore_err_code(hdl) != ESSTORE_OK &&
sstore_err_code(hdl) != ESSTORE_ITER_DONE) {
sstore_iter_free(iter);
fprintf(stderr, "%s. Error: %s.\n", sstore_err_action(hdl),
sstore_err_description(hdl));
}
}
int main()
{
/* Allocate a libsstore handle */
if ((hdl = sstore_alloc()) == NULL) {
printf("Failed to allocate handle\n");
return (-1);
}
/* Read and print the statistics */
read_data();
/* Free the libsstore handle */
sstore_free(hdl);
return (0);
}
Output:
IDENTIFIER TIMESTAMP VALUE
//:class.cpu//:stat.xcalls 1424815728214187 68027
//:class.cpu//:stat.usage//:part.mode(idle) 1424815727214132 idle 3206077270089
//:class.cpu//:stat.interrupt-count 1424815728960968 total 1479974
//:class.cpu//:stat.interrupt-time 1424815728960968 total 5329198050
//:class.cpu//:stat.xcalls 1424815728214187 68027
//:class.cpu//:stat.usage//:part.mode(idle) 1424815728214187 idle 3207073755382
//:class.cpu//:stat.interrupt-count 1424815728960968 total 1479974
//:class.cpu//:stat.interrupt-time 1424815728960968 total 5329198050
//:class.cpu//:stat.xcalls 1424815729214360 68053
//:class.cpu//:stat.usage//:part.mode(idle) 1424815729214360 idle 3208069183506
//:class.cpu//:stat.interrupt-count 1424815729214363 total 1480104
//:class.cpu//:stat.interrupt-time 1424815729214363 total 5329702612
Example 2 Reading Historical CPU Statistics and Walking the Result
Read historical statistics for CPU 0 and walk the result with different
walk types as follows:
#include <libsstore.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#define MICRO 1000000
/* List of statistical identifiers */
const char *ids[] = {
"//:class.cpu//:stat.usage",
"//:class.cpu//:stat.xcalls",
};
/* Total number of statistical identifiers */
uint32_t id_count = 2;
/* Interval for data capture */
int interval = 3;
sstore_handle_t hdl = NULL;
/*
* Prints the value in the value handle.
*/
int print_value(sstore_value_t val)
{
uint64_t val_u64;
double val_real;
char *keyp;
sstore_value_t valp;
switch(sstore_value_type(val)) {
case SSTORE_VALUE_NUMBER:
if (sstore_value_number(hdl, val, &val_u64) != ESSTORE_OK) {
return (sstore_err_code(hdl));
}
printf("%llu\n", val_u64);
break;
case SSTORE_VALUE_REAL:
if (sstore_value_real(hdl, val, &val_real) != ESSTORE_OK) {
return (sstore_err_code(hdl));
}
printf("%6.2f\n", val_real);
break;
case SSTORE_VALUE_DICTIONARY:
while (sstore_value_dictionary_next(hdl, val, &keyp,
&valp) == ESSTORE_OK) {
(void) printf("%s ", keyp);
(void) print_value(valp);
}
break;
case SSTORE_VALUE_NODATA:
printf("NO_DATA\n");
break;
default:
printf("Invalid value type %d\n", sstore_value_type(val));
}
return (ESSTORE_OK);
}
/*
* Reads and iterate through the statistics for the given identifiers
* every second for 'count' number of times.
*/
void read_data(sstore_range_t range, sstore_walk_t walk,
int print_data)
{
sstore_iter_t iter = NULL;
sstore_value_t val;
char *id, *desc;
uint64_t ts;
/* Read the statistics collected during the interval */
if (sstore_data_read(hdl, ids, id_count, range, walk,
&iter) != ESSTORE_OK)
goto error;
/* Check if we need to print the data */
if (print_data == 0)
goto cleanup;
/* Iterate through data records and print */
printf("%-42s %-16s %s\n", "IDENTIFIER", "TIMESTAMP", "VALUE");
while (sstore_data_iter_next(hdl, iter, &id, &ts,
&val) == ESSTORE_OK) {
/* Round out the times */
ts = (ts / MICRO) * MICRO;
printf("%-42s %16llu ", id, ts);
if (print_value(val) != ESSTORE_OK)
goto cleanup;
}
cleanup:
/* Free the iterator */
sstore_iter_free(iter);
if (sstore_err_code(hdl) == ESSTORE_OK ||
sstore_err_code(hdl) == ESSTORE_ITER_DONE)
return;
error:
fprintf(stderr, "%s. Error: %s\n", sstore_err_action(hdl),
sstore_err_description(hdl));
}
int main()
{
uint64_t init_time, start_time, end_time, step;
sstore_range_t range = NULL;
if ((init_time = time(NULL)) == (time_t)-1) {
fprintf(stderr, "Could not find time\n");
return (-1);
}
/* Allocate a libsstore handle */
if ((hdl = sstore_alloc()) == NULL) {
fprintf(stderr, "Failed to allocate handle\n");
return (-1);
}
/* Allocate a range struct */
if ((range = sstore_range_alloc()) == NULL) {
sstore_free(hdl);
fprintf(stderr, "Failed to allocate range\n");
return (-1);
}
/*
* Start a dynamic log job to record stats in sstored.
* Wait 'interval' seconds to allow some data to be collected.
*
* Note: Passing NULL for 'range' implies start = SS_TIME_NOW,
* end = SS_TIME_NOW and step = 1.
*/
printf("Capturing data for %d seconds...\n", interval);
read_data(NULL, SSTORE_WALK_ID, 0);
sleep(interval);
/* Convert init_time into microseconds and get the time range */
start_time = init_time * MICRO;
end_time = ((init_time + interval) * MICRO) - 1;
step = 1;
/*
* Initialize the range struct
* Note: The following call will not fail since we are
* reusing the range struct allocated earlier.
*/
range = sstore_range_by_time(range, start_time, end_time, step);
/* Read and print the statistics while walking by ID */
printf("\nWalking data by TS...\n");
read_data(range, SSTORE_WALK_TS, 1);
/* Read and print the statistics while walking by TS */
printf("\nWalking data by ID...\n");
read_data(range, SSTORE_WALK_ID, 1);
/* Free the libsstore handle */
sstore_free(hdl);
/* Free the range struct */
sstore_range_free(range);
return (0);
}
Output:
Capturing data for 3 seconds...
Walking data by TS...
IDENTIFIER TIMESTAMP VALUE
//:class.cpu//:stat.usage 1424815732000000 total 3243831735969
//:class.cpu//:stat.xcalls 1424815732000000 68122.89
//:class.cpu//:stat.usage 1424815733000000 total 3244833333130
//:class.cpu//:stat.xcalls 1424815733000000 80431.19
//:class.cpu//:stat.usage 1424815734000000 total 3244833333587
//:class.cpu//:stat.xcalls 1424815734000000 80629.86
Walking data by ID...
IDENTIFIER TIMESTAMP VALUE
//:class.cpu//:stat.usage 1424815732000000 total 3243831735969
//:class.cpu//:stat.usage 1424815733000000 total 3244833333130
//:class.cpu//:stat.usage 1424815734000000 total 3244833333587
//:class.cpu//:stat.xcalls 1424815732000000 68122.89
//:class.cpu//:stat.xcalls 1424815733000000 80431.19
//:class.cpu//:stat.xcalls 1424815734000000 80629.86
ATTRIBUTES
See the attributes(7) man page for descriptions of the following
attributes:
tab() box; cw(2.75i) |cw(2.75i) lw(2.75i) |lw(2.75i) ATTRIBUTE TYPEAT‐
TRIBUTE VALUE _ Availabilitypkg:/service/system/sstore _ Interface Sta‐
bilityCommitted _ MT-LevelSafe
SEE ALSO
libnvpair(3LIB), libsstore(3LIB), sstore_alloc(3SSTORE),
sstore_data_attach(3SSTORE), sstore_err_action(3SSTORE),
sstore_range_alloc(3SSTORE), attributes(7), privileges(7), sstore(7),
sstore-security(7)
Oracle Solaris 11.4 19 May 2017 sstore_data_read(3SSTORE)