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
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);
Handle to libsstore
Array of statistics store identifiers
Total number of statistics store identifiers
Statistic store identifier associated with the histogram
sstore_histogram_t to be memory-mapped
Array of values corresponding to the array of statistics store identifiers
Address to store the starting address of the shared-memory region in the statistics store daemon
sstore_data_t containing the data points for a statistic
Timestamp in microseconds since epoch
Value for a statistic at a given timestamp
Array of sstore_data_t's corresponding to the array of statistics store identifiers
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:
Sets up an array of uint64_t shared between the calling process and the sstored daemon.
Stores the starting address of this shared array in addrs on success.
Enables any resources in the given ssid that are defined statically and are not currently enabled. For more information about statically defined resources, see the sstore(7) man pages.
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() function, 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_histogram_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 information, 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:
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.
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.
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 information, see the webui(7) man page.
The sstore_data_bulk_update() function performs the following tasks:
Enables any resources in the given ssid that are defined statically and are not currently enabled. For more information 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 persistently 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.
For a description on the authorizations required to provide and update statistics, see the sstore-security(7) man page.
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.
The sstore_data_update() and sstore_data_attach() functions fail if:
No memory is available
One of the following reasons:
Required arguments are missing
Metadata is not available
A provider already exists for at least one of the ssids
The data type does not match the metadata
An ssid is invalid
An ssid contains a wildcard or slice
An ssid is not a user space statistic or event
The handle is invalid
The statistics store daemon is busy. Retry later
Failed to connect to the statistics store daemon
The caller is not authorized. For more information, see the sstore-security(7) man page
The sstore_data_add() function fails if:
One of the following reasons:
Required arguments are missing
Data point is not in chronological order
Data point value does not have same data type as the other data points in sstore_data_t
The following metadata files, installed in /usr/lib/sstore/metadata/json/solaris, are required for this example:
class.app.solaris.exapp.json
stat.app.solaris.exapp.stat1.json
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/metadata/json/solaris, are required for this example:
class.example.json
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.twoExample 3 Update partitioned stat using sstore_data_update()
The following metadata files, installed in /usr/lib/sstore/metadata/json/solaris, are required for this example:
class.example_partition.json
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.0Example 4 Update counter type stats using sstore_data_bulk_update()
The following metadata files, installed in /usr/lib/sstore/metadata/json/solaris, are required for this example:
class.example_bulk.json
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.twoExample 5 Update partitioned stat using sstore_data_bulk_update()
The following metadata files, installed in /usr/lib/sstore/metadata/json/solaris, are required for this example:
class.example_bulk_partition.json
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
See attributes(7) for descriptions of the following attributes:
|
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)