////
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
*  KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
////
= Remote service admin based on shared memory

In order to reuse the (de)serialization features of remote service admin, 
the remote service admin will be realized by `rsa_shm` and `rsa_json_rpc` bundles.
The `rsa_shm` bundle is used to realize `remote_service_admin_service_t` and IPC. 
The `rsa_json_rpc` bundle is used to realize (de)serialization and Creating service endpoint/proxy.

To decouple `rsa_shm` and `rsa_json_rpc`, we abstract several non-OSGi standard interfaces as follows:

[plantuml]
----
@startuml
interface rsa_rpc_factory_t {
    + createProxy()
    + destroyProxy()
    + createEndPoint()
    + destroyEndPoint()
}

interface rsa_request_handler_service_t {
    + handleRequest()
}

interface rsa_request_sender_service_t {
    + sendRequest()
}
@enduml
----

== component diagram

[plantuml]
----
@startuml

component Consumer as "Service Consumer"
component RSA as "Remote Service Admin"
component TPM as "Topology Manager"
component RSA_RPC as "Remote service Admin RPC"

() remote_service_admin_service_t
() RS as "remote_service_t"
() RSProxy as "remote_service_t"
note bottom: remote service proxy
() rsa_rpc_factory_t
() rsa_request_handler_service_t
() rsa_request_sender_service_t

RSA -left-( rsa_rpc_factory_t
RSA_RPC -right- rsa_rpc_factory_t

RSA -up-( rsa_request_handler_service_t
RSA_RPC -up- rsa_request_handler_service_t

RSA -down- rsa_request_sender_service_t
RSA_RPC -down-( rsa_request_sender_service_t

RSA_RPC -down- RSProxy
RSA -right- remote_service_admin_service_t

TPM -left-( remote_service_admin_service_t
TPM .[dotted].> RS: <<monitors>>

Consumer -left-( RSProxy

@enduml
----

== remote service call

[plantuml]
----
@startuml
box "consumer process"
participant service_consumer
participant c_framework as "consumer framework"
participant c_rsa as "consumer rsa"
participant c_rpc as "consumer rpc"
end box

box "provider process"
participant p_rsa as "provider rsa"
participant p_rpc as "provider rpc"
participant remote_service
end box

service_consumer->c_framework ++:use/track remote service
c_framework->c_rpc ++:getService
c_rpc->c_rpc:create proxy service for remote service
return proxy service of remote service 
return proxy service of remote service

service_consumer -> c_rpc ++: call proxy service method
c_rpc -> c_rpc: serialize reuqest data
c_rpc -> c_rsa++: sendRequest
c_rsa  -> p_rsa++: IPC(shared memory), send request data

p_rsa->p_rpc++:handleRequest
p_rpc->p_rpc:deserialize reuqest data
p_rpc->remote_service++: call remote service
return response
p_rpc-->p_rpc:serialize response
return response
return IPC(shared memory), return response
return response
c_rpc --> c_rpc: deserialize response
return result
@enduml
----

== IPC for shared memory

In order to dynamically allocate shared memory only on the client. 
The client will transmit the shared memory id and shared memory offset to the server 
using a domain datagram socket. And response will reuse the shared memory of request.

[plantuml]
----
@startuml

control send_request_thread
participant shared_memory
queue domain_socket
control handle_request_thread

send_request_thread->shared_memory ++:shmPool_malloc
return shared memory address
send_request_thread->shared_memory:copy request to shared memory
send_request_thread->domain_socket:sendto(rsa_shm_msg_t)
loop pthread_cond_timedwait,\nUntil the response is readed completly
    send_request_thread->shared_memory:read response from shared memory
    note over shared_memory: If the response is complete,\n'msgState' will be set to 'REPLIED' or 'ABEND'\nby the 'handle_request_thread'
end

domain_socket->handle_request_thread:recvfrom(rsa_shm_msg_t)
handle_request_thread->shared_memory++:read request from shared memory
return
handle_request_thread->handle_request_thread:handleRequest
loop Until the response is writed completly
    handle_request_thread->shared_memory :copy response to shared memory
    handle_request_thread->handle_request_thread:pthread_cond_signal
end

send_request_thread->shared_memory :shmPool_free
@enduml
----