rpc_lesson2

Three models run in a client-server, remote procedure call (RPC) communication pattern. The two client models (client1 & client2) send requests and receive response to/from the server model server via the deprecated call method. The server model receives requests and send responses. This example demostrates the RPC pattern through the use of the client_of and is_server model parameters and the RPC interface classes/functions. The client1 & client2 models also send request/response pairs to files in the temporary directory and receive parameters via the command line as specified in the YAML (both model call the same source code). The server model receives parameters as input from a file.

C Version

Model Code:

 1#include "YggInterface.h"
 2#include <stdio.h>
 3
 4
 5int get_fibonacci(int n) {
 6  int pprev = 0, prev = 1, result = 1, fib_no = 1;
 7  while (fib_no < n) {
 8    result = prev + pprev;
 9    pprev = prev;
10    prev = result;
11    fib_no = fib_no + 1;
12  }
13  return result;
14};
15
16
17int main(int argc, char *argv[]) {
18  
19  int exit_code = 0;
20  printf("Hello from C server!\n");
21
22  // Create server-side rpc conneciton using model name
23  yggRpc_t rpc = yggRpcServer("server", "%d", "%d");
24
25  // Continue receiving requests until the connection is closed when all
26  // clients have disconnected.
27  int flag, n, result;
28  while (1) {
29    printf("server(C): receiving...\n");
30    flag = rpcRecv(rpc, &n);
31    if (flag < 0) {
32      printf("server(C): end of input\n");
33      break;
34    }
35
36    // Compute fibonacci number
37    printf("server(C): Received request for Fibonacci number %d\n", n);
38    result = get_fibonacci(n);
39    printf("server(C): Sending response for Fibonacci number %d: %d\n",
40	   n, result);
41
42    // Send response back
43    flag = rpcSend(rpc, result);
44    if (flag < 0) {
45      printf("server(C): ERROR sending\n");
46      exit_code = -1;
47      break;
48    }
49  }
50
51  printf("Goodbye from C server\n");
52  return exit_code;
53};
 1#include "YggInterface.h"
 2#include <stdio.h>
 3
 4
 5int main(int argc, char *argv[]) {
 6   
 7  int iterations = atoi(argv[1]);
 8  int client_index = atoi(argv[2]);
 9  int exit_code = 0;
10  printf("Hello from C client%d: iterations %d\n",
11	 client_index, iterations);
12  
13  // Set up connections matching yaml
14  // RPC client-side connection will be $(server_name)_$(client_name)
15  char rpc_name[100];
16  char log_name[100];
17  sprintf(rpc_name, "server_client%d", client_index);
18  sprintf(log_name, "output_log%d", client_index);
19  yggRpc_t rpc = yggRpcClient(rpc_name, "%d", "%d");
20  yggOutput_t log = yggOutputFmt(log_name, "fib(%-2d) = %-2d\n");
21
22  // Initialize variables
23  int ret = 0;
24  int fib = -1;
25  int i;
26
27  // Iterate over Fibonacci sequence
28  for (i = 1; i <= iterations; i++) {
29    
30    // Call the server and receive response
31    printf("client%d(C): Calling fib(%d)\n", client_index, i);
32    ret = rpcCall(rpc, i, &fib);
33    if (ret < 0) {
34      printf("client%d(C): RPC CALL ERROR\n", client_index);
35      exit_code = -1;
36      break;
37    }
38    printf("client%d(C): Response fib(%d) = %d\n", client_index, i, fib);
39
40    // Log result by sending it to the log connection
41    ret = yggSend(log, i, fib);
42    if (ret < 0) {
43      printf("client%d(C): SEND ERROR\n", client_index);
44      exit_code = -1;
45      break;
46    }
47  }
48
49  printf("Goodbye from C client%d\n", client_index);
50  return exit_code;
51    
52}
53

Model YAML:

1---
2
3model:
4  name: server
5  language: c
6  args: ./src/server.c
7  is_server: True  # Creates a RPC server queue called "server"
 1---
 2
 3models:
 4  - name: client1
 5    language: c
 6    args:
 7      - ./src/client.c
 8      - 3  # Pass the number of iterations that should be performed
 9      - 1  # Pass index of the client
10    client_of: server  # Creates an RPC client queue "server_client"
11    outputs: output_log1
12  - name: client2
13    language: c
14    args:
15      - ./src/client.c
16      - 5  # Pass the number of iterations that should be performed
17      - 2  # Pass index of the client
18    client_of: server  # Creates an RPC client queue "server_client"
19    outputs: output_log2
20
21connections:
22  - input: output_log1
23    output: client_output1.txt
24    in_temp: true
25  - input: output_log2
26    output: client_output2.txt
27    in_temp: true

C++ Version

Model Code:

 1#include "YggInterface.hpp"
 2#include <stdio.h>
 3
 4
 5int get_fibonacci(int n) {
 6  int pprev = 0, prev = 1, result = 1, fib_no = 1;
 7  while (fib_no < n) {
 8    result = prev + pprev;
 9    pprev = prev;
10    prev = result;
11    fib_no = fib_no + 1;
12  }
13  return result;
14};
15
16
17int main(int argc, char *argv[]) {
18  
19  int exit_code = 0;
20  printf("Hello from C++ server!\n");
21
22  // Create server-side rpc conneciton using model name
23  YggRpcServer rpc("server", "%d", "%d");
24
25  // Continue receiving requests until the connection is closed when all
26  // clients have disconnected.
27  int flag, n, result;
28  while (1) {
29    printf("server(C++): receiving...\n");
30    flag = rpc.recv(1, &n);
31    if (flag < 0) {
32      printf("server(C++): end of input\n");
33      break;
34    }
35
36    // Compute fibonacci number
37    printf("server(C++): Received request for Fibonacci number %d\n", n);
38    result = get_fibonacci(n);
39    printf("server(C++): Sending response for Fibonacci number %d: %d\n",
40	   n, result);
41
42    // Send response back
43    flag = rpc.send(1, result);
44    if (flag < 0) {
45      printf("server(C++): ERROR sending\n");
46      exit_code = -1;
47      break;
48    }
49  }
50
51  printf("Goodbye from C++ server\n");
52  return exit_code;
53};
 1#include "YggInterface.hpp"
 2#include <stdio.h>
 3
 4
 5int main(int argc, char *argv[]) {
 6   
 7  int iterations = atoi(argv[1]);
 8  int client_index = atoi(argv[2]);
 9  int exit_code = 0;
10  printf("Hello from C++ client%d: iterations %d\n",
11	 client_index, iterations);
12  
13  // Set up connections matching yaml
14  // RPC client-side connection will be $(server_name)_$(client_name)
15  char rpc_name[100];
16  char log_name[100];
17  sprintf(rpc_name, "server_client%d", client_index);
18  sprintf(log_name, "output_log%d", client_index);
19  YggRpcClient rpc(rpc_name, "%d", "%d");
20  YggOutput log(log_name, "fib(%-2d) = %-2d\n");
21  
22  // Initialize variables
23  int ret = 0;
24  int fib = -1;
25  char *logmsg = (char*)malloc(YGG_MSG_MAX*sizeof(char));
26  int i;
27
28  // Iterate over Fibonacci sequence
29  for (i = 1; i <= iterations; i++) {
30    
31    // Call the server and receive response
32    printf("client%d(C++): Calling fib(%d)\n", client_index, i);
33    ret = rpc.call(2, i, &fib);
34    if (ret < 0) {
35      printf("client%d(C++): RPC CALL ERROR\n", client_index);
36      exit_code = -1;
37      break;
38    }
39    printf("client%d(C++): Response fib(%d) = %d\n", client_index, i, fib);
40
41    // Log result by sending it to the log connection
42    ret = log.send(2, i, fib);
43    if (ret < 0) {
44      printf("client%d(C++): SEND ERROR\n", client_index);
45      exit_code = -1;
46      break;
47    }
48  }
49
50  free(logmsg);
51  printf("Goodbye from C++ client%d\n", client_index);
52  return exit_code;
53}

Model YAML:

1---
2
3model:
4  name: server
5  language: c++
6  args: ./src/server.cpp
7  is_server: True  # Creates a RPC server queue called "server"
 1---
 2
 3models:
 4  - name: client1
 5    language: c++
 6    args:
 7      - ./src/client.cpp
 8      - 3  # Pass the number of iterations that should be performed
 9      - 1  # Pass index of the client
10    client_of: server  # Creates an RPC client queue "server_client"
11    outputs: output_log1
12  - name: client2
13    language: c++
14    args:
15      - ./src/client.cpp
16      - 5  # Pass the number of iterations that should be performed
17      - 2  # Pass index of the client
18    client_of: server  # Creates an RPC client queue "server_client"
19    outputs: output_log2
20
21connections:
22  - input: output_log1
23    output: client_output1.txt
24    in_temp: true
25  - input: output_log2
26    output: client_output2.txt
27    in_temp: true

Fortran Version

Model Code:

 1program main
 2  use fygg
 3
 4  interface
 5     function get_fibonacci(n) result(out)
 6       integer, intent(in) :: n
 7       integer :: out
 8     end function get_fibonacci
 9  end interface
10
11  type(yggcomm) :: rpc
12  logical :: ret
13  integer :: fib, n
14  integer :: exit_code = 0
15
16  write(*, '("Hello from Fortran server!")')
17
18  ! Create server-side rpc conneciton using model name
19  rpc = ygg_rpc_server("server", "%d", "%d")
20
21  ! Initialize variables
22  ret = .true.
23  fib = -1
24
25  ! Continue receiving requests until the connection is closed when all
26  ! clients have disconnected.
27  do while (.TRUE.)
28     write(*, '("server(F): receiving...")')
29     ret = ygg_recv_var(rpc, yggarg(n))
30     if (.not.ret) then
31        write(*, '("server(F): end of input")')
32        exit
33     end if
34
35     ! Compute fibonacci number
36     write(*, '("server(F): Received request for Fibonacci number ",i2)') n
37     fib = get_fibonacci(n)
38     write(*, '("server(F): Sending response for Fibonacci number ",i2,": ",i2)') n, fib
39
40     ! Send response back
41     ret = ygg_send_var(rpc, yggarg(fib))
42     if (.not.ret) then
43        write(*, '("server(F): ERROR sending")')
44        exit_code = -1;
45        exit;
46     end if
47  end do
48
49  write(*, '("Goodbye from Fortran server")')
50  if (exit_code.lt.0) then
51     stop 1
52  end if
53
54end program main
55
56function get_fibonacci(n) result(out)
57  integer, intent(in) :: n
58  integer :: out
59  integer :: pprev, prev, fib_no
60  pprev = 0
61  prev = 1
62  out = 1
63  fib_no = 1
64  do while (fib_no < n)
65     out = prev + pprev
66     pprev = prev
67     prev = out
68     fib_no = fib_no + 1
69  end do
70end function get_fibonacci
 1program main
 2  use fygg
 3
 4  character(len=32) :: arg
 5  integer :: iterations, client_index
 6  type(yggcomm) :: rpc
 7  type(yggcomm) :: log
 8  logical :: ret
 9  integer :: fib, i
10  integer :: exit_code = 0
11  character(len=100) :: rpc_name
12  character(len=100) :: log_name
13
14  call get_command_argument(1, arg)
15  read(arg, *) iterations
16  call get_command_argument(2, arg)
17  read(arg, *) client_index
18  write(*, '("Hello from Fortran client",i1,": iterations ",i2)') &
19       client_index, iterations
20
21  ! Set up connections matching yaml
22  ! RPC client-side connection will be $(server_name)_$(client_name)
23  write(rpc_name, '("server_client",i1)') client_index
24  write(log_name, '("output_log",i1)') client_index
25  rpc = ygg_rpc_client(trim(rpc_name), "%d", "%d")
26  log = ygg_output_fmt(trim(log_name), "fib(%-2d) = %-2d\n")
27
28  ! Initialize variables
29  ret = .true.
30  fib = -1
31
32  ! Iterate over Fibonacci sequence
33  do i = 1, iterations
34
35     ! Call the server and receive response
36     write(*, '("client",i1,"(F): Calling fib(",i2,")")') &
37          client_index, i
38     ret = ygg_rpc_call(rpc, yggarg(i), yggarg(fib))
39     if (.not.ret) then
40        write(*, '("client",i1,"(F): RPC CALL ERROR")') client_index
41        exit_code = -1;
42        exit
43     end if
44     write(*, '("client",i1,"(F): Response fib(",i2,") = ",i2)') &
45          client_index, i, fib
46
47     ! Log result by sending it to the log connection
48     ret = ygg_send_var(log, [yggarg(i), yggarg(fib)])
49     if (.not.ret) then
50        write(*, '("client",i1,"(F): SEND ERROR")') client_index
51        exit_code = -1
52        exit
53     end if
54
55  end do
56
57  write(*, '("Goodbye from Fortran client",i1)') client_index
58  if (exit_code.lt.0) then
59     stop 1
60  end if
61
62end program main

Model YAML:

1---
2
3model:
4  name: server
5  language: fortran
6  args: ./src/server.f90
7  is_server: True  # Creates a RPC server queue called "server"
 1---
 2
 3models:
 4  - name: client1
 5    language: fortran
 6    args:
 7      - ./src/client.f90
 8      - 3  # Pass the number of iterations that should be performed
 9      - 1  # Pass index of the client
10    client_of: server  # Creates an RPC client queue "server_client"
11    outputs: output_log1
12  - name: client2
13    language: fortran
14    args:
15      - ./src/client.f90
16      - 5  # Pass the number of iterations that should be performed
17      - 2  # Pass index of the client
18    client_of: server  # Creates an RPC client queue "server_client"
19    outputs: output_log2
20
21connections:
22  - input: output_log1
23    output: client_output1.txt
24    in_temp: true
25  - input: output_log2
26    output: client_output2.txt
27    in_temp: true

Julia Version

Model Code:

 1using Yggdrasil
 2using Printf
 3
 4
 5function get_fibonacci(n)
 6  global pprev = 0
 7  global prev = 1
 8  global result = 1
 9  global fib_no = 1
10  while (fib_no < n)
11    global result = prev + pprev
12    global pprev = prev
13    global prev = result
14    global fib_no = fib_no + 1
15  end
16  return Int64(result)
17end
18
19
20function main()
21
22  println("Hello from Julia server!")
23
24  # Create server-side rpc conneciton using model name
25  rpc = Yggdrasil.YggInterface("YggRpcServer", "server", "%d", "%d")
26
27  # Continue receiving requests until the connection is closed when all
28  # clients have disconnected.
29  while (true)
30    println("server(Julia): receiving...")
31    retval, rpc_in = rpc.recv()
32    if (!retval)
33      println("server(Julia): end of input")
34      break
35    end
36
37    # Compute fibonacci number
38    n = rpc_in[1]
39    @printf("server(Julia): Received request for Fibonacci number %d\n", n)
40    result = get_fibonacci(n)
41    @printf("server(Julia): Sending response for Fibonacci number %d: %d\n", n, result)
42
43    # Send response back
44    flag = rpc.send(result)
45    if (!flag)
46      error("server(Julia): ERROR sending")
47    end
48  end
49  
50  println("Goodbye from Julia server")
51end
52
53main()
 1using Yggdrasil
 2using Printf
 3
 4
 5function main(iterations, client_index)
 6    
 7  @printf("Hello from Julia client: iterations = %d\n", iterations)
 8
 9  # Set up connections matching yaml
10  # RPC client-side connection will be $(server_name)_$(client_name)
11  rpc = Yggdrasil.YggInterface("YggRpcClient", @sprintf("server_client%d", client_index), "%d", "%d")
12  log = Yggdrasil.YggInterface("YggOutput", @sprintf("output_log%d", client_index), "fib(%-2d) = %-2d\n")
13
14  # Iterate over Fibonacci sequence
15  for i = 1:iterations
16        
17    # Call the server and receive response
18    @printf("client%d(Julia): Calling fib(%d)\n", client_index, i)
19    ret, result = rpc.call(i)
20    if (!ret)
21      error(@sprintf("client%d(Julia): RPC CALL ERROR", client_index))
22    end
23    fib = result[1]
24    @printf("client%d(Julia): Response fib(%d) = %d\n", client_index, i, fib)
25
26    # Log result by sending it to the log connection
27    ret = log.send(i, fib)
28    if (!ret)
29      error(@sprintf("client%d(Julia): SEND ERROR", client_index))
30    end
31  end
32
33  @printf("Goodbye from Julia client%d\n", client_index)
34end
35
36    
37main(parse(Int64, ARGS[1]), parse(Int64, ARGS[2]))

Model YAML:

1---
2
3model:
4  name: server
5  language: julia
6  args: ./src/server.jl
7  is_server: True  # Creates a RPC server queue called "server"
 1---
 2
 3models:
 4  - name: client1
 5    language: julia
 6    args:
 7      - ./src/client.jl
 8      - 3  # Pass the number of iterations that should be performed
 9      - 1  # Pass index of the client
10    client_of: server  # Creates an RPC client queue "server_client"
11    outputs: output_log1
12  - name: client2
13    language: julia
14    args:
15      - ./src/client.jl
16      - 5  # Pass the number of iterations that should be performed
17      - 2  # Pass index of the client
18    client_of: server  # Creates an RPC client queue "server_client"
19    outputs: output_log2
20
21connections:
22  - input: output_log1
23    output: client_output1.txt
24    in_temp: true
25  - input: output_log2
26    output: client_output2.txt
27    in_temp: true

Matlab Version

Model Code:

 1function server()
 2  
 3  disp('Hello from Matlab server!');
 4
 5  % Create server-side rpc conneciton using model name
 6  rpc = YggInterface('YggRpcServer', 'server', '%d', '%d');
 7
 8  % Continue receiving requests until the connection is closed when all
 9  % clients have disconnected.
10  while true
11    disp('server(M): receiving...');
12    [retval, rpc_in] = rpc.recv();
13    if (~retval);
14      disp('server(M):end of input');
15      break;
16    end;
17
18    % Compute fibonacci number
19    n = rpc_in{1};
20    fprintf('server(M): Received request for Fibonacci number %d\n', n);
21    pprev = 0;
22    prev = 1;
23    result = 1;
24    fib_no = 1;
25    while fib_no < n
26      result = prev + pprev;
27      pprev = prev;
28      prev = result;
29      fib_no = fib_no + 1;
30    end;
31    fprintf('server(M): Sending response for Fibonacci number %d: %d\n', n, result);
32
33    % Send response back
34    flag = rpc.send(int32(result));
35    if (~flag);
36      error('server(M): ERROR sending');
37    end;
38  end;
39
40  disp('Goodbye from Matlab server');
41  
42end
 1function client(iterations, client_index)
 2  
 3  iterations = str2num(iterations);
 4  client_index = str2num(client_index);
 5  fprintf('Hello from Matlab client%d: iterations = %d\n', ...
 6          client_index, iterations);
 7
 8  % Set up connections matching yaml
 9  % RPC client-side connection will be $(server_name)_$(client_name)
10  rpc_name = sprintf('server_client%d', client_index);
11  log_name = sprintf('output_log%d', client_index);
12  rpc = YggInterface('YggRpcClient', rpc_name, '%d', '%d');
13  log = YggInterface('YggOutput', log_name, 'fib(%-2d) = %-2d\n');
14
15  % Iterate over Fibonacci sequence
16  for i = 1:iterations
17    
18    % Call the server and receive response
19    fprintf('client%d(Matlab): Calling fib(%d)\n', client_index, i);
20    [ret, result] = rpc.call(int32(i));
21    if (~ret);
22      error(sprintf('client%d(Matlab): RPC CALL ERROR\n', client_index));
23    end;
24    fib = result{1};
25    fprintf('client%d(Matlab): Response fib(%d) = %d\n', client_index, ...
26            i, fib);
27
28    % Log result by sending it to the log connection
29    ret = log.send(int32(i), fib);
30    if (~ret);
31      error(sprintf('client%d(Matlab): SEND ERROR\n', client_index));
32    end;
33  end;
34
35  fprintf('Goodbye from Matlab client%d\n', client_index);
36  
37end

Model YAML:

1---
2
3model:
4  name: server
5  language: matlab
6  args: ./src/server.m
7  is_server: True  # Creates a RPC server queue called "server"
 1---
 2
 3models:
 4  - name: client1
 5    language: matlab
 6    args:
 7      - ./src/client.m
 8      - 3  # Pass the number of iterations that should be performed
 9      - 1  # Pass index of the client
10    client_of: server  # Creates an RPC client queue "server_client"
11    outputs: output_log1
12  - name: client2
13    language: matlab
14    args:
15      - ./src/client.m
16      - 5  # Pass the number of iterations that should be performed
17      - 2  # Pass index of the client
18    client_of: server  # Creates an RPC client queue "server_client"
19    outputs: output_log2
20
21connections:
22  - input: output_log1
23    output: client_output1.txt
24    in_temp: true
25  - input: output_log2
26    output: client_output2.txt
27    in_temp: true

Python Version

Model Code:

 1import numpy as np
 2from yggdrasil.interface.YggInterface import YggInput, YggRpcServer
 3
 4
 5def get_fibonacci(n):
 6    r"""Compute the nth number of the Fibonacci sequence.
 7
 8    Args:
 9        n (int): Index of the Fibonacci number in the Fibonacci sequence that
10            should be returned.
11
12    Returns:
13        int: The nth Fibonacci number.
14
15    """
16    pprev = 0
17    prev = 1
18    result = 1
19    fib_no = 1
20    while fib_no < n:
21        result = prev + pprev
22        pprev = prev
23        prev = result
24        fib_no = fib_no + 1
25    return result
26
27
28def main():
29    r"""Function to execute server communication and computation in a loop."""
30
31    print('Hello from Python server!')
32
33    # Get parameters
34    inp = YggInput("params")
35    retval, params = inp.recv()
36    if not retval:
37        raise RuntimeError('server: ERROR receiving parameters')
38    print('server: Parameters = %s' % params)
39
40    # Create server-side rpc conneciton using model name
41    rpc = YggRpcServer("server", "%d", "%d")
42
43    # Continue receiving requests until the connection is closed when all
44    # clients have disconnected.
45    while True:
46        print('server: receiving...')
47        retval, rpc_in = rpc.recv()
48        if not retval:
49            print('server: end of input')
50            break
51
52        # Compute fibonacci number
53        n = rpc_in[0]
54        print('server: Received request for Fibonacci number %d' % n)
55        result = get_fibonacci(n)
56        print('server: Sending response for Fibonacci number %d: %d' % (n, result))
57
58        # Send response back
59        flag = rpc.send(np.int32(result))
60        if not flag:
61            raise RuntimeError('server: ERROR sending')
62
63    print('Goodbye from Python server')
64
65    
66if __name__ == '__main__':
67    main()
 1import sys
 2import numpy as np
 3from yggdrasil.interface.YggInterface import (
 4    YggRpcClient, YggOutput)
 5
 6
 7def main(iterations, client_index):
 8    r"""Function to execute client communication with server that computes
 9    numbers in the Fibonacci sequence.
10
11    Args:
12        iterations (int): The number of Fibonacci numbers to log.
13        client_index (int): Index of the client in total list of clients.
14
15    """
16
17    print('Hello from Python client%d: iterations = %d ' % (client_index,
18                                                            iterations))
19
20    # Set up connections matching yaml
21    # RPC client-side connection will be $(server_name)_$(client_name)
22    rpc = YggRpcClient("server_client%d" % client_index, "%d", "%d")
23    log = YggOutput("output_log%d" % client_index, 'fib(%-2d) = %-2d\n')
24
25    # Iterate over Fibonacci sequence
26    for i in range(1, iterations + 1):
27        
28        # Call the server and receive response
29        print('client%d(Python): Calling fib(%d)' % (client_index, i))
30        ret, result = rpc.call(np.int32(i))
31        if not ret:
32            raise RuntimeError('client%d(Python): RPC CALL ERROR' % client_index)
33        fib = result[0]
34        print('client%d(Python): Response fib(%d) = %d' % (client_index, i, fib))
35
36        # Log result by sending it to the log connection
37        ret = log.send(np.int32(i), fib)
38        if not ret:
39            raise RuntimeError('client%d(Python): SEND ERROR' % client_index)
40
41    print('Goodbye from Python client%d' % client_index)
42
43    
44if __name__ == '__main__':
45    # Take number of iterations from the first argument and the
46    # client index from the second
47    main(int(sys.argv[1]), int(sys.argv[2]))

Model YAML:

 1---
 2
 3model:
 4  name: server
 5  language: python
 6  args: ./src/server.py
 7  is_server: True  # Creates a RPC server queue called "server"
 8  inputs:
 9    name: params
10    default_file:
11      name: ./Input/server_params.txt
12      filetype: ascii
 1---
 2
 3models:
 4  - name: client1
 5    language: python
 6    args:
 7      - ./src/client.py
 8      - 3  # Pass the number of iterations that should be performed
 9      - 1  # Pass index of the client
10    client_of: server  # Creates an RPC client queue "server_client"
11    outputs: output_log1
12  - name: client2
13    language: python
14    args:
15      - ./src/client.py
16      - 5  # Pass the number of iterations that should be performed
17      - 2  # Pass index of the client
18    client_of: server  # Creates an RPC client queue "server_client"
19    outputs: output_log2
20
21connections:
22  - input: output_log1
23    output: client_output1.txt
24    in_temp: true
25  - input: output_log2
26    output: client_output2.txt
27    in_temp: true

R Version

Model Code:

 1library(yggdrasil)
 2
 3
 4get_fibonacci <- function(n) {
 5  pprev = 0
 6  prev = 1
 7  result = 1
 8  fib_no = 1
 9  while (fib_no < n) {
10    result = prev + pprev
11    pprev = prev
12    prev = result
13    fib_no = fib_no + 1
14  }
15  return(as.integer(result))
16}
17
18
19main <- function() {
20
21  fprintf('Hello from R server!')
22
23  # Create server-side rpc conneciton using model name
24  rpc <- YggInterface('YggRpcServer', "server", "%d", "%d")
25
26  # Continue receiving requests until the connection is closed when all
27  # clients have disconnected.
28  while (1) {
29    fprintf('server(R): receiving...')
30    c(retval, rpc_in) %<-% rpc$recv()
31    if (!retval) {
32      fprintf('server(R): end of input')
33      break
34    }
35
36    # Compute fibonacci number
37    n = rpc_in[[1]]
38    fprintf('server(R): Received request for Fibonacci number %d', n)
39    result = get_fibonacci(n)
40    fprintf('server(R): Sending response for Fibonacci number %d: %d', n, result)
41
42    # Send response back
43    flag <- rpc$send(result)
44    if (!flag) {
45      stop('server(R): ERROR sending')
46    }
47    
48  }
49
50  print('Goodbye from R server')
51}
52
53main()
 1library(yggdrasil)
 2
 3
 4main <- function(iterations, client_index) {
 5
 6  fprintf('Hello from Python client: iterations = %d ', iterations)
 7
 8  # Set up connections matching yaml
 9  # RPC client-side connection will be $(server_name)_$(client_name)
10  rpc <- YggInterface('YggRpcClient',
11                      sprintf("server_client%d", client_index), "%d", "%d")
12  log <- YggInterface('YggOutput',
13                      sprintf("output_log%d", client_index), 'fib(%-2d) = %-2d\n')
14
15  # Iterate over Fibonacci sequence
16  for (i in 1:iterations) {
17        
18    # Call the server and receive response
19    fprintf('client%d(R): Calling fib(%d)', client_index, i)
20    c(ret, result) %<-% rpc$call(i)
21    if (!ret) {
22      stop(sprintf('client%d(R): RPC CALL ERROR', client_index))
23    }
24    fib <- result[[1]]
25    fprintf('client%d(R): Response fib(%d) = %d', client_index, i, fib)
26
27    # Log result by sending it to the log connection
28    ret <- log$send(i, fib)
29    if (!ret) {
30      stop(sprintf('client%d(R): SEND ERROR', client_index))
31    }
32  }
33
34  fprintf('Goodbye from R client%d', client_index)
35}
36
37
38args = commandArgs(trailingOnly=TRUE)
39main(strtoi(args[[1]]), strtoi(args[[2]]))

Model YAML:

1---
2
3model:
4  name: server
5  language: R
6  args: ./src/server.R
7  is_server: True  # Creates a RPC server queue called "server"
 1---
 2
 3models:
 4  - name: client1
 5    language: R
 6    args:
 7      - ./src/client.R
 8      - 3  # Pass the number of iterations that should be performed
 9      - 1  # Pass index of the client
10    client_of: server  # Creates an RPC client queue "server_client"
11    outputs: output_log1
12  - name: client2
13    language: R
14    args:
15      - ./src/client.R
16      - 5  # Pass the number of iterations that should be performed
17      - 2  # Pass index of the client
18    client_of: server  # Creates an RPC client queue "server_client"
19    outputs: output_log2
20
21connections:
22  - input: output_log1
23    output: client_output1.txt
24    in_temp: true
25  - input: output_log2
26    output: client_output2.txt
27    in_temp: true