VconfBuxton

From Tizen Wiki
Jump to: navigation, search

Overview

System configuration is often managed by keys and provided by a key manager service. That is the case of Tizen.

Many programs of Tizen are using the key manager named VCONF.

Going from Tizen 2 to Tizen 3, the key manager changed to be buxton (see that ref).

For some informations about, follow that link Buxton. It contains a good porting guide for going from vconf to buxton.

This page describes:

  • how to continue to use legacy vconf code transparently;
  • how data are recorded;
  • how to smoothly move to a true buxton integration into tizen;
  • what are specific useable API (but that should probably not be used).

How to continue to use legacy code transparently

The package vconf-buxton (platform/core/appfw/vconf-buxton on review.tizen.org) provides a wrapper emulating vconf using the buxton key manager.

When installing, the package vconf-buxton declares that the previous package vconf is obsolete and then replace it.

The 2 main features of vconf will be replaced: - libvconf is overwritten by the wrapping library of the same name - vconftool is overwritten by a tool rewritten to use the new wrapping library.

Then the system is ready to run the legacy vconf programs transparently.

How does it work ?

The following figure shows how it works:

 +--------------+            +----------+                 +---------+
 | legacy vconf |   linked   | wrapping |     socket      | buxton  |
 |   client     +----------->| library  +---------------->| service |
 +--------------+    with    +----------+   connection    +---------+

The wrapping library is making a key name conversion from the vconf naming scheme to the buxton naming scheme.

Initialisation features

Some more features are coming with vconf-buxton. This features are needed to achieve these operations:

  • Initialise the buxton data base from the vconf data base;
  • Initialise at start up the volatile keys from their saved default values;
  • Optionally, save the values of the volatile keys for the next restart.

The program implementing these features are written using BASH and are named respectively:

  • /usr/bin/vconf-buxton-init-from-vconf.sh
  • /usr/bin/vconf-buxton-restore-mem-layer.sh
  • /usr/bin/vconf-buxton-backup-mem-layer.sh

How data are recorded: conversion of key names

((see discussion Talk:VconfBuxton))

The vconf naming scheme

This naming is like a relative path name (example: memory/appservice/serviceready or db/alarm/state are valid keys). Let names each string of the name separated by slash a component (Example: the key db/alarm/state has three components, the first is db, the second is alarm and the third is state).

The first component of a vconf key, called its prefix, is used by vconf to select a file subsystem root directory where to store or retrieve the keys and their values. The remaining components (from 2 to the count of components) are used to identify the key file within the computed root location.

vconf knows several prefix components:

  • memory: for in memory volatile key-values;
  • db: persistent
  • file: persisten

The buxton naming scheme

Buxton isn't using an uniform naming of the keys. It rather organises the keys in layers and groups. Then naming a key for buxton is basically giving its layer, its groups and its name within the group and the layer. A subtle feature of buxton is to request a key without giving its layer, in such case, the layers are orderly searched to find the group and key, the first occurence is returned (for details check the buxton documentation).

The layers are statically configured by the file '/etc/buxton.conf'. The default configuration declares the following layers:

  • base: persistent, system wide
  • isp: INTENDED TO BE INTEGRATION SPECIFIC
  • temp: in memory volatile, system wide
  • user: persistent, user oriented (one layer per client uid).

The conversion from vconf naming scheme to buxton naming scheme

The wrapping library of vconf-buxton uses that table:

vconf naming scheme buxton naming scheme
Layer Group key
db/remaining... base vconf db/remaining...
file/remaining... base vconf file/remaining...
memory/remaining... temp vconf memory/remaining...
user/remaining... user vconf user/remaining...
memory_init/remaining... base vconf memory_init/remaining...

That table shows that the wrapper vconf-buxton provides two new new prefixes: user and memory_init:

  • user can be used for user purpose (but that will probably not be used at all);
  • memory_init isn't really new and is intended to be used for initialisation of the volatile layer temp.

The tool vconftool

The tool vconftool is emulated. It is written as a bash script that internally uses the command line tool buxtonctl.

Thus, the vconftool is working in the same way that the "true" legacy vconftool.

Note that the option --smack (aka -s) is supported and set the Smack label of the keys. It should be used instead of using chsmack. If not set, the default Smack label will be "User".

Note also that the option --user and --group are ignored. It means that they don't throw any error but have no effect.

Here is the help of the new vconf-tool:

Usage: vconftool [-v|--verbose|-q|--quiet] command ...

Command set: set a value (create or update)

   vconftool set -t <TYPE> <KEY-NAME> <VALUE> <OPTIONS>

       <TYPE> = int | bool | double | string

       <OPTIONS>

          -u, --user    <UID>    ignored! (compatibility)
          -g, --group   <GID>    ignored! (compatibility)
          -i, --install          for keys starting with memory/
                                 installs in db the startup value
          -s, --smack   <LABEL>  tells to set the security label <LABEL>
          -f, --force            tells force updating the value

       Ex) vconftool set -t string db/testapp/key1 "This is test" 

Command get: get a value

   vconftool get <OPTIONS> <KEY-NAME>

       <OPTIONS>

          -r, --recursive        retrieve all keys having the given prefix

       Ex) vconftool get db/testapp/key1
           vconftool get -r db/testapp/

Command unset: remove a value

   vconftool unset <KEY-NAME>

       Ex) vconftool unset db/testapp/key1

Command label: set the security label

   vconftool label <KEY-NAME> <SMACK-LABEL>

       Ex) vconftool label db/testapp/key1 User::Share

How to smoothly move to a true buxton integration into Tizen ?

The previous chapter showed that the vconf naming scheme is in a one to one fit with the buxton naming scheme.

The only little difference is the layer to use that can be either base, temp or user. The group is always vconf.

The layer user (activated by the prefix user/) is a new feature comparing to vconf because it allows to have user specific keys easily.

For the transition to true pure buxton integration, the laziest path is to keep that naming scheme and to replace API calls. This transition is easy for some verbs and difficult for some other.

WARNING: buxton is not thread safe because notifications can collide with other messages.

WARNING: recording notification is not obvious because the status is only given on error.

CAUTION: buxton library isn't thread safe (currently)

Some useful documentation https://wiki.tizen.org/w/images/0/07/Buxton_guide.pdf

Dont create file anymore

Some packages are creating vconf keys directly by setting files. This is not the correct process. At least each of this packages must be using the program vconftool to set the keys.

Basic API easy to translate

Basic API verbs can be easily mapped to API offered by buxtonsimple. They are summarized in the below tables:

setting getting
vconf verb buxtonsimple verb vconf verb buxtonsimple verb
vconf_set_int sbuxton_set_int32 vconf_get_int sbuxton_get_int32
vconf_set_bool sbuxton_set_bool vconf_get_bool sbuxton_get_bool
vconf_set_dbl sbuxton_set_double vconf_get_dbl sbuxton_get_double
vconf_set_str sbuxton_set_string vconf_get_str sbuxton_get_string

Example of vconf code:

err = vconf_set_int(KI, 12);
err = vconf_get_int(KI, &value);
err = vconf_set_str(KS, "null");
s = vconf_get_str(KS);

Same example translated to sbuxton code:

sbuxton_set_group("vconf", "base");  /* replace "base" with "temp" if needed */
sbuxton_set_int32(KI, 12);
value = sbuxton_get_int32(KI);
sbuxton_set_string(KS, "null");
s = sbuxton_get_string(KS);

As what can be seen sbuxton maps well and is simplest because it never fails;)

The API verbs vconf_unset, vconf_notify_key_changed and vconf_ignore_key_changed are also easy to translate:

 err = vconf_unset(K1);
 err = vconf_notify_key_changed(K2, f2, data);
 err = vconf_ignore_key_changed(K3, f3);

becomes

 err = buxton_open(&client);

 key1 = buxton_key_create("vconf", K1, "base", BUXTON_TYPE_UNSET); 
 err = buxton_unset_value(client, key1, f1, NULL, 0);

 key2 = buxton_key_create("vconf", K2, "base", BUXTON_TYPE_UNSET);
 err = buxton_register_notification(client, key2, f2, data, 0);

 key3 = buxton_key_create("vconf", K3, "base", BUXTON_TYPE_UNSET);
 err = buxton_unregister_notification(client, key3, f3, data, 0);

there are many details that are hidden but the idea is here and that is not so hard.

When creating keys be aware that generally, the type must be set exactly. Using here BUXTON_TYPE_UNSET is possible but not recommended when the type is known.

The layer is here "base" but you should change it to what is wished ("base" or "temp").

API not easy to translate

Many verbs of the vconf API are working on list of keys. These verbs are difficult to translate to buxton because buxton does not have list of keys.

New API verbs

Including the file <vconf/vconf-buxton.h> allows to use some new API verbs or data that are specific to vconf-buxton. These verbs are used internally and by the implementation of vconftool by vconf-buxton.

verb summary
vconf_set_default_group used to change globally the group to use that, by default, is vconf
vconf_keylist_sort Sorts alphabetically the keys of the list
vconf_set_label Set the Smack label of one key
vconf_set_labels Set the Smack label of a list of keys
vconf_refresh Refresh the values of the keys of the list by querying the buxton backend
vconf_scan List the keys of a hierarchy
vconf_exists Checks if a key exists

Here below an extract of the C header file <vconf/vconf-buxton.h> for the new verbs or data.

/**
 * VCONF_GET_KEY, VCONF_GET_ALL, VCONF_GET_DIR
 * \n Use for vconf_get()
 * @see vconf_get()
 */
    enum get_option_t {
	VCONF_GET_KEY = 0,
	    /**< get only keys */
	VCONF_GET_ALL,
	    /**< get keys and directorys */
	VCONF_GET_DIR,
	   /**< get only directorys */
	VCONF_REFRESH_ONLY,
	    /**< get only keys */
	VCONF_GET_KEY_REC,
	    /**< get only keys recursively */
	VCONF_GET_ALL_REC,
	    /**< get keys and directorys recursively */
	VCONF_GET_DIR_REC
	   /**< get only directorys recursively */
    };

    typedef enum get_option_t get_option_t;

/**
 * Set the default group of key lists created using vconf_keylist_new.
 * @param[in] groupname The name of the default group to bind to
 * @return 0 in case of success or -1 in case of error of allocation
 * @see vconf_keylist_new()
 */
    int             vconf_set_default_group(const char *groupname);

/**
 * This function sorts the list in alphabetical order (with LANG=C)
 * @param[in] keylist Key List
 * @return 0 if done, -1 on error
 * @pre None
 * @post None
 * @remarks None
 */
    int             vconf_keylist_sort(keylist_t * keylist);

/************************************************
 * setting label APIs                           *
 ************************************************/

/**
 * This function set the smack label of its keys
 * @param[in] keylist Key List
 * @param[in] label The label to set
 * @return 0 if done, -1 on error
 * @pre None
 * @post None
 * @remarks None
 */
    int             vconf_set_labels(keylist_t * keylist, const char *label);

/**
 * This function set the smack label of its keys
 * @param[in] keylist Key List
 * @param[in] label The label to set
 * @return 0 if done, -1 on error
 * @pre None
 * @post None
 * @remarks None
 */
    int             vconf_set_label(const char *keyname, const char *label);

/************************************************
 * getting APIs                                 *
 ************************************************/

/**
 * This function reads the database to refresh the values of
 * the keys in 'keylist'.
 * @param[in]	keylist	the keylist whose values have to be refreshed
 * @return 0 on success, -1 on error
 * @see vconf_keylist_lookup, vconf_keylist_nextnode, vconf_keylist_rewind
 */
    int             vconf_refresh(keylist_t * keylist);

/**
 * This function retrieves the keys or subdirectory in in_parentDIR.<br>
 * @param[in]	keylist	keylist created by vconf_keylist_new(), MUST be empty
 * @param[in]	in_parentDIR parent DIRECTORY of needed keys
 * @param[in]	option VCONF_GET_KEY|VCONF_GET_DIR|VCONF_GET_ALL|VCONF_GET_KEY_REC|VCONF_GET_DIR_REC|VCONF_GET_ALL_REC
 * @return 0 on success, -1 on error
 * @pre None
 * @post None
 * @remkar None
 * @par example
 * @code
#include <stdio.h>
#include <vconf.h>

int main()
{
   keylist_t *kl=NULL;
   keynode_t *temp_node;
   const char *vconfkeys1="db/test/key1";
   const char *parent_dir="db/test";

   kl = vconf_keylist_new();
   if(vconf_scan(kl, parent_dir, VCONF_GET_KEY))
      fprintf(stderr, "vconf_get FAIL(%s)", vconfkeys1);
   else
      printf("vconf_get OK(%s)", vconfkeys1);

   while((temp_node = vconf_keylist_nextnode(kl))) {
      switch(vconf_keynode_get_type(temp_node)) {
	case VCONF_TYPE_INT:
		printf("key = %s, value = %d\n",
			vconf_keynode_get_name(temp_node), vconf_keynode_get_int(temp_node));
		break;
	case VCONF_TYPE_BOOL:
		printf("key = %s, value = %d\n",
			vconf_keynode_get_name(temp_node), vconf_keynode_get_bool(temp_node));
		break;
	case VCONF_TYPE_DOUBLE:
		printf("key = %s, value = %f\n",
			vconf_keynode_get_name(temp_node), vconf_keynode_get_dbl(temp_node));
		break;
	case VCONF_TYPE_STRING:
		printf("key = %s, value = %s\n",
			vconf_keynode_get_name(temp_node), vconf_keynode_get_str(temp_node));
		break;
	default:
		printf("Unknown Type\n");
      }
   }
   vconf_keylist_free(kl);
}
 * @endcode
 */
    int             vconf_scan(keylist_t * keylist,
			       const char *in_parentDIR,
			       get_option_t option);

/**
 * This function checks if the given key exists from backend system.
 * @param[in]	keyname	key
 * @return 0 on success: exists, -1 on error or not existing
 */
    int             vconf_exists(const char *keyname);