Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Latest commit

 

History

History

elixir

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Elixir bindings

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

Conveniences

Creating keys using maps

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"},
    ],
  }
)

Converting keys to maps

{name: name, value: value} = Elektra.Key.to_map(key)

Generate a stream of keys from a key set

key_stream = Elektra.KeySet.stream(ks)

Iterating over key sets

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)

Examples

Hello Elektra with Elektra.System

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()

Hello Elektra with Elektra

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

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

Creating tests

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

Installation

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

  1. 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.