sysdb: Use a custom output format instead of pretty-printed JSON. JSON is really not what users wanna see, even if it's pretty-printed ;-) Instead, use a simple key/value style output.
Let the JSON formatter include a metric's data_names. For that purpose, let the metric store provide a reference to the timeseries information object (to be populated on read). The JSON formatter compiles a list of unique data_names and outputs that alongside the other metric metadata.
Add support for multiple metric data-stores. It did not make sense to only store one and let conflicting values override each other on each iteration. Instead, track each separately, along with the respective last_update timestamp. This will allow to read the right data on access. At the moment, when requesting a timeseries, the most up to date data store will be used. The network plugin does not support sending multiple data stores at the moment. It will only send the first.
Store a separate last_update timestamp for metric stores. Currently, it is (at least) the same as the metric's last_update timestamp. We'll need this later when supporting multiple metric stores.
store.h: Reuse the sdb_metric_store_t type for a metric's store field.
Split the memstore module from the store module.
Renamed in-memory store types and functions to sdb_memstore*.
Removed sdb_store_fetch_timeseries from headers; it's gone.
store: Use full initializers for store objects. Older versions of GCC/CLANG don't handle "missing" field initializers well.
Build a more generic/powerful query API which writes to a store-writer. Instead of letting the query implementation write JSON directly, let them emit objects to a store-writer. This allows for more powerful and centralized post-processing of the data and avoids code-duplication by moving all logic of how to write out the data to the core. Also, this had a couple of nice side effects and allowed for further simplication: - The TIMESERIES command is now handled by the front-end (based on a FETCH of the respective metric data); query plugin no longer have to implement this. - All protocol specific information is now handled by the frontend; query plugins no longer have to handle this (response-type). - Further separation of the memory-store and generic store code.
store: Use the JSON writer when querying the in-memory store. That is, instead of writing to a JSON formatter directly, access it through it's writer API. This will allow for more flexible store access.
store_json: Let the formatter implement the store-writer interface.
Read-only store types: const char ** → const char * const *. This makes it truely read-only.
store, plugin: Let the plugin module determine an objects backends. The store writer plugins are only expected to record the provided backend (after merging it with existing entries).
store: Add separate store-object types for the store writer API. The argument list of some of the callbacks has already gotten kinda long and we'll want to add more (backends, etc.). Introduce new types which provide all meta-data of the respective store types. Also, only use a single callback to store all kinds of attributes, similar to how it was already done in the "proto" module.
store.h: Updated some documentation comments. A store instance isn't synonym to "the database" anymore.
Remove unused sdb_store_expr_iterable().
plugin, store: Handle hostname canonicalization in the plugin module. This is a high-level functionality. Each store implementation should not have to worry about it.
store: Drop the global (default) store. Instead, register a store from sysdbd and make sure to re-register it on reconfigure. Previously, the store plugin would have been dropped in that case.
store: All store functions now accept a store object. That is, instead of operating on a global, shared instance.