sil2100//vx developer log

Welcome to my personal web page

Empty

UniConf: introduction

While writing my thesis some time ago, I did a small review of existing configuration systems in use. One of them especially caught my eye - UniConf. The authors once called it the "One True Configuration System", which might sound a bit provocative, but has a seed of truth in it.

2011-02-15

In short - UniConf aims to meld many configuration systems together. This means UniConf tries to understand most existing configuration systems, written in various file formats, and exports them in an unified way. UniConf, by its own, does not really define one particular way of storing variables, but provides an API for reading most of the common configurations (though the use of so called generators) and adds some features that can be useful when designing/using/implementing a configuration system.

UniConf architecture

In the graph above, temp: cache: unix: ssl: are some of the possible generators that can be used by UniConf. For instance, the temp: moniker makes the variables of the given UniConf tree be only saved in memory, where unix: makes use of UNIX sockets to read the configuration variables from a listening UniConf server (uniconfd - we'll get to that). As another example, an ini: generator can be used to read from and store variables in the standard .ini configuration file format.
UniConf provides an C++ API with respective wrappers for the C language. Designing a simple UniConf application is very easy and is a rather convenient process.


#include <iostream>
#include <wvstreams/uniconfroot.h>

using namespace std;

int main(void)
{
    // Define the root of the configuration.
    // Use an .ini file stored in the current working directory
    // Since this is our first UniConf tree, we mount it as "/"
    UniConfRoot root("ini:tmp.conf");

    // Reading the value of a variable
    cout << "Value before: " << root["ala"].getme().cstr() << endl;

    // Setting the value of a variable
    root["ala"].setme("is the best");

    // We can also ask for the virtual name and 'pathname' of the variable
    cout << "Path: " << root["ala"].fullkey().cstr() << endl;

    // In this choice of monikers, if we want to save the changes, we
    // need to commit them
    root.commit();

    return 0;
}

Besides having the basic get/set variable functionality, UniConf also offers such features like variable on-change notification (by using the add_callback() method) or mounting multiple configurations into different mount points a single UniConf tree. But since this is only an introductory post, we will get to these features later.
But configurations not only need to be accessed locally. UniConf includes a configuration serving daemon, uniconfd, which can be used either to export variables outside of the local space or act as a local server, binding configuration systems and making them available in one consistent form. The uniconfd server can either listen on a given TCP port or use a UNIX socket for communication with clients. Useful, although from what I know some features seem to be still missing.

I am rather fond of UniConf, since the idea of a hybrid system that could bind configurations together reminds me of Flatconf. One problem might be the lack of beginner-targeting documentation, since one of the only programming related help one can get can be found either in the source code or the doxygen documentation. But I'll try to shed some more light on the programming aspects of this system in my future UniConf posts. Stay tuned.