| Crates.io | zenoh-plugin-storage-manager |
| lib.rs | zenoh-plugin-storage-manager |
| version | 1.7.2 |
| created_at | 2022-09-29 15:28:44.684831+00 |
| updated_at | 2026-01-08 16:16:48.190141+00 |
| description | The zenoh storages plugin. |
| homepage | http://zenoh.io |
| repository | https://github.com/eclipse-zenoh/zenoh |
| max_upload_size | |
| id | 676747 |
| size | 364,443 |
Eclipse Zenoh: Zero Overhead Pub/Sub, Store/Query and Compute.
Zenoh (pronounced /zeno/) unifies data in motion, data at rest, and computations. It carefully blends traditional pub/sub with geo-distributed storages, queries, and computations, while retaining a level of time and space efficiency that is well beyond any of the mainstream stacks.
Check the website zenoh.io for more information and installation instructions.
See also the roadmap for more detailed technical information.
zenohd routerA plugin that allows connecting zenohd to different storages (e.g., databases). This plugin is a plugin manager
itself that loads its own plugins - backends - specific for the external storage API.
memory backend
Stores data in a hashmap in memory, statically linked to the storage manager.
This backend relies on the host's file system to implement the storages.
This backend relies on Amazon S3 to implement the storages. It is also compatible with MinIO object storage.
This backend relies on RocksDB to implement the storages.
This backend relies on InfluxDB server to implement the storages.
The storages are configured in the storage manager plugin configuration in the plugins section of the
config.json.
There are two concepts in the storage manager: "volumes" and "storages".
The "volume" is a specific database backend plugin (memory, s3, rocksdb, etc.) plus a concrete backend configuration (database name, username, password, etc.).
The "storage" is a mapping from a glob key expression to a volume, defining where data for each path is stored.
Here is a simple example config that sets up two storages. The __path__ explicitly
sets up paths to dynamic plugins for different platforms.
"plugins": {
"storage_manager": {
"volumes": {
"example": {
"__path__": ["target/debug/libzenoh_backend_example.so","target/debug/libzenoh_backend_example.dylib"],
}
},
"storages": {
"memory": {
"volume": "memory",
"key_expr": "demo/memory/**"
},
"example": {
"volume": "example",
"key_expr": "demo/example/**"
}
}
}
}
Assume that we are in the root of the zenoh repository.
Uncomment the following part in the DEFAULT_CONFIG.json5 which demonstrates using
external plugin config files.
"plugins|": {
"rest": {
"__config__": "./plugins/zenoh-plugin-rest/config.json5",
},
"storage_manager": {
"__config__": "./plugins/zenoh-plugin-storage-manager/config.json5",
}
},
Also either change option timestamping -> enabled -> peer to true or change the mode to router to enable message
timestamping which is required by storage manager.
Run the zenohd router with adminspace write permissions enabled:
RUST_LOG=info cargo run -- --config DEFAULT_CONFIG.json5 --adminspace-permissions rw
The RUST_LOG=info is important to enable logging from zenoh_plugin_storage_manager itself. Otherwise, the logs from plugins are suppressed.
The adminspace write permissions allow you to manage storages dynamically at runtime via the admin space REST API. See the example at the end.
Verify that the plugin loaded successfully: the output should contain lines like:
2025-10-02T13:33:38.279758Z INFO main ThreadId(01) zenoh::api::loader: Loading plugin "rest"
2025-10-02T13:33:38.530621Z INFO main ThreadId(01) zenoh::api::loader: Loading plugin "storage_manager"
2025-10-02T13:33:38.787932Z INFO main ThreadId(01) zenoh::api::loader: Starting plugin "rest"
2025-10-02T13:33:38.795413Z INFO main ThreadId(01) zenoh::api::loader: Successfully started plugin rest from "/Users/milyin/ZS/zenoh/target/debug/libzenoh_plugin_rest.dylib"
2025-10-02T13:33:38.795433Z INFO main ThreadId(01) zenoh::api::loader: Finished loading plugins
2025-10-02T13:33:38.795441Z INFO main ThreadId(01) zenoh::api::loader: Starting plugin "storage_manager"
2025-10-02T13:33:38.801661Z INFO ThreadId(01) zenoh_plugin_storage_manager: Spawning volume 'memory' with backend 'memory'
2025-10-02T13:33:38.802118Z INFO ThreadId(01) zenoh_plugin_storage_manager: Spawning volume 'example' with backend 'example'
2025-10-02T13:33:38.925730Z INFO ThreadId(01) zenoh_plugin_storage_manager: Spawning storage 'example' from volume 'example' with backend 'example'
2025-10-02T13:33:38.926759Z INFO ThreadId(01) zenoh_plugin_storage_manager: Spawning storage 'memory' from volume 'memory' with backend 'memory'
2025-10-02T13:33:38.926833Z INFO main ThreadId(01) zenoh::api::loader: Successfully started plugin storage_manager from "/Users/milyin/ZS/zenoh/target/debug/libzenoh_plugin_storage_manager.dylib"
2025-10-02T13:33:38.926860Z INFO main ThreadId(01) zenoh::api::loader: Finished loading plugins
Now we can store and retrieve data. This can be done by zenoh put and get operations as well as using REST API.
Store some data using put:
cargo run --example z_put -- -k demo/memory/test -p 'Hello from zenoh put'
Then query the stored data:
cargo run --example z_get -- -s "demo/memory/test"
Expected output with the stored data
>> Received ('demo/memory/test': 'Hello from zenoh put')
Notice that this would not work without storage enabled. The put operation belongs to the publish/subscribe API, while the get is part of the query/reply API.
It's the storage that runs a subscriber and querier for its key expression. In other words, storages link pub/sub and query/reply APIs together in
the Zenoh network.
Store data via REST PUT:
curl -X PUT -d '"Hello from REST"' -H "Content-Type: application/json" http://localhost:8080/demo/memory/test
Retrieve data via REST GET:
curl http://localhost:8080/demo/memory/test
Expected output:
[{"key":"demo/memory/test","value":"Hello from REST","encoding":"application/json","timestamp":"7556630592622444272/d3f8913b8af0c842078d30652a04bd8f"}]
Note: Use the application/json content type and quoted value in PUT to get data as a string value in GET json output. Otherwise, the value is base-64 encoded to
ensure correctness of the json format.
Delete stored data with REST DELETE:
curl -X DELETE http://localhost:8080/demo/memory/test
You can verify the deletion by querying the key again:
curl http://localhost:8080/demo/memory/test
Expected output (empty array, indicating no data found):
[]
You can manage storages dynamically via the admin space - the predefined key expression starting with @/.
To view current storages:
curl -s 'http://localhost:8080/@/local/router/**/storages/*' | jq
Expected output (showing active storages):
[
{
"key": "@/d3f8913b8af0c842078d30652a04bd8f/router/status/plugins/storage_manager/storages/memory",
"value": {
"key_expr": "demo/memory/**",
"volume": "memory"
},
"encoding": "application/json",
"timestamp": null
},
{
"key": "@/d3f8913b8af0c842078d30652a04bd8f/router/status/plugins/storage_manager/storages/example",
"value": null,
"encoding": "application/json",
"timestamp": null
}
]
Add another memory storage dynamically:
curl -X PUT -H 'content-type:application/json' \
-d '{"key_expr":"demo/sensors/**","volume":"memory"}' \
http://localhost:8080/@/local/router/config/plugins/storage_manager/storages/sensors
Delete example storage dynamically:
curl -X DELETE http://localhost:8080/@/local/router/config/plugins/storage_manager/storages/example
Verify the new memory storage is created and the example storage is deleted:
curl -s 'http://localhost:8080/@/local/router/**/storages/*' | jq