rdd-howto – step-by-step introduction to rdd(1).

Description

This manual describes the essential usage of rdd(1) from the very beginning.

rdd(1) takes user-described libraries, constructs executable script from them and launches. Data used inside the script and list of called functions are given by a user (in command line or config files). Script construction and launch can be repeated several times, if a user wants to launch his code for the series of objects.

Hello, world!

Create these two files in current directory:

hello.sh

main()
{
    printf "%s\n" "Hello, world!"
}

rdd.def

[first]

rdd_map_libs = shell hello.sh

And launch this:

    $ rdd first object main

The result you should see:

Hello, world!

Now we'll see what lies behind all that.

First to mention is no function calls inside hello.sh. There is only implementation of main.
Note the absence of shebang #!/bin/sh in hello.sh as well (and no execution permissions on file).

The next file rdd.def contains some data in INI format.
The name first of data section is arbitrary. It contains variables, describing properties of the code we want to use.
The variable rdd_map_libs contains files with the used code. First word-specificator tells the file is written in shell language. Our library is assigned without absolute path - in that case path is interpreted as relative to the root of working directory.

Launch string has the following meaning.

    $ rdd first object main

first is the name of the data section we chose to use in the launch. Input data for our script code is calculated from here. The argument is the adjective of the launch.

object is the name of some entity we operate on. Objects are needed, when one repeats his actions in cycle for some list, and each entry of the list may define it's custom properties. The argument is the noun of the launch.

main is the name of the shell function we launch. The argument is the verb of the launch.

Each of the three main parameters above can be given explicitly by variable.

rdd_prf_entry is the name of data section.
rdd_list_entry is the name of used objects.
rdd_map_entry is the name of the launched function.

Now let's shorten the launch string and save all parameters to config file.
rdd.def for short command string:

[first]

rdd_map_entry = main
rdd_list_entry = object

rdd_map_libs = shell hello.sh

With key data, saved inside config, the launch looks like:

    $ rdd first
Parameter first to initialise rdd_prf_entry is still required, as we need to know data section, which contains all other necessary data.
The variant with two arguments is also possible:
    $ rdd first object
Function name is ommitted with two arguments given.

Hello, friends

Each of the three rdd(1)'s main arguments can contain a list of arguments instead of a single value. Extend hello.sh functionality a bit to illustrate that.

hello.sh with friends:

hello_print()
{
    printf "%s\n" "Hello, ${rdd_atom_id}"
}

hello_length()
{
    hello_print | wc -c
}

hello_profiled_print()
{
    printf "%s" "${rdd_prf_entry}: "
    hello_print
}

hello_all()
{
    hello_print
    hello_length
}

Launch string with several values:

    $ rdd first thing,more_thing hello_print,hello_length
And the result:
Hello, thing
13
Hello, more_thing
18
Here one can see the launch of two functions hello_print and hello_length.
Moreover, they are called twice: for the object thing and more_thing.
The code also demonstrates simple usage of input data, described above, inside functions.

Let's extend our configuration file also.
rdd.def with several data sections:

[first]

rdd_map_entry = hello_print, hello_length
rdd_list_entry = thing, more_thing

rdd_map_libs = shell hello.sh

[second]

rdd_map_entry = hello_profiled_print, hello_length
rdd_list_entry = thing, more_thing, side_thing

rdd_map_libs = shell hello.sh

Launch the example:

    $ rdd first
And the result, same as the previous one:
Hello, thing
13
Hello, more_thing
18

Change the name for argument:

    $ rdd second
The result:
second: Hello, thing
13
second: Hello, more_thing
18
second: Hello, side_thing
18
All parameters are hidden in config now, and we can manage launches with short command line.

Data combination

In the last version of config file the data about language is duplicated.
To get rid off that, we can combine data sections.

rdd.def with structured data sections

[first]

rdd_map_entry = hello_print, hello_length
rdd_list_entry = thing, more_thing

rdd_prf_id = shell

[second]

rdd_map_entry = hello_profiled_print, hello_length
rdd_list_entry = thing, more_thing, side_thing

rdd_prf_id = shell

[shell]

rdd_map_libs = shell hello.sh
The launch and results remain the same:
    $ rdd first

Hello, thing
13
Hello, more_thing
18

    $ rdd second

second: Hello, thing
13
second: Hello, more_thing
18
second: Hello, side_thing
18

But this time we describe the data only once. Lang variables reside in separate section, and first and second sections include it. To use some data section inside other section, rdd_prf_id is used.
The command line equivalent for data inclusion is:

    $ rdd first,shell

Define more data sections to include several ones at once and see their priorities.

rdd.def for chainloading

[add_some]

last_data = some
uniq_some_data = qwerty

[add_another]

last_data = another
uniq_another_data = asdfgh

[first]

rdd_map_entry = hello_print, hello_length,add_print
rdd_list_entry = thing, more_thing

rdd_prf_id = shell

[second]

rdd_map_entry = hello_profiled_print, hello_length
rdd_list_entry = thing, more_thing, side_thing

rdd_prf_id = shell

[shell]

rdd_map_libs = shell hello.sh, shell add.sh

Note the appearence of the new library file add.sh and printing method add_print.

add.sh

add_print()
{
    printf "%s\n" "${last_data}"
    printf "%s\n" "${uniq_some_data}"
    printf "%s\n" "${uniq_another_data}"
}
The launch:
    $ rdd first,add_some,add_another
The result:
Hello, thing
13
another
qwerty
asdfgh
Hello, more_thing
18
another
qwerty
asdfgh

The most right data section in the list (as in command line, so inside config file) has the highest priority.
Thus the variable last_data is taken from section add_another as the most right one in command line.
At the same time non-overlapping variables uniq_some_data and uniq_another_data were gathered each from its own section.

rdd_prf_id is not redefined, when mentioned in several sections.
Instead all mentioned sections are summarised and each met section is included.

The same data can be given in three forms, first has the most priority.
Options in command line:

    $ rdd first some_var=value
Value in rdd.def file
Value in *.conf file inside rdd.conf.d/ dir at the root of working copy

To list all gathered data, datardd(1) is used:

    $ datardd first

rdd_atom_id=thing
rdd_list_entry=thing, more_thing
rdd_map_libs=shell hello.sh, shell add.sh
rdd_map_entry=hello_print, hello_length,add_print
rdd_prf_all=shell,first
rdd_prf_entry=first
The output contains one set of data regardless of quantity of objects in configuration.

Objects and lists

Object names can be kept in plain text lists.
rdd_list_path variable contains path to directory with such lists.
    $ echo 'rdd_list_path = buildfiles' >> rdd.def
When lists are set up, they can be used as:
    $ rdd first,add_some list.src
with example content of buildfiles/list.src
thing

# comments are ingored
# as well as empty strings

more_thing

Lists can be nested, thus some list may contain another lists.

To show resulting list of objects, lsrdd(1) is used.

    $ lsrdd first list.src
thing
more_thing

Object may store their custom data.
rdd_atom_path variable contains path to directory with atom data.

    $ echo 'rdd_atom_path = atomfiles' >> rdd.def
Data of objects now is checked up in corresponding file atomfiles/NAME/atom.conf.
Priority of data from atom.conf is between rdd.conf.d/ and rdd.def.
Used example above will not demonstrate the data from atom.conf, as it stores all data in rdd.def with higher priority.

Script dumps

All the rdd(1) actually does is writing down a script with user's wishes and executing it. Have a look at it:
    $ rdd first,add_some thing
Dumped scripts for all launches reside in var/dump/ directory.
For the launch above scripts lie in var/dump/thing_first_add_some/.
Note the name of final personal dir: it contains name of the object and data sections, given in command line, first and add_some. It does not contain section shell in the name, though the section is in use. That's because minimal identification for resulting data in dir name is used.

First essential file in dump dir is var/dump/thing_first_add_some/dump.sh. It contains all the data and inclusion of libraries, declared for use in configs.
The file does not contain any calls. Its purpose is to make available needed data and functions to the scripts, doing nothing on itself.

var/dump/thing_first_add_some/dump.sh

last_data="some"
rdd_atom_id="thing"
rdd_list_entry="thing"
rdd_list_path="buildfiles"
rdd_map_libs="shell hello.sh, shell add.sh"
rdd_map_entry="hello_print, hello_length,add_print"
rdd_prf_all="shell,first,add_some"
rdd_prf_entry="first,add_some"
uniq_some_data="qwerty"

. /home/user/poligon/hello.sh
. /home/user/poligon/add.sh

Another essential file in dump dir is var/dump/thing_first_add_some/calldump.
It includes dump.sh and calls all ordered functions.
This file is executed by rdd(1), can be re-executed directly, saved and reused on regular purpose.

var/dump/thing_first_add_some/calldump

(
#!/bin/sh < /dev/null
. /home/user/poligon/var/dump/thing_first_add_some/dump.sh
hello_print
hello_length
add_print

)

See also

rdd(1), the main tool of the set.
datardd(1), tool to output data from rdd config files.
dumprdd(1), tool to output language script, constructed from rdd config files.
droprdd(1), tool to write down script, constructed from rdd config files.
lsrdd(1), tool to output list of rdd objects.
rootrdd(1), tool to output root of rdd working directory.