The functions of the underlying C API are exposed by the modules in Elektra.System
.
Elektra.System
See src/bindings/erl_nif/README.md
for an overview of the differences to the C API and the limitations.
Each of the Elektra classes is also available as a Elixir modules which implement a GenServer
behavior1:
Elektra.Kdb
Elektra.Key
Elektra.KeySet
Elektra.Key.new(%{name: "user:/test"})
Elektra.Key.new(%{name: "user:/test", value: "value"})
Elektra.Key.new(
%{
name: "user:/test",
value: "value",
meta: [
{"metaname1", "metavalue1"},
{"metaname2", "metavalue2"},
],
}
)
{name: name, value: value} = Elektra.Key.to_map(key)
key_stream = Elektra.KeySet.stream(ks)
Using the Elektra.KeySet.stream
function it is straightforward to iterate over the keys of a key set
ks
|> Elektra.KeySet.stream
|> Stream.map(&Elektra.Key.to_map/1)
|> Enum.each(fn %{name: name, value: value} ->
IO.puts("#{name}, #{value}")
end)
The analogue of the helloElektra.c
example is given by the following snippet
defmodule Main do
use Elektra
def main do
error_key = Elektra.System.key_new("/")
config = Elektra.System.ks_new(0)
root = Elektra.System.key_new("user:/test")
IO.puts("Open key database")
handle = Elektra.System.kdb_open(:null, error_key)
IO.puts("Retrieve key set")
Elektra.System.kdb_get(handle, config, root)
IO.puts("Number of key-value pairs: #{Elektra.System.ks_get_size(config)}")
key = Elektra.System.key_new("user:/test/hello")
Elektra.System.key_set_string(key, "elektra")
IO.puts("Add key #{Elektra.System.key_base_name(key)}")
Elektra.System.ks_append_key(config, key)
IO.puts("Number of key-value pairs: #{Elektra.System.ks_get_size(config)}")
IO.puts("#{Elektra.System.key_base_name(key)}, #{Elektra.System.key_string(key)}")
# If you want to store the key database on disk, then please uncomment the following two lines
# IO.puts("Write key set to disk")
# Elektra.System.kdb_set(handle, config, root)
IO.puts("Delete key-value pairs inside memory")
Elektra.System.ks_del(config)
IO.puts("Close key database")
Elektra.System.kdb_close(handle, error_key)
Elektra.System.key_del(error_key)
end
end
Main.main()
defmodule Main do
use Elektra
def main do
{:ok, config} = Elektra.KeySet.new()
{:ok, root} = Elektra.Key.new(%{name: "user:/test"})
IO.puts("Open key database")
{:ok, handle} = Elektra.Kdb.open()
IO.puts("Retrieve key set")
Elektra.Kdb.get(handle, config, root)
IO.puts("Number of key-value pairs: #{Elektra.KeySet.get_size(config)}")
{:ok, key} = Elektra.Key.new(%{name: "user:/test/hello", value: "elektra"})
IO.puts("Add key #{Elektra.Key.base_name(key)}")
Elektra.KeySet.append_key(config, key)
IO.puts("Number of key-value pairs: #{Elektra.KeySet.get_size(config)}")
IO.puts("#{Elektra.Key.base_name(key)}, #{Elektra.Key.string(key)}")
# If you want to store the key database on disk, then please uncomment the following two lines
# IO.puts("Write key set to disk")
# Elektra.Kdb.set(handle, config, root)
IO.puts("Delete key-value pairs inside memory")
Elektra.KeySet.del(config)
IO.puts("Close key database")
Elektra.Kdb.close(handle)
end
end
Main.main()
Testing is done via ExUnit.
To run all tests run
mix test
Note that running the tests requires the compiled NIF library.
It might be convenient to copy the NIF library libnif_kdb.so
from the build directory to the source directory, so that the tests can be run without building the project.
To ensure that simply copy the priv
directory from the build directory to the development directory,
cp -r build/src/bindings/erl_nif/elixir/priv src/bindings/erl_nif/elixir
Tests can be added by adding or changing the appropriate files in test
or writing doctests in the inline documentation.
If you have a module MyModule
located at path/to/my_module.ex
then you would create a file test/path/to/my_module_test.exs
with the content
defmodule MyModuleTest do
use ExUnit.Case
doctest MyModule
test "always pass" do
assert true
end
end
To have access to the Elixir module you need to compile Elektra with elixir
added to the CMake option BINDINGS
.
Note that the Elixir binding is marked as experimental and therefore also included if you specify EXPERIMENTAL
in the BINDINGS
CMake option.
For instance, the configuration inside a build directory might be (assuming the build directory is itself in the root directory of Elektra)
cmake -DBINDINGS=elixir ..
The Elixir module is then available in libelektra/build/src/bindings/erl_nif/elixir
.
You can copy the module directory to any convenient location.
When using Mix the dependency can be specified as follows in mix.exs
defp deps do
[
{:elektra, path: "/path/to/the/elixir/module"}
]
end
Note that the Elixir module has Elektra as a dependency and the Elektra libraries need to be installed.
Footnotes
-
We adopt the American spelling due to technical limitations of the spell checking script. The correct spelling in the context of Erlang/OTP is the British spelling. ↩