RCFC

Remote C Function Call

by Pierre Mavrikios rcfc@petros.it 2010-09-01

 

How to create a RCFC distributed application.


To create a distributed application with RCFC, two types of information have to be defined.
  1. Define the hierarchical tree of the fundamental program nodes that compose the application.
  2. Define the relationship between the nodes, declaring the remote C functions that links them.

This two fundamental informations are necessary and sufficient to:
  1. Build the distributed application.


1. Defining the hierarchical tree.
First the fundamental node tree has to be defined. Every node is a program that is hierarchically linked with another one. A lower program node is linked to a higher level, when a set of functions called from lower node are executed by the upper one and/or when a set of functions called from upper node are executed by the lower one.

Fundamental node tree.



Many instances of a program node can run in respect of its higher level. This forms the distributed application tree.

Distributed application tree



Once the fundamental node tree topology is determined, the RCFC project can be set. This is done by creating the project directory tree that reflects the fundamental node tree.

Fundamental node tree.
Project directory  tree
<=>




2.
Defining the relationship between nodes.
The relationship between each node and its higher level is governed by the containts of a C language compatible header file, named "rcfc_functions.def".  In each directory of the project tree, except the top level, a "rcfc_functions.def" file has to exist.



The relationship between the two nodes is determined by declaring the C function calls that the lower node calls the higher one and the C function calls that the higher level node calls the lower one. To do it, two sections have to be defined in the "rcfc_functions.def" file, identified by the
:
//### Call
and
//### Called
rows.
Under the "//### Call" section, all functions the actual level program node calls the higher level program node, have to be declared, hence, in the higher level program node all declared functions have to be defined.
Under the "//### Called" section, all functions the higher level program node calls the actual level program node, have to be declared, hence, in the actual level program node all declared functions have to be defined.
The "rcfc_functions.def" file follows C language syntax and rules.

"rcfc_functions.def " file example.
/*
    Just an example
*/

// Include all needed header files
#include <stdint.h>

#define ARRAY_ELEMENTS     32
#define
CHUNK_LEN         128

typedef struct
{
    int     handler;
    long    array [32];
} MY_STRUCT;

//### Call
// Insert all C function prototypes, this level node calls the higher level node functions

int         rf_is_upper_ready   ( void );
int         rf_lower_says       ( const char message [64] );
MY_STRUCT   rf_choose           ( const MY_STRUCT array [ARRAY_ELEMENTS], uint32_t num );



//### Called
// Insert all C function prototypes, the higher level node calls this level node functions

int         rf_lower_is_ready   ( void );
int         rf_open_file        ( const str file_name );
int         rf_write_to_file    ( int handler, const char data [CHUNK_LEN] );
int         rf_close_file       ( int handler );




3. Building the distributed application.

From within the project directory tree, open a console and execute the "rcfcbuild" program.
The "rcfcbuild" program will create whatever is needed to build the distributed application.



For every node of the project directory tree a static library "librcfc_libs.xxx.la" and header file[s] will be generated.




In every node of the project tree, write the node application C source code:

Top node application template
Mid node application template
Term node application template
//
#include <rcfc_ta.h>


//############################
//#       Top
//############################

// include '.h' files generated by 'rcfcbuild'.
#include "rf_functions.h"



//
// Define the rcfc functions called by other nodes
// declared in the '//#--- Called.' section
// of rcfc generated included files
// ("rf_functions.h")
//>----------------------------------------------------
//|-- Insert function definitions here --|//


//-----------------------------------------------------
//-----------------------------------------------------
int main ( int argc, char **argv )
{

    // rcfc initialization


    if ( !rcfc_grant_functions ( port, app_ide ) )
        exit ( -1 );

    // main node loop
    while ( rcfc_is_grant_running () ) // optional
    {


        // call the remote rcfc functions
        // declared in the '//#--- Call.' section
        // of rcfc generated included files
        // ("rf_functions.h")
        //|-- Edit here --|//

        sleep ( 1 );
    }

    rcfc_wait_grant_to_exit (); // optional


    return 0;
}
//
#include <rcfc_ta.h>


//############################
//#       Mid
//############################

// include '.h' files generated by 'rcfcbuild'.
#include "rf_functions.h"



//
// Define the rcfc functions called by other nodes
// declared in the '//#--- Called.' section
// of rcfc generated included files
// ("rf_functions.h")
//>----------------------------------------------------
//|-- Insert function definitions here --|//


//-----------------------------------------------------
//-----------------------------------------------------
int main ( int argc, char **argv )
{

    // rcfc initialization
    if ( !rcfc_offer_functions ( host, port, app_ide ) )
        exit ( -1 );
    if ( !rcfc_grant_functions ( port, app_ide ) )
        exit ( -1 );

    // main node loop
    while ( rcfc_is_grant_running ()
                      &&
             rcfc_is_offer_running () ) // optional
    {
        // call the remote rcfc functions
        // declared in the '//#--- Call.' section
        // of rcfc generated included files
        // ("rf_functions.h")
        //|-- Edit here --|//

        sleep ( 1 );
    }

    rcfc_wait_grant_to_exit (); // optional
    rcfc_wait_offer_to_exit (); // optional

    return 0;
}
//
#include <rcfc_ta.h>


//############################
//#       Term
//############################

// include '.h' files generated by 'rcfcbuild'.
#include "rf_functions.h"



//
// Define the rcfc functions called by other nodes
// declared in the '//#--- Called.' section
// of rcfc generated included files
// ("rf_functions.h")
//>----------------------------------------------------
//|-- Insert function definitions here --|//


//-----------------------------------------------------
//-----------------------------------------------------
int main ( int argc, char **argv )
{

    // rcfc initialization
    if ( !rcfc_offer_functions ( host, port, app_ide ) )
        exit ( -1 );



    // main node loop
    while ( rcfc_is_offer_running () ) // optional
    {


        // call the remote rcfc functions
        // declared in the '//#--- Call.' section
        // of rcfc generated included files
        // ("rf_functions.h")
        //|-- Edit here --|//

        sleep ( 1 );
    }


    rcfc_wait_offer_to_exit (); // optional

    return 0;
}

In
every node of the project tree, compile and link with the respective 'librcfc_libs.xxx.la'.