rpc_lesson1¶
Two models run in a client-server, remote procedure call (RPC) communication pattern. The client model client sends requests and receives 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 client model also sends request/response pairs to 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 exit_code = 0;
9 printf("Hello from C client: iterations %d\n", iterations);
10
11 // Set up connections matching yaml
12 // RPC client-side connection will be $(server_name)_$(client_name)
13 yggRpc_t rpc = yggRpcClient("server_client", "%d", "%d");
14 yggOutput_t log = yggOutputFmt("output_log", "fib(%-2d) = %-2d\n");
15
16 // Initialize variables
17 int ret = 0;
18 int fib = -1;
19 char *logmsg = (char*)malloc(YGG_MSG_MAX*sizeof(char));
20 int i;
21
22 // Iterate over Fibonacci sequence
23 for (i = 1; i <= iterations; i++) {
24
25 // Call the server and receive response
26 printf("client(C): Calling fib(%d)\n", i);
27 ret = rpcCall(rpc, i, &fib);
28 if (ret < 0) {
29 printf("client(C): RPC CALL ERROR\n");
30 exit_code = -1;
31 break;
32 }
33 printf("client(C): Response fib(%d) = %d\n", i, fib);
34
35 // Log result by sending it to the log connection
36 ret = yggSend(log, i, fib);
37 if (ret < 0) {
38 printf("client(C): SEND ERROR\n");
39 exit_code = -1;
40 break;
41 }
42 }
43
44 free(logmsg);
45 printf("Goodbye from C client\n");
46 return exit_code;
47
48}
49
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
3model:
4 name: client
5 language: c
6 args:
7 - ./src/client.c
8 - 3 # Pass the number of iterations that should be performed
9 client_of: server # Creates an RPC client queue "server_client"
10 outputs: output_log
11
12connections:
13 input: output_log
14 output: client_output.txt
15 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 exit_code = 0;
9 printf("Hello from C++ client: iterations %d\n", iterations);
10
11 // Set up connections matching yaml
12 // RPC client-side connection will be $(server_name)_$(client_name)
13 YggRpcClient rpc("server_client", "%d", "%d");
14 YggOutput log("output_log", "fib(%-2d) = %-2d\n");
15
16 // Initialize variables
17 int ret = 0;
18 int fib = -1;
19 char *logmsg = (char*)malloc(YGG_MSG_MAX*sizeof(char));
20 int i;
21
22 // Iterate over Fibonacci sequence
23 for (i = 1; i <= iterations; i++) {
24
25 // Call the server and receive response
26 printf("client(C++): Calling fib(%d)\n", i);
27 ret = rpc.call(2, i, &fib);
28 if (ret < 0) {
29 printf("client(C++): RPC CALL ERROR\n");
30 exit_code = -1;
31 break;
32 }
33 printf("client(C++): Response fib(%d) = %d\n", i, fib);
34
35 // Log result by sending it to the log connection
36 ret = log.send(2, i, fib);
37 if (ret < 0) {
38 printf("client(C++): SEND ERROR\n");
39 exit_code = -1;
40 break;
41 }
42 }
43
44 free(logmsg);
45 printf("Goodbye from C++ client\n");
46 return exit_code;
47}
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
3model:
4 name: client
5 language: c++
6 args:
7 - ./src/client.cpp
8 - 3 # Pass the number of iterations that should be performed
9 client_of: server # Creates an RPC client queue "server_client"
10 outputs: output_log
11
12connections:
13 input: output_log
14 output: client_output.txt
15 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
6 type(yggcomm) :: rpc
7 type(yggcomm) :: log
8 logical :: ret
9 integer :: fib, i
10 integer :: exit_code = 0
11
12 call get_command_argument(1, arg)
13 read(arg, *) iterations
14 write(*, '("Hello from Fortran client: iterations ",i2)') iterations
15
16 ! Set up connections matching yaml
17 ! RPC client-side connection will be $(server_name)_$(client_name)
18 rpc = ygg_rpc_client("server_client", "%d", "%d")
19 log = ygg_output_fmt("output_log", "fib(%-2d) = %-2d\n")
20
21 ! Initialize variables
22 ret = .true.
23 fib = -1
24
25 ! Iterate over Fibonacci sequence
26 do i = 1, iterations
27
28 ! Call the server and receive response
29 write(*, '("client(F): Calling fib(",i2,")")') i
30 ret = ygg_rpc_call(rpc, yggarg(i), yggarg(fib))
31 if (.not.ret) then
32 write(*, '("client(F): RPC CALL ERROR")')
33 exit_code = -1;
34 exit
35 end if
36 write(*, '("client(F): Response fib(",i2,") = ",i2)') i, fib
37
38 ! Log result by sending it to the log connection
39 ret = ygg_send_var(log, [yggarg(i), yggarg(fib)])
40 if (.not.ret) then
41 write(*, '("client(F): SEND ERROR")')
42 exit_code = -1
43 exit
44 end if
45
46 end do
47
48 write(*, '("Goodbye from Fortran client")')
49 if (exit_code.lt.0) then
50 stop 1
51 end if
52
53end 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
3model:
4 name: client
5 language: fortran
6 args:
7 - ./src/client.f90
8 - 3 # Pass the number of iterations that should be performed
9 client_of: server # Creates an RPC client queue "server_client"
10 outputs: output_log
11
12connections:
13 input: output_log
14 output: client_output.txt
15 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)
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", "server_client", "%d", "%d")
12 log = Yggdrasil.YggInterface("YggOutput", "output_log", "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(Julia): Calling fib(%d)\n", i)
19 ret, result = rpc.call(i)
20 if (!ret)
21 error("client(Julia): RPC CALL ERROR")
22 end
23 fib = result[1]
24 @printf("client(Julia): Response fib(%d) = %d\n", i, fib)
25
26 # Log result by sending it to the log connection
27 ret = log.send(i, fib)
28 if (!ret)
29 error("client(Julia): SEND ERROR")
30 end
31 end
32
33 println("Goodbye from Julia client")
34end
35
36
37main(parse(Int64, ARGS[1]))
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
3model:
4 name: client
5 language: julia
6 args:
7 - ./src/client.jl
8 - 3 # Pass the number of iterations that should be performed
9 client_of: server # Creates an RPC client queue "server_client"
10 outputs: output_log
11
12connections:
13 input: output_log
14 output: client_output.txt
15 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)
2
3 iterations = str2num(iterations);
4 fprintf('Hello from Matlab client: iterations = %d\n', iterations);
5
6 % Set up connections matching yaml
7 % RPC client-side connection will be $(server_name)_$(client_name)
8 rpc = YggInterface('YggRpcClient', 'server_client', '%d', '%d');
9 log = YggInterface('YggOutput', 'output_log', 'fib(%-2d) = %-2d\n');
10
11 % Iterate over Fibonacci sequence
12 for i = 1:iterations
13
14 % Call the server and receive response
15 fprintf('client(Matlab): Calling fib(%d)\n', i);
16 [ret, result] = rpc.call(int32(i));
17 if (~ret);
18 error('client(Matlab): RPC CALL ERROR');
19 end;
20 fib = result{1};
21 fprintf('client(Matlab): Response fib(%d) = %d\n', i, fib);
22
23 % Log result by sending it to the log connection
24 ret = log.send(int32(i), fib);
25 if (~ret);
26 error('client(Matlab): SEND ERROR');
27 end;
28 end;
29
30 disp('Goodbye from Matlab client');
31
32end
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
3model:
4 name: client
5 language: matlab
6 args:
7 - ./src/client.m
8 - 3 # Pass the number of iterations that should be performed
9 client_of: server # Creates an RPC client queue "server_client"
10 outputs: output_log
11
12connections:
13 input: output_log
14 output: client_output.txt
15 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(P): ERROR receiving parameters')
38 print('server(P): 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(P): receiving...')
47 retval, rpc_in = rpc.recv()
48 if not retval:
49 print('server(P): end of input')
50 break
51
52 # Compute fibonacci number
53 n = rpc_in[0]
54 print('server(P): Received request for Fibonacci number %d' % n)
55 result = get_fibonacci(n)
56 print('server(P): 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(P): 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):
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
14 """
15
16 print('Hello from Python client: iterations = %d ' % iterations)
17
18 # Set up connections matching yaml
19 # RPC client-side connection will be $(server_name)_$(client_name)
20 rpc = YggRpcClient("server_client", "%d", "%d")
21 log = YggOutput("output_log", 'fib(%-2d) = %-2d\n')
22
23 # Iterate over Fibonacci sequence
24 for i in range(1, iterations + 1):
25
26 # Call the server and receive response
27 print('client(Python): Calling fib(%d)' % i)
28 ret, result = rpc.call(np.int32(i))
29 if not ret:
30 raise RuntimeError('client(Python): RPC CALL ERROR')
31 fib = result[0]
32 print('client(Python): Response fib(%d) = %d' % (i, fib))
33
34 # Log result by sending it to the log connection
35 ret = log.send(np.int32(i), fib)
36 if not ret:
37 raise RuntimeError('client(Python): SEND ERROR')
38
39 print('Goodbye from Python client')
40
41
42if __name__ == '__main__':
43 # Take number of iterations from the first argument
44 main(int(sys.argv[1]))
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
3model:
4 name: client
5 language: python
6 args:
7 - ./src/client.py
8 - 3 # Pass the number of iterations that should be performed
9 client_of: server # Creates an RPC client queue "server_client"
10 outputs: output_log
11
12connections:
13 input: output_log
14 output: client_output.txt
15 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) {
5
6 fprintf('Hello from R 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', "server_client", "%d", "%d")
11 log <- YggInterface('YggOutput', "output_log", 'fib(%-2d) = %-2d\n')
12
13 # Iterate over Fibonacci sequence
14 for (i in 1:iterations) {
15
16 # Call the server and receive response
17 fprintf('client(R): Calling fib(%d)', i)
18 c(ret, result) %<-% rpc$call(i)
19 if (!ret) {
20 stop('client(R): RPC CALL ERROR')
21 }
22 fib <- result[[1]]
23 fprintf('client(R): Response fib(%d) = %d', i, fib)
24
25 # Log result by sending it to the log connection
26 ret <- log$send(i, fib)
27 if (!ret) {
28 stop('client(R): SEND ERROR')
29 }
30 }
31
32 print('Goodbye from R client')
33}
34
35
36args = commandArgs(trailingOnly=TRUE)
37main(strtoi(args[[1]]))
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
3model:
4 name: client
5 language: R
6 args:
7 - ./src/client.R
8 - 3 # Pass the number of iterations that should be performed
9 client_of: server # Creates an RPC client queue "server_client"
10 outputs: output_log
11
12connections:
13 input: output_log
14 output: client_output.txt
15 in_temp: True