MqContextC - setup and manage a routing-link … More...
Macros | |
#define | MQ_ROUTE_CTX_MAX 50 |
maximum number of context-items in the return-array from MqRouteResolve … | |
Functions | |
MQ_EXTERN enum MkErrorE | MqRouteCreate_RT (MK_RT const mkrt, MQ_CTX ctx, MK_STRN route, MK_STRN service, bool overwrite) |
create/delete a routing-link between context an a service using route | |
MQ_EXTERN enum MkErrorE | MqRouteDelete_RT (MK_RT const mkrt, MQ_CTX ctx, MK_STRN route, MK_STRN service, bool overwrite) |
delete a routing-link created with MqRouteCreate | |
MQ_EXTERN enum MkErrorE | MqRouteTraverse_RT (MK_RT const mkrt, MQ_CTX ctx, MK_STRN service, MK_BAC args) |
traverse a tree down and call service if available. | |
MQ_EXTERN MQ_CTX_A | MqRouteResolve_RT (MK_RT const mkrt, MQ_CTX const ctx, MK_STRN const ident, MK_NUM const retnum) |
return a list of all context belonging to ident … | |
MQ_EXTERN enum MkErrorE | MqRouteGetPath_RT (MK_RT const mkrt, MQ_CTX const ctx, MK_STRN *path_out) |
return the absolut route-connection-string up to the current ctx … | |
MQ_EXTERN enum MkErrorE | MqRouteGetTree_RT (MK_RT const mkrt, MQ_CTX const ctx, MK_BFL *treeP_out) |
create an overview about all available routing-target and services … | |
MqContextC - MqContextC_RouteApi_Route_C_API - overload | |
#define | MqRouteGetTree_NULL(...) |
#define | MqRouteGetTree(...) |
#define | MqRouteGetTree_E(...) |
#define | MqRouteGetTree_C(...) |
#define | MqRouteGetTree_e(...) |
#define | MqRouteCreate_NULL(...) |
#define | MqRouteCreate(...) |
#define | MqRouteCreate_3(ctx, route, service) |
#define | MqRouteCreate_E(...) |
#define | MqRouteCreate_C(...) |
#define | MqRouteDelete_NULL(...) |
#define | MqRouteDelete(...) |
#define | MqRouteDelete_3(ctx, route, service) |
#define | MqRouteDelete_E(...) |
#define | MqRouteDelete_C(...) |
#define | MqRouteResolve_NULL(...) |
#define | MqRouteResolve(...) |
#define | MqRouteResolve_2(ctx, ident) |
#define | MqRouteTraverse_NULL(...) |
#define | MqRouteTraverse(...) |
#define | MqRouteTraverse_2(ctx, service) |
#define | MqRouteTraverse_E(...) |
#define | MqRouteTraverse_C(...) |
#define | MqRouteGetPath_NULL(...) |
#define | MqRouteGetPath(...) |
#define | MqRouteGetPath_E(...) |
#define | MqRouteGetPath_C(...) |
#define | MqRouteGetPath_e(...) |
MqContextC - setup and manage a routing-link …
A routing-link is the connection of two context, the route-source and the route-target, with a unspecifiend number of hub-context in between using a specific service-token.
A single context is identified by the context-identifier as returned by MqClassIdentGet.
A routing-link can be created using Service-Level-Routing or Package-Level-Routing.
The difference between Service-Level-Routing and Package-Level-Routing is the public versa private behaviour.
Summary:
(runtime) enum MkErrorE MqRouteCreate(MQ_CTX ctx, MK_STRN route, MK_STRN service, MK_BOOL overwrite)
using a route-connection-string and a service-token. The TCP/IP model define the following layers (from: https://www.geeksforgeeks.org/tcp-ip-model/) :
The libmqmsgque layer model is an extension to the TCP/IP layer model.
protocoll_mq.h
→ this is the "syntax" of the protocol. This layer provide the MqContextC-ServiceApi ontop of the Application Layer.
The master-slave-link is used to create a mesh of nodes defined by different parent-context. The master control the slave.
The master-slave-link is used to perform the following tasks:
In difference to the client-server-link the master-slave-link connect two independent parent-context in the same process or thread (e.g. node). This leads to the restriction that only the master-context can be a server-context because only one server-context per node is possible.
node-0 | node-1/2 | node-3/4/5 =================================================================== | <- client/server link -> | <- client/server link -> | | <-- master/slave link --> | |- client1-0 -|- server3 ... |- server1 -| | |- client1-1 -|- server4 ... client0-0 -| |- server2 -|- client1-2 -|- server5 ...
Definition of the "master-context"
Definition of the "slave-context"
0
.Definition of the "worker-context"
0
./etc/services
0
slave-id | value | definition |
---|---|---|
MQ_SLAVE_MAX | 1024 | internal: the maximum slave-id … . |
MQ_SLAVE_USER | 10 | internal: start of user-defined-slave-id . |
MQ_SLAVE_LOOPBACK | 0 | internal: the loopback-slave-id, (call my own services) . |
MQ_SLAVE_FILTER | 1 | internal: the filter-slave-id, (on a master get the filter-slave) . |
MQ_SLAVE_MASTER | 1 | internal: the master-slave-id, (on a slave get the master) . |
MQ_SLAVE_OTHER | 1 | internal: on the master-ctx get the slave-ctx and on the slave-ctx get the master-ctx . |
range | definition |
---|---|
0 <= slave-id < MQ_SLAVE_MAX | range of valid slave-id's |
0 <= slave-id < MQ_SLAVE_USER | internale usage |
MQ_SLAVE_USER <= slave-id < MQ_SLAVE_MAX | external usage |
Definition of the "LOOPBACK" (0) slave
client | server | =========================================== | <--- client/server ---> | <-- loop --> | | <------ master/slave -----> | client -- | -- server -- | -- client -- # == == # server -- | -- client -- #
slave-id = 0
. MyLoopServer.c
→ create a new loop-server #include "common.h" // [MyLoopServerC_Define] typedef struct MyLoopServerS { struct MqContextS mqctx; ///< link to the \libmqmsgque object #define mydata_size 30 char mydata[mydata_size]; ///< define the "mydata" attribute } MyLoopServerC; // [MyLoopServerC_Define] // the MyLoopServerC class-type static MkThreadLocal MK_TYP MyLoopServerCTT = NULL; // service to serve all EXTERNAL requests for token "HLWO" static enum MkErrorE HLWO_srv ( MQ_SERVICE_CALL_ARGS ) { // get the "loopback" context MQ_CTX loop = MqSlaveGet_e(mqctx,MQ_SLAVE_LOOPBACK); // call the LOOP service on the SAME server MqSend_E(loop,"W","LOOP"); // answer HLWO with string-return from LOOP MqSend_E(mqctx, "R", "C", MqReadSTR_e(loop)); return MK_OK; error: return MqSendRETURN(mqctx); } // service to serve all INTERNAL requests for token "LOOP static enum MkErrorE LOOP_srv ( MQ_SERVICE_CALL_ARGS ) { // get the "master" context MyLoopServerC* master = (MyLoopServerC*)MqSlaveGetMaster(mqctx); // answer LOOP with data from MASTER->mydata attribute return MqSend(mqctx, "R", "C", master->mydata); } // define a service as link between the token "HLWO" and the callback "HLWO_srv" static enum MkErrorE ServerSetup ( MQ_SERVICE_CALL_ARGS ) { // EXTERNAL: link the "HLWO" service with "HLWO_srv" MqServiceCreate_E(mqctx, "HLWO", HLWO_srv, NULL, NULL, NULL); // INTERNAL: link the "LOOP" service with "LOOP_srv" MqServiceCreate_E(MqSlaveGet_e(mqctx,MQ_SLAVE_LOOPBACK), "LOOP", LOOP_srv, NULL, NULL, NULL); return MK_OK; error: return MkErrorStack_1X(mqctx); } // [MyLoopServerC_Create] enum MkErrorE MyLoopServerFactory ( MQ_CALLBACK_FACTORY_CTOR_ARGS ) { // create new instance using the MyLoopServerCTT class-type MQ_CTX const mqctx = *contextP = MqContextCreate(MyLoopServerCTT,tmpl); // initialize the new context MqConfigSetServerSetup (mqctx, ServerSetup, NULL, NULL, NULL); // cast the libmqmsgque-context into the MyLoopServerC-context MyLoopServerC* mqctxC = (MyLoopServerC*)mqctx; // initialize the "mydata" attribute strncpy(mqctxC->mydata,"Hello World",mydata_size); mqctxC->mydata[mydata_size-1] = '\0'; return MK_OK; } // [MyLoopServerC_Create] int main (int argc, MK_STRN argv[]) { MqRtSetup_NULL; // [MyLoopServerC_Init] // initialize the MyLoopServer class-type with existing MqContextC_TT class-type MyLoopServerCTT = MkTypeDup2(MqContextC_TT,"MyLoopServerC"); MyLoopServerCTT->objsize = sizeof(struct MyLoopServerS); // [MyLoopServerC_Init] // setup commandline arguments for later use MK_BFL largv = MkBufferListCreateVC(argc, argv); MQ_CTX mqctx = NULL; // create "MyLoopServer" factory… and make it to the default. MqFactoryDefault(MqFactoryAdd_2(MyLoopServerFactory,"MyLoopServer")); // inspect commandline-argument for the "factory" to choose… and create a object MqFactoryNew_E (MqFactoryGetCalledL(largv), NULL, &mqctx); // start listen for incoming call's MqLinkCreate_E (mqctx, largv); MqCheckForLeftOverArguments_E (mqctx, largv); MqProcessEvent_E (mqctx,MQ_WAIT_FOREVER,MK_TIMEOUT_DEFAULT); error: MkBufferListDelete(largv); MqExit_1(mqctx); }
Performance analyse
Nhi1Exec perfclient.c --parent --wrk ? @ perfserver.c
Nhi1Exec -r=uds perfserver.c --spawn|fork|thread
Nhi1Exec -r=uds perfclient.c --parent --wrk ?
perfclient worker perfserver ========== ====== ========== | |- loop --wrk x |- MqSlaveWorker(...) -> worker[1] |- MqSend(worker[1],"E","STR0..") -> PerfWorker_I160(...) |- loop endless |- MqContextCreate(...) |- MqLinkCreate(...) <-> MqContextCreate(...) |- MqContextDelete(...) <-> MqContextDelete(...) |- sleep x sec |- loop --wrk x |- MqSend(worker[1],"C"..,"END0") -> PerfWorker_END0(...) | |- stop loop |- "callback" - add number to all <- |- return #context
setup | –wrk | # worker-context | performance | info |
---|---|---|---|---|
pipe | 1 | 2500 | 1000 | the pipe start a new worker-context with spawn |
spawn | 1 | 2500 | <1000 | same as pipe but use network-protocoll |
fork | 1 | 3800 | 4000 | the fork is faster than spawn |
thread | 1 | 16500 | 9000 | the thread is faster than fork |
pipe | 4 | 8000 | 4500 | the worker scale linear up to number of processors |
spawn | 4 | 7600 | <4500 | - |
fork | 4 | 23200 | 11500 | - |
thread | 4 | 55500 | 27500 | - |
pipe | 8 | 10000 | 5500 | the additional scaling up to the max hyper-threading does not really help |
spawn | 8 | 9100 | <5500 | - |
fork | 8 | 23200 | 11500 | - |
thread | 8 | 55500 | 27500 | - |
A client-server connection is defined with the route-connection-string as a composition of "identifier" and is build like a UNIX directory tree with the initial client as root.
Example: GUI/Data Frontend
With --ident-from prefix|factory the identifier is defined as prefix-identifier or factory-identifer.
A route-connection-string is the path between TWO locations in the tree using the UNIX syntax:
short | syntax | direction |
---|---|---|
dot | . | current-context |
double-dot | .. | previous-context |
slash | / | root-context (the client) |
"string" | xxx | next-context with name xxx |
path between "DB" and "header"
relative: ctx.RouteCreate("../GUI/header",service)
absolute: ctx.RouteCreate("/frontend/GUI/header",service)
path between "footer" and "DB"
relative: ctx.RouteCreate("../../DB",service)
absolute: ctx.RouteCreate("/frontend/DB",service)
path between "frontend" and "footer"
relative: ctx.RouteCreate("GUI/footer",service)
absolute: ctx.RouteCreate("/frontend/GUI/footer",service)
The LibMqMsgque-Service-Layer-Routing create proxy-services (MqServiceProxyRoundRobin ...) between frontend and footer. (example c++)
The MqRouteCreate will take the following action:
Attention:
overwrite=true
to guarantee that a route is available....
#define MQ_ROUTE_CTX_MAX 50 |
maximum number of context-items in the return-array from MqRouteResolve …
The maximum size of the return-array is MQ_ROUTE_CTX_MAX+1
because there is always an additional MK_NULL
item at the end.
Definition at line 5548 of file LibMqMsgque_mq.h.
#define MqRouteCreate | ( | ... | ) |
Definition at line 509 of file msgque_overload_mq.h.
#define MqRouteCreate_3 | ( | ctx, | |
route, | |||
service ) |
Definition at line 510 of file msgque_overload_mq.h.
#define MqRouteCreate_C | ( | ... | ) |
Definition at line 512 of file msgque_overload_mq.h.
#define MqRouteCreate_E | ( | ... | ) |
Definition at line 511 of file msgque_overload_mq.h.
#define MqRouteCreate_NULL | ( | ... | ) |
Definition at line 508 of file msgque_overload_mq.h.
#define MqRouteDelete | ( | ... | ) |
Definition at line 514 of file msgque_overload_mq.h.
#define MqRouteDelete_3 | ( | ctx, | |
route, | |||
service ) |
Definition at line 515 of file msgque_overload_mq.h.
#define MqRouteDelete_C | ( | ... | ) |
Definition at line 517 of file msgque_overload_mq.h.
#define MqRouteDelete_E | ( | ... | ) |
Definition at line 516 of file msgque_overload_mq.h.
#define MqRouteDelete_NULL | ( | ... | ) |
Definition at line 513 of file msgque_overload_mq.h.
#define MqRouteGetPath | ( | ... | ) |
Definition at line 529 of file msgque_overload_mq.h.
#define MqRouteGetPath_C | ( | ... | ) |
Definition at line 531 of file msgque_overload_mq.h.
#define MqRouteGetPath_E | ( | ... | ) |
Definition at line 530 of file msgque_overload_mq.h.
#define MqRouteGetPath_e | ( | ... | ) |
Definition at line 532 of file msgque_overload_mq.h.
#define MqRouteGetPath_NULL | ( | ... | ) |
Definition at line 528 of file msgque_overload_mq.h.
#define MqRouteGetTree | ( | ... | ) |
Definition at line 502 of file msgque_overload_mq.h.
#define MqRouteGetTree_C | ( | ... | ) |
Definition at line 504 of file msgque_overload_mq.h.
#define MqRouteGetTree_E | ( | ... | ) |
Definition at line 503 of file msgque_overload_mq.h.
#define MqRouteGetTree_e | ( | ... | ) |
Definition at line 505 of file msgque_overload_mq.h.
#define MqRouteGetTree_NULL | ( | ... | ) |
Definition at line 501 of file msgque_overload_mq.h.
#define MqRouteResolve | ( | ... | ) |
Definition at line 519 of file msgque_overload_mq.h.
#define MqRouteResolve_2 | ( | ctx, | |
ident ) |
Definition at line 520 of file msgque_overload_mq.h.
#define MqRouteResolve_NULL | ( | ... | ) |
Definition at line 518 of file msgque_overload_mq.h.
#define MqRouteTraverse | ( | ... | ) |
Definition at line 522 of file msgque_overload_mq.h.
#define MqRouteTraverse_2 | ( | ctx, | |
service ) |
Definition at line 523 of file msgque_overload_mq.h.
#define MqRouteTraverse_C | ( | ... | ) |
Definition at line 525 of file msgque_overload_mq.h.
#define MqRouteTraverse_E | ( | ... | ) |
Definition at line 524 of file msgque_overload_mq.h.
#define MqRouteTraverse_NULL | ( | ... | ) |
Definition at line 521 of file msgque_overload_mq.h.
MQ_EXTERN enum MkErrorE MqRouteCreate_RT | ( | MK_RT const | mkrt, |
MQ_CTX | ctx, | ||
MK_STRN | route, | ||
MK_STRN | service, | ||
bool | overwrite ) |
create/delete a routing-link between context an a service using route
[in] | mkrt | the MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only) |
[in] | ctx | the MqContextS instance to work on |
[in] | route | the absolute or relative path to the target-context, if NULL or '\0' the current context is returned. |
[in] | service | the service token on the target context |
[in] | overwrite | if overwrite=false an error is raised if the service already exists. |
MQ_EXTERN enum MkErrorE MqRouteDelete_RT | ( | MK_RT const | mkrt, |
MQ_CTX | ctx, | ||
MK_STRN | route, | ||
MK_STRN | service, | ||
bool | overwrite ) |
delete a routing-link created with MqRouteCreate
[in] | mkrt | the MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only) |
[in] | ctx | the MqContextS instance to work on |
[in] | route | the absolute or relative path to the target-context, if NULL or '\0' the current context is returned. |
[in] | service | the service token on the target context |
[in] | overwrite | if overwrite=false an error is raised if the service already exists. |
MQ_EXTERN enum MkErrorE MqRouteGetPath_RT | ( | MK_RT const | mkrt, |
MQ_CTX const | ctx, | ||
MK_STRN * | path_out ) |
return the absolut route-connection-string up to the current ctx …
The absolut route-connection-string is the route starting at root (e.g. "/").
[in] | mkrt | the MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only) |
[in] | ctx | the MqContextS instance to work on |
[out] | path_out | the return path or MK_NULL on error |
MQ_EXTERN enum MkErrorE MqRouteGetTree_RT | ( | MK_RT const | mkrt, |
MQ_CTX const | ctx, | ||
MK_BFL * | treeP_out ) |
create an overview about all available routing-target and services …
The data returned is a list of "ROUTE|IDENT|SERVICE,..."
string items.
ROUTE
is the route-connection-string used in (runtime) enum MkErrorE MqRouteCreate(MQ_CTX ctx, MK_STRN route, MK_STRN service, MK_BOOL overwrite)
. IDENT
is the MqClassIdentGet and usually the final part of the route-connection-string. SERVICE
is the list of services available at IDENT
.Example from MyWorker.c
→ get the "Tree" as service
void TREE () { Send("R", "L", RouteGetTree()); }
Example from tests/route2.test -> route2-1-0
/cl-0/sv-0/svWO2-11/svWO3-11|svWO3-11-0-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-11/svWO3-11|svWO3-11-1-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-11/svWO3-11|svWO3-11-2-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-11/svWO3-12|svWO3-12-0-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-11/svWO3-12|svWO3-12-1-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-11/svWO3-12|svWO3-12-2-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-11|svWO2-11-0-2|FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-11|svWO2-11-1-2|FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-11|svWO2-11-2-2|FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-12/svWO3-11|svWO3-11-0-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-12/svWO3-11|svWO3-11-1-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-12/svWO3-11|svWO3-11-2-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-12/svWO3-12|svWO3-12-0-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-12/svWO3-12|svWO3-12-1-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-12/svWO3-12|svWO3-12-2-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-12|svWO2-12-0-2|FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-12|svWO2-12-1-2|FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-12|svWO2-12-2-2|FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0|sv-0-0-2|FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0|sv-0-1-2|FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0|sv-0-2-2|FOID,HLWO,HLWS,PATH,TREE /cl-0|cl-0-0-2|HLWO,HLWS /cl-0|cl-0-1-2|HLWO,HLWS /cl-0|cl-0-2-2|HLWO,HLWS /cl-0/sv-0/svWO2-11/svWO3-11|svWO3-11-0-2|FINL,FOID,HLWO,HLWS,PATH,TREE /cl-0/sv-0/svWO2-11/svWO3-11|svWO3-11-1-2|FINL,FOID,HLWO,HLWS,PATH,TREE
The following information is available:
cl-0
cl-0
, are reachable: cl-0-
.... sv
... [in] | mkrt | the MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only) |
[in] | ctx | the MqContextS instance to work on |
[out] | treeP_out | the tree-object with the results… |
MQ_EXTERN MQ_CTX_A MqRouteResolve_RT | ( | MK_RT const | mkrt, |
MQ_CTX const | ctx, | ||
MK_STRN const | ident, | ||
MK_NUM const | retnum ) |
return a list of all context belonging to ident …
This api-proc is used to return all context with MqLinkS::targetIdent == ident
.
In addition the following special ident are recognized:
MK_NULL
or DOT=. or ClassIdentGet -> The loopback-slave Example from server.c
→ in a service call return all connected targets
MK_STRN rmtIdent = MqReadSTR_e (mqctx); for (MQ_CTX* ret=MqRouteResolve(mqctx,rmtIdent,-1).data; *ret != NULL; ret++) { MqSendSTR_E (mqctx, MqLinkGetTargetIdent(*ret)); }
MK_NULL
for a non-error result.MK_NULL
.[in] | mkrt | the MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only) |
[in] | ctx | the MqContextS instance to work on |
[in] | ident | The identifer to search the context for |
[in] | retnum | The maximum number-of-items accepted in the result-array, if <0 than MQ_ROUTE_CTX_MAX is used. |
MK_NULL
. MQ_EXTERN enum MkErrorE MqRouteTraverse_RT | ( | MK_RT const | mkrt, |
MQ_CTX | ctx, | ||
MK_STRN | service, | ||
MK_BAC | args ) |
traverse a tree down and call service if available.
The MqRouteTraverse is intended to call a service on all-routes "*"
starting from ctx.
This is a tool to be used to do maintenance work, sometimes a service is changed (e.g MqRouteCreate) or an internal status need to be reset.
The following internal tasks are performed ( C notation ) :
"*"
to get all routes starting from the ctx up to MQ_ROUTE_CTX_MAX routes : sRouteTool_CB
set the flag[i]
to 1
to signal done.[in] | mkrt | the MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only) |
[in] | ctx | the MqContextS instance to work on |
[in] | service | the service token to be called |
[in] | args | command-line-arguments passed as arguments to the service call |