Synchrouns timeout server and client test

Introduction

On this tutorial is built a server which have only one service. This service is public an allways answer a positive reply once expired a forced sleep during 10 seconds.

On the client side, a simple console client can request the previous service but setting timeout values for synchronous request. This allows to play with synchronous timeouts, experimenting what happens on the different cases where timeout are handled.

This example was used to perform tests on synchronous timeout mechanism implemented inside Af-Arch. As a result, this test can also be used as a simple example to better understand Af-Arch framework.

NOTE: you can find full source code for this example inside af-arch/doc/example/sync directory inside the Af-Arch project.

On this example we will develop the following files:

Server implementation

We will use the following af-gen IDL definition:

// af-test server interface definition.
// af-gen-tutorial (ML4)
// Advanced Software Production Line
server interface af-test {
        relation sells;
        module product (string name, string description, string ref,
                        decimal (10, 2) price) implicit definition {
                product sells provider with 0..n;
        };
        module provider (string name,
                         string address) implicit definition {
                provider sells product with 0..n;
        };
} // end server interface definition

As you can observe, this definition declares only one module called timeout with only one service called service. The service is also implemented directly inside the IDL definition.

Client implementation

The client program is the following:

#include <afdal.h>
#include <afdal_af_test.h>
#include <readline/readline.h>
#include <glib.h>
#include <stdlib.h>


void init_function ()
{
        gchar              *user = getenv ("AF_USER");
        gchar              *pass = getenv ("AF_PASS");
        gchar              *host = getenv ("AF_HOST");
        gchar              *port = getenv ("AF_PORT");
        AfDalNulData       *login;

        if (user == NULL)
                user = readline ("User to login: ");
        if (pass == NULL)
                pass = readline ("Password: ");
        if (host == NULL)
                host = readline ("Host: ");
        if (port == NULL)
                port = readline ("Port: ");

        login = afdal_sync_session_login (user, pass, host, port);
        if (AFDAL_IS_ERROR (login)) {
                g_print ("Unable to login at %s:%s using %s with pass %s\n", 
                         host, port, user, pass);
                exit (-1);
        }

        return;
}

gint main (gint argc, gchar ** argv) {


        gchar        * line;
        AfDalNulData * data;

        // Initialize afdal subsystem 
        afdal_init ();

        // Login agaisnt the server 
        init_function ();
        
        while (1) {
                // display menu, ask user for an action
                g_print ("Synchronous timeout check:\n");
                g_print ("  options available:\n");
                g_print ("  1. Set timeout to be used (current: %d seconds)\n",
                         afdal_sync_get_timeout () / 1000000);
                g_print ("  2. Run test\n");
                g_print ("     To exit simply type control-C\n");
                line = readline ("--> ");

                // set a timeout
                if (!g_strcasecmp ("1", line)) {
                        line = readline ("new timeout to set (in milliseconds): ");
                        
                        afdal_sync_set_timeout (g_strtod (line, NULL));
                        // g_print ("Timeout out set to: %s\n", line);
                }

                // perform a test
                if (!g_strcasecmp ("2", line)) {
                        data = afdal_af_test_timeout_service_sync ();
                        if (AFDAL_IS_OK (data)) {
                                g_print ("Response was: %s\n", 
                                         AFDAL_RESPONSE (data));
                        }else {
                                g_print ("Error: response was: %s\n", 
                                         AFDAL_RESPONSE (data));
                        }
                        afdal_nul_free (data);
                }
        }
        
        return;
}

Building the example

NOTE: The easy way to compile this example is to use the repository inside Af-Arch. Just type make inside the af-arch/doc/examples/sync directory.

Anyway, to get ready this example you will have to:

  1. Have a working Af-Arch installation (well, this is quite obvious ;-) You can check this section to know more about installing Af-Arch
  2. Compile previous IDL definition using af-gen tools as follows:
          af-gen --base-dir . af-test.idl
    
  3. Compile client STUB connector generated by af-gen tool as follows:
          cd libafdal-af-test
          ./autogen.sh
          <<before a while and some autoconf output>>
          make
          make install
    
  4. Compile our test server:
          cd af-kernel
          ./autogen.sh
          <<before a while and some autoconf output>>
          make
          make install
    
  5. Configure server settings. You can use the following configuration:
    # Config file 
    # 
    # Lines starting with # are comments. 
    
    listening port = auto
    listening hostname = any
    
    kernel server = localhost 
    kernel port = 55000 
    
    database server =
    database port = 
    database name =
    database user = 
    database password = 
    
    
    log file = /tmp/af-test.log
    log active = yes
    
    afkey expiration = 3600
    
    # The file must end with a new line
    

    Usually this config file should be placed on /etc/af-arch directory but, this depends on your af-arch installation and your af-test installation.

    Anyway, don't worry too much about this because every server reports you where was trying to look up the config file in case the server can't found it.

  6. For the first time the server is loaded, you must register its services. This is done by typing:
          af-test --update-services
          <<before af-test have register, run af-test again>>
    
          af-test
    
  7. Compile the client program using the following:
          gcc `pkg-config --libs --cflags glib-2.0 afdal_af_test afdal` \
               -lreadline -o test-sync main.c
    

Testing synchronous timeouts