svcadm(8)을 검색하려면 섹션에서 8 을 선택하고, 맨 페이지 이름에 svcadm을 입력하고 검색을 누른다.
sstore_data_attach(3sstore)
Solaris Statistics Store Library Functions
sstore_data_attach(3SSTORE)
NAME
sstore_data_attach, sstore_data_attach_histogram, sstore_data_update,
sstore_data_alloc, sstore_data_free, sstore_data_reset,
sstore_data_bulk_update - provide statistics to sstored
SYNOPSIS
cc [ flag... ] file... -lsstore [ library... ]
#include <libsstore.h>
typedef struct sstore_data *sstore_data_t;
sstore_err_t sstore_data_attach(sstore_handle_t hdl,
const char **ids, uint32_t id_count, uint64_t **addrs);
sstore_err_t sstore_data_attach_histogram(sstore_handle_t hdl,
const char *id, sstore_histogram_t hist);
sstore_err_t sstore_data_update(sstore_handle_t hdl,
const char **ids, uint32_t id_count,
sstore_value_t *vals);
sstore_data_t sstore_data_alloc(void);
void sstore_data_free(sstore_data_t data);
void sstore_data_reset(sstore_data_t data);
sstore_err_t sstore_data_add(sstore_handle_t hdl,
sstore_data_t data, uint64_t ts,
sstore_value_t val);
sstore_err_t sstore_data_bulk_update(sstore_handle_t hdl,
const char **ids, uint32_t id_count,
sstore_data_t *data_arr);
PARAMETERS
hdl Handle to libsstore
ids Array of statistics store identifiers
id_count Total number of statistics store identifiers
id Statistic store identifier associated with the histogram
hist sstore_histogram_t to be memory-mapped
vals Array of values corresponding to the array of statistics
store identifiers
addrs Address to store the starting address of the shared-memory
region in the statistics store daemon
data sstore_data_t containing the data points for a statistic
ts Timestamp in microseconds since epoch
val Value for a statistic at a given timestamp
data_arr Array of sstore_data_t's corresponding to the array of sta‐
tistics store identifiers
DESCRIPTION
The statistics store provides three methods of updating statistics from
a user application: sstore_data_attach(), sstore_data_update(), and
sstore_data_bulk_update().
The sstore_data_attach() function is an init routine for counter-type
numeric statistics that sets up a shared-memory region between
sstored(8) and the client process. Only one call to this function is
necessary during the runtime of a client process, after which updates
to the stats can be made directly within the shared-memory region.
The sstore_data_attach() function performs the following tasks:
o Sets up an array of uint64_t shared between the calling
process and the sstored daemon.
o Stores the starting address of this shared array in addrs on
success.
o Enables any resources in the given ssid that are defined
statically and are not currently enabled. For more informa‐
tion about statically defined resources, see the sstore(7)
man pages.
o Marks statistics in the given ssids as actively provided.
An ssid at index i in the ids array maps to the i'th element in the
addrs array.
For example, to update the value of ids[i] with val:
addrs[i] = val;
The sstore_data_attach_histogram(), like the sstore_data_attach() func‐
tion, sets up a shared-memory region between sstored(8) and the client
process. However, instead of mapping a single counter per statistic, it
maps an array of counters corresponding to the buckets in the given
histogram. The sstore_histogram_t can then be updated using sstore_his‐
togram_quantize(3SSTORE) and the relevant counter will be updated in
the shared memory region.
Note that simply updating the values does not have any impact on
sstored(8), and these values are not actually sampled until asked for
either through sstore_data_read(3SSTORE) or sstore(1). For more infor‐
mation, see the sstore_data_read(3SSTORE) man page for a description of
what trigger data capture in the daemon.
Once capture begins, however, sstore attempts to read from the shared-
memory region every second regardless of how quickly the provider
updates the value.
Statistics that are updated using the shared-memory method remain
mapped by the statistics store daemon until the client either dies or
frees the libsstore handle that was used in the sstore_data_attach()
call. If the client restarts, then the client must reinitialize the
shared memory region with the same statistic ordering as before to be
able to provide the statistics again. If the client does not use the
same ordering, then the call to the sstore_data_attach() function will
fail. If the statistics store daemon restarts but the client does not,
the client does not need to reinitialize the shared-memory region.
The sstore_data_update() function allows users to update values of
their application statistics for all types of data. This interface is
provided for string or other large data types that cannot be written to
shared-memory safely without some additional synchronization mechanism.
An sstore_data_update() call must be made each time the client wants a
value update.
The sstore_data_update() function performs the following tasks:
o Updates the value of the given ssids with the given values.
There is a one to one relationship between the ssids in ids
and the values in data.
o Enables any resources in the given ssid that are defined
statically and are not currently enabled. See the sstore(7)
man page for information about statically defined resources.
o Marks statistics in the given ssids as actively provided.
The sstore_data_bulk_update() function allows users to provide multiple
data points, that is, a set of (timestamp, value) pairs for a statistic
at once. This removes the requirement of providing statistics in real
time since the user can provide the timestamp along with the value.
However, the data points provided must be in chronological order and
hence the client can only provide data points that are more recent than
data points that were provided earlier. Any data point that does not
meet the above requirement will be ignored.
Any statistic for which data will be provided using this interface also
needs to define "min-update-interval", which is the minimum number of
seconds between two bulk updates, in its metadata. This field is just a
pass-through interface for the consumers like webui(), to set some
expectations about the update frequency of a statistic. For more infor‐
mation, see the webui(7) man page.
The sstore_data_bulk_update() function performs the following tasks:
o Enables any resources in the given ssid that are defined
statically and are not currently enabled. For more informa‐
tion about statically defined resources, see the sstore(7))
man pages.
Sampling behavior for the sstore_data_update() and
sstore_data_bulk_update() functions are identical to the
sstore_data_attach() function. Most importantly, values are only
recorded when asked for by the sstore_data_read() function or when per‐
sistently enabled. Once it starts recording, a statistic updated
through the sstore_data_update() function will be sampled every second
using the value received in the most recent update as opposed to a
statistic updated through the sstore_data_bulk_update() function which
will be sampled as the new data points become available from the
statistic provider. For more information on the sampling behaviour, see
the sstore_data_read(3SSTORE) man page.
The sstore_data_t is used to provide one or more data points for a
statistic using the sstore_data_bulk_update() function.
The sstore_data_alloc() function allocates and returns an
sstore_data_t.
The sstore_data_free()function frees the given sstore_data_t and all
the data points stored in it.
The sstore_data_reset() function frees all the data points stored in
sstore_data_t and resets it back the state when it was alloc'd. This
interface allows the client to reuse an sstore_date_t for subsequent
calls to sstore_data_bulk_update() function.
The sstore_data_add() function adds a new data point, a timestamp and a
value, to sstore_data_t. The data points must be added in chronological
order. The sstore_data_add() function makes a copy of the given val, so
it can be reused for the next data point.
AUTHORIZATIONS
For a description on the authorizations required to provide and update
statistics, see the sstore-security(7) man page.
RETURN VALUES
Upon successful completion, sstore_data_update(), and
sstore_data_attach() return ESSTORE_OK. Otherwise, they return an error
code, which is cached in the given libsstore handle.
ERRORS
The sstore_data_update() and sstore_data_attach() functions fail if:
ESSTORE_NOMEM No memory is available
ESSTORE_ARG_INVALID One of the following reasons:
o Required arguments are missing
o Metadata is not available
o A provider already exists for
at least one of the ssids
o The data type does not match
the metadata
o An ssid is invalid
o An ssid contains a wildcard or
slice
o An ssid is not a user space
statistic or event
ESSTORE_HANDLE_INVALID The handle is invalid
ESSTORE_RETRY The statistics store daemon is busy. Retry
later
ESSTORE_CONNECTION_FAILED Failed to connect to the statistics store
daemon
ESSTORE_UNAUTHORIZED The caller is not authorized. For more
information, see the sstore-security(7)
man page
The sstore_data_add() function fails if:
ESSOTE_ARG_INVALID One of the following reasons:
o Required arguments are missing
o Data point is not in chronological
order
o Data point value does not have same
data type as the other data points in
sstore_data_t
EXAMPLES
Example 1 Using sstore_data_attach()
The following metadata files, installed in /usr/lib/sstore/meta‐
data/json/solaris, are required for this example:
o class.app.solaris.exapp.json
o stat.app.solaris.exapp.stat1.json
o stat.app.solaris.exapp.stat2.json
After installing the files, svc:/system/sstore:default must be
restarted.
class.app.solaris.exapp.json:
{
"$schema": "//:class",
"description": "Example class",
"id": "app/solaris/exapp",
"namespaces": [
{
"name-type": "string",
"resource-name": "name"
}
],
"stability": "stable",
"static-instances": [
{
"name": "exapp/ins",
"namespace": "name"
}
],
"stat-names": [
"//:stat.stat1",
"//:stat.stat2"
]
}
stat.app.solaris.exapp.stat1.json:
{
"$schema": "//:stat",
"description": "Example count statistic one",
"id": "//:class.app/solaris/exapp//:stat.stat1",
"stability": "stable",
"type": "counter",
"units": "calls"
}
stat.app.solaris.exapp.stat2.json:
{
"$schema": "//:stat",
"description": "Example count statistic one",
"id": "//:class.app/solaris/exapp//:stat.stat2",
"stability": "stable",
"type": "counter",
"units": "calls"
}
The example program, attach_example.c:
/*
* Program to provide statistics values
*/
#include <libsstore.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
/* libsstore handle */
sstore_handle_t hdl;
/* statistic identifiers */
char *ids[] = {
"//:class.app/solaris/exapp//:res.name/exapp/ins//:stat.stat1",
"//:class.app/solaris/exapp//:res.name/exapp/ins//:stat.stat2"
};
/* structure where values are stored */
struct mystats {
uint64_t stat1;
uint64_t stat2;
};
int main()
{
int iterations = 10;
struct mystats *stats;
/* Allocate a libsstore handle */
if ((hdl = sstore_alloc()) == NULL) {
(void) printf("Failed to allocate handle\n");
return (-1);
}
/*
* These statistics already have metadata in a common location,
* so sstore knows how to create them. sstore_data_attach will
* create a shared-memory region between sstore and this program.
*/
if (sstore_data_attach(hdl, (const char **)&ids, 2,
(uint64_t **)&stats) != ESSTORE_OK) {
(void) fprintf(stderr,
"Received result message\n\t%s\nfrom sstored "
"in sstore_data_attach\n",
sstore_err_description(hdl));
return (-1);
}
/*
* Update the values in the structure. The new values will be
* stored when sstore reads them.
*/
while (iterations-- > 0) {
stats->stat1++;
stats->stat2 += 3;
sleep(1);
}
/*
* Free the libsstore handle.
* The statistics are marked as not being actively provided.
*/
sstore_free(hdl);
return (0);
}
Compile this program as follows:
$ cc -o attach_example attach_example.c -lsstore
Once the stats store has been restarted, run the following
command in one terminal to observe the effect of running the
attach_example program in another terminal:
$ sstore capture //:class.app/solaris/exapp//:*//:*
The attach_example program must either be run as root, or a
user with appropriate stats store privileges. See sstore-security(7)
for a description of the authorizations required to provide
and update statistics.
Example 2 Update counter type stats using sstore_data_update()
The following metadata files must be installed in /usr/lib/sstore/meta‐
data/json/solaris, are required for this example:
o class.example.json
o stat.example.json
After installing the files, svc:/system/sstore:default must be
restarted.
class.example.json:
{
"$schema": "//:class",
"description": "example class",
"id": "example",
"stability": "stable",
"stat-names": [
"//:stat.one",
"//:stat.two"
]
}
stat.example.json:
[
{
"$schema": "//:stat",
"description": "example stat one",
"id": "//:class.example//:stat.one",
"stability": "stable",
"type": "counter",
"units": "calls"
},
{
"$schema": "//:stat",
"description": "example stat two",
"id": "//:class.example//:stat.two",
"stability": "stable",
"type": "counter",
"units": "calls"
}
]
/*
* Example program data_update.c:
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libsstore.h>
#define NUM_STATS 2
const char *ssids[NUM_STATS] = {
"//:class.example//:stat.one",
"//:class.example//:stat.two"
};
int main()
{
sstore_handle_t hdl;
sstore_value_t vals[NUM_STATS] = {0};
int i, j;
if ((hdl = sstore_alloc()) == NULL) {
fprintf(stderr, "Failed to alloc libsstore handle\n");
return (-1);
}
/* Alloc the sstore_value_t's */
for (i = 0; i < NUM_STATS; i++) {
if ((vals[i] = sstore_value_alloc()) == NULL) {
fprintf(stderr, "Failed to alloc sstore_value_t\n");
goto end;
}
vals[i]->sv_type = SSTORE_VALUE_NUMBER;
}
/* Update the stats every second */
for (i = 0;; i++) {
char *id, *desc;
for (j = 0; j < NUM_STATS; j++) {
vals[j]->sv_value.num += j + 1;
}
if (sstore_data_update(hdl, ssids, NUM_STATS,
vals) != ESSTORE_OK) {
fprintf(stderr, "Failed to update stats. "
"Reason: %s\n", sstore_err_description(hdl));
break;
}
/* Check warnings */
while (sstore_warning_next(hdl, &id,
&desc) != SS_WARN_OK) {
fprintf(stderr, "failed to update stat for %s "
"because %s\n", id, desc);
}
sleep(1);
}
end:
for (i = 0; i < NUM_STATS; i++) {
sstore_value_free(vals[i]);
}
sstore_free(hdl);
return (0);
}
Compile this program as follows:
$ cc -o data_update -lsstore data_update.c
Once the sstore has restarted after installing the metadata,
run 'data_update' as root or as a user with appropriate stats
store authorizations. See sstore-security(5) for a description
of the authorizations required to provide and update
statistics.
In another terminal, start recording the stats updated via
data_update as follows:
$ sstore capture //:class.example//:stat.*
Sample output:
$ sstore capture //:class.example//:stat.*
TIME VALUE IDENTIFIER
2016-03-31T13:36:12 6 //:class.example//:stat.one
2016-03-31T13:36:12 12 //:class.example//:stat.two
2016-03-31T13:36:13 7 //:class.example//:stat.one
2016-03-31T13:36:13 14 //:class.example//:stat.two
2016-03-31T13:36:14 8 //:class.example//:stat.one
2016-03-31T13:36:14 16 //:class.example//:stat.two
Example 3 Update partitioned stat using sstore_data_update()
The following metadata files, installed in /usr/lib/sstore/meta‐
data/json/solaris, are required for this example:
o class.example_partition.json
o stat.example_partition.json
After installing the files, svc:/system/sstore:default must be
restarted.
class.example_partition.json:
{
"$schema": "//:class",
"description": "example class",
"id": "example/partition",
"stability": "stable",
"stat-names": [
"//:stat.one"
]
}
stat.example_partition.json
{
"$schema": "//:stat",
"description": "example stat one",
"id": "//:class.example/partition//:stat.one",
"partitions": [
"name",
"place"
],
"stability": "stable",
"type": "counter",
"units": "calls"
}
/*
* Example program data_update_partition.c:
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libsstore.h>
#define NUM_STATS 1
#define NUM_PARTS 2
#define NUM_KEYS 3
const char *ssids[NUM_STATS] = {
"//:class.example/partition//:stat.one"
};
const char *example_keys[NUM_PARTS][NUM_KEYS] = {
{ "john", "tom", "bill" },
{ "home", "work", "party" }
};
int
main()
{
sstore_handle_t hdl;
sstore_value_t val = NULL;
sstore_partition_t part = NULL;
int i, j;
if ((hdl = sstore_alloc()) == NULL) {
fprintf(stderr, "Failed to alloc libsstore handle\n");
return (-1);
}
/* Alloc sstore_partition_t */
if ((part = sstore_partition_alloc(NUM_PARTS)) == NULL) {
fprintf(stderr, "Failed to alloc sstore_partition_t\n");
goto end;
}
/* Alloc and init sstore_value_t */
if ((val = sstore_value_alloc()) == NULL) {
fprintf(stderr, "Failed to alloc sstore_value_t\n");
goto end;
}
val->sv_type = SSTORE_VALUE_PARTITION;
val->sv_value.part = part;
/* Update the stats every second */
for (i = 0;; i++) {
char *id, *desc;
char *keys[NUM_PARTS] = {0};
uint64_t part_val = i;
for (j = 0; j < NUM_PARTS; j++) {
keys[j] = (char *)example_keys[j][(i + j) % NUM_KEYS];
}
if (sstore_partition_inc_value(hdl, part, (const char **)keys,
part_val) != ESSTORE_OK) {
fprintf(stderr, "Failed to increment partition "
"value. Reason: %s\n",
sstore_err_description(hdl));
break;
}
if (sstore_data_update(hdl, ssids, NUM_STATS,
&val) != ESSTORE_OK) {
fprintf(stderr, "Failed to update stats. "
"Reason: %s\n",
sstore_err_description(hdl));
break;
}
/* Check warnings */
while (sstore_warning_next(hdl, &id, &desc) != SS_WARN_OK) {
fprintf(stderr, "failed to update stat for %s "
"because %s\n", id, desc);
}
sleep(1);
}
end:
sstore_partition_free(part);
sstore_value_free(val);
sstore_free(hdl);
return (0);
}
Compile this program as follows:
$ cc -o data_update_partition -lsstore data_update_partition.c
Once the sstore has restarted after installing the metadata,
run 'data_update_partition' as root or as a user with appropriate
stats store authorizations. See sstore-security(5) for a
description of the authorizations required to provide and update
statistics.
In another terminal, start recording the stats updated via
data_update as follows:
sstore capture //:class.example/partition//:stat.one
sstore capture //:class.example/partition//:stat.one//:part.name
sstore capture //:class.example/partition//:stat.one//:part.place
sstore capture "//:class.example/partition//:stat.one//:part.place(party)//:part.name"
Sample output:
$ sstore capture //:class.example/partition//:stat.one
TIME VALUE IDENTIFIER
2016-04-11T17:03:27 703.0 //:class.example/partition//:stat.one
2016-04-11T17:03:28 741.0 //:class.example/partition//:stat.one
2016-04-11T17:03:29 780.0 //:class.example/partition//:stat.one
$ sstore capture //:class.example/partition//:stat.one//:part.name
TIME VALUE IDENTIFIER
2016-04-11T17:03:32 //:class.example/partition//:stat.one//:part.name
john: 315.0
tom: 287.0
bill: 301.0
$ sstore capture //:class.example/partition//:stat.one//:part.place
TIME VALUE IDENTIFIER
2016-04-11T17:03:35 //:class.example/partition//:stat.one//:part.place
work: 360.0
party: 330.0
home: 345.0
2016-04-11T17:03:36 //:class.example/partition//:stat.one//:part.place
work: 360.0
party: 376.0
home: 345.0
$ sstore capture "//:class.example/partition//:stat.one//:part.place(party)//:part.name"
TIME VALUE IDENTIFIER
2016-04-11T17:03:52 //:class.example/partition//:stat.one//:part.place(party)//:part.name
tom: 651.0
2016-04-11T17:03:53 //:class.example/partition//:stat.one//:part.place(party)//:part.name
tom: 651.0
Example 4 Update counter type stats using sstore_data_bulk_update()
The following metadata files, installed in /usr/lib/sstore/meta‐
data/json/solaris, are required for this example:
o class.example_bulk.json
o stat.example_bulk.json
After installing the files, svc:/system/sstore:default must be
restarted.
class.example_bulk.json:
{
"$schema": "//:class",
"description": "example class",
"id": "example/bulk",
"stability": "stable",
"stat-names": [
"//:stat.one",
"//:stat.two"
]
}
stat.example_bulk.json:
[
{
"$schema": "//:stat",
"description": "example stat one",
"id": "//:class.example/bulk//:stat.one",
"min-update-interval": 10,
"stability": "stable",
"type": "counter",
"units": "calls"
},
{
"$schema": "//:stat",
"description": "example stat two",
"id": "//:class.example/bulk//:stat.two",
"min-update-interval": 10,
"stability": "stable",
"type": "counter",
"units": "calls"
}
]
/*
* Example program data_bulk_update.c:
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libsstore.h>
#define SEC_TO_uSEC(secs) ((secs)*1000000)
#define NUM_STATS 2
#define SLEEP_INTERVAL 10
const char *ssids[NUM_STATS] = {
"//:class.example/bulk//:stat.one",
"//:class.example/bulk//:stat.two"
};
/*
* Gets the current timestamp in microseconds since epoch
*/
uint64_t
get_current_ts(void)
{
struct timeval tp = {0};
(void) gettimeofday(&tp, NULL);
return (SEC_TO_uSEC((uint64_t)tp.tv_sec) + ((uint64_t)tp.tv_usec));
}
int
main()
{
sstore_handle_t hdl;
sstore_value_t vals[NUM_STATS] = {0};
sstore_data_t data[NUM_STATS] = {0};
uint64_t now_ts = get_current_ts();
int i, j;
if ((hdl = sstore_alloc()) == NULL) {
fprintf(stderr, "Failed to alloc libsstore handle\n");
return (-1);
}
/* Alloc the sstore_value_t and sstore_data_t's */
for (i = 0; i < NUM_STATS; i++) {
if ((vals[i] = sstore_value_alloc()) == NULL) {
fprintf(stderr, "Failed to alloc sstore_value_t\n");
goto end;
}
vals[i]->sv_type = SSTORE_VALUE_NUMBER;
if ((data[i] = sstore_data_alloc()) == NULL) {
fprintf(stderr, "Failed to alloc sstore_data_t\n");
goto end;
}
}
/*
* Bulk update data points for last SLEEP_INTERVAL seconds for
* each stat
*/
while (1) {
char *id, *desc;
uint64_t ts = now_ts - SEC_TO_uSEC(SLEEP_INTERVAL);
/* Add data points for each stat */
for (i = 0; i < SLEEP_INTERVAL; i++, ts += 1000000) {
for (j = 0; j < NUM_STATS; j++) {
vals[j]->sv_value.num += i + j + 1;
if (sstore_data_add(hdl, data[j], ts,
vals[j]) != ESSTORE_OK) {
fprintf(stderr, "Failed to add "
"data point. Reason %s\n",
sstore_err_description(hdl));
goto end;
}
}
}
/* bulk update */
if (sstore_data_bulk_update(hdl, ssids, NUM_STATS,
data) != ESSTORE_OK) {
fprintf(stderr, "Failed to bulk update. "
"Reason %s\n",
sstore_err_description(hdl));
goto end;
}
/*
* Reset sstore_data_t to avoid resending the same data
* points again
*/
for (i = 0; i < NUM_STATS; i++) {
sstore_data_reset(data[i]);
}
/* Check warnings */
while (sstore_warning_next(hdl, &id, &desc) != SS_WARN_OK) {
fprintf(stderr, "failed to bulk update stat for %s "
"because %s\n", id, desc);
}
sleep(SLEEP_INTERVAL);
now_ts += SEC_TO_uSEC(SLEEP_INTERVAL);
}
end:
for (i = 0; i < NUM_STATS; i++) {
sstore_value_free(vals[i]);
sstore_data_free(data[i]);
}
sstore_free(hdl);
return (0);
}
Compile this program as follows:
$ cc -o data_bulk_update -lsstore data_bulk_update.c
Once the sstore has restarted after installing the metadata,
run 'data_bulk_update' as root or as a user with appropriate stats
store authorizations. See sstore-security(5) for a description
of the authorizations required to provide and update
statistics.
In another terminal, start recording the stats updated via
data_bulk_update as follows:
$ sstore capture //:class.example/bulk//:stat.*
Sample output:
$ sstore capture //:class.example/bulk//:stat.* 10
TIME VALUE IDENTIFIER
2016-04-11T17:52:06 220 //:class.example/bulk//:stat.one
2016-04-11T17:52:06 260 //:class.example/bulk//:stat.two
2016-04-11T17:52:16 275 //:class.example/bulk//:stat.one
2016-04-11T17:52:16 325 //:class.example/bulk//:stat.two
2016-04-11T17:52:26 330 //:class.example/bulk//:stat.one
2016-04-11T17:52:26 390 //:class.example/bulk//:stat.two
Example 5 Update partitioned stat using sstore_data_bulk_update()
The following metadata files, installed in /usr/lib/sstore/meta‐
data/json/solaris, are required for this example:
o class.example_bulk_partition.json
o stat.example_bulk_partition.json
After installing the files, svc:/system/sstore:default must be
restarted.
class.example_bulk_partition.json:
{
"$schema": "//:class",
"description": "example class",
"id": "example/bulk/partition",
"stability": "stable",
"stat-names": [
"//:stat.one"
]
}
stat.example_bulk_partition.json
{
"$schema": "//:stat",
"description": "example stat one",
"id": "//:class.example/bulk/partition//:stat.one",
"min-update-interval": 10,
"partitions": [
"name",
"place"
],
"stability": "stable",
"type": "counter",
"units": "calls"
}
/*
* Example program data_bulk_update_partition.c:
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libsstore.h>
#define SEC_TO_uSEC(secs) ((secs)*1000000)
#define NUM_STATS 1
#define NUM_PARTS 2
#define NUM_KEYS 3
#define SLEEP_INTERVAL 10
const char *ssids[NUM_STATS] = {
"//:class.example/bulk/partition//:stat.one"
};
const char *example_keys[NUM_PARTS][NUM_KEYS] = {
{ "john", "tom", "bill" },
{ "home", "work", "party" }
};
/*
* Gets the current timestamp in microseconds since epoch
*/
uint64_t
get_current_ts(void)
{
struct timeval tp = {0};
(void) gettimeofday(&tp, NULL);
return (SEC_TO_uSEC((uint64_t)tp.tv_sec) + ((uint64_t)tp.tv_usec));
}
int
main()
{
sstore_handle_t hdl;
sstore_data_t data = NULL;
sstore_value_t val = NULL;
sstore_partition_t part = NULL;
uint64_t now_ts = get_current_ts();
int i, j;
if ((hdl = sstore_alloc()) == NULL) {
fprintf(stderr, "Failed to alloc libsstore handle\n");
return (-1);
}
/* Alloc sstore_partition_t */
if ((part = sstore_partition_alloc(NUM_PARTS)) == NULL) {
fprintf(stderr, "Failed to alloc sstore_partition_t\n");
goto end;
}
/* Alloc sstore_data_t */
if ((data = sstore_data_alloc()) == NULL) {
fprintf(stderr, "Failed to alloc sstore_data_t\n");
goto end;
}
/* Alloc and init sstore_value_t */
if ((val = sstore_value_alloc()) == NULL) {
fprintf(stderr, "Failed to alloc sstore_value_t\n");
goto end;
}
val->sv_type = SSTORE_VALUE_PARTITION;
val->sv_value.part = part;
/* bulk update the stat */
while (1) {
char *id, *desc;
char *keys[NUM_PARTS] = {0};
uint64_t ts = now_ts - SEC_TO_uSEC(SLEEP_INTERVAL);
/* Add data points for the last SLEEP_INTERVAL seconds */
for (i = 0; i < SLEEP_INTERVAL; i++, ts += 1000000) {
uint64_t part_val = i;
for (j = 0; j < NUM_PARTS; j++) {
keys[j] = (char *)example_keys[j][(i + j) % NUM_KEYS];
}
if (sstore_partition_inc_value(hdl, part, (const char **)keys,
part_val) != ESSTORE_OK) {
fprintf(stderr, "Failed to increment partition "
"value. Reason: %s\n",
sstore_err_description(hdl));
break;
}
if (sstore_data_add(hdl, data, ts, val) != ESSTORE_OK) {
fprintf(stderr, "Failed to add data point. "
"Reason %s\n",
sstore_err_description(hdl));
goto end;
}
}
/* bulk update */
if (sstore_data_bulk_update(hdl, ssids, NUM_STATS,
&data) != ESSTORE_OK) {
fprintf(stderr, "Failed to bulk update stat. "
"Reason: %s\n",
sstore_err_description(hdl));
break;
}
/*
* Reset sstore_data_t to avoid resending the same data
* points again
*/
sstore_data_reset(data);
/* Check warnings */
while (sstore_warning_next(hdl, &id, &desc) != SS_WARN_OK) {
fprintf(stderr, "failed to bulk update stat %s "
"because %s\n", id, desc);
}
sleep(SLEEP_INTERVAL);
now_ts += SEC_TO_uSEC(SLEEP_INTERVAL);
}
end:
sstore_partition_free(part);
sstore_value_free(val);
sstore_data_free(data);
sstore_free(hdl);
return (0);
}
Compile this program as follows:
$ cc -o data_bulk_update_partition -lsstore data_bulk_update_partition.c
Once the sstore has restarted after installing the metadata,
run 'data_bulk_update_partition' as root or as a user with appropriate
stats store authorizations. See sstore-security(5) for a
description of the authorizations required to provide and update
statistics.
In another terminal, start recording the stats updated via
data_bulk_update as follows:
sstore capture //:class.example/bulk/partition//:stat.one 10
sstore capture //:class.example/bulk/partition//:stat.one//:part.name 10
sstore capture //:class.example/bulk/partition//:stat.one//:part.place 10
Sample output:
$ sstore capture //:class.example/partition//:stat.one 10
TIME VALUE IDENTIFIER
2016-04-11T18:10:40 180.0 //:class.example/bulk/partition//:stat.one
2016-04-11T18:10:50 225.0 //:class.example/bulk/partition//:stat.one
$ sstore capture //:class.example/partition//:stat.one//:part.name 10
TIME VALUE IDENTIFIER
2016-04-11T18:10:50 //:class.example/bulk/partition//:stat.one//:part.name
john: 90.0
tom: 60.0
bill: 75.0
2016-04-11T18:10:50 //:class.example/bulk/partition//:stat.one//:part.name
john: 90.0
tom: 60.0
bill: 75.0
$ sstore capture //:class.example/partition//:stat.one//:part.place 10
TIME VALUE IDENTIFIER
2016-04-11T18:12:35 //:class.example/partition//:stat.one//:part.place
work: 252.0
party: 168.0
home: 210.0
2016-04-11T18:12:45 //:class.example/partition//:stat.one//:part.place
work: 270.0
party: 180.0
home: 225.0
ATTRIBUTES
See attributes(7) 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_read(3SSTORE), sstore_err_action(3SSTORE),
sstore_range_alloc(3SSTORE), attributes(7), privileges(7), sstore(7),
sstore-security(7)
Oracle Solaris 11.4 27 Nov 2017
sstore_data_attach(3SSTORE)