MqContextC - create and manage a slave context … More...
Functions | |
MQ_EXTERN enum MkErrorE | MqSlaveWorker_RT (MK_RT const mkrt, MQ_CTX const ctx, MQ_SLAVE_ID const id, MK_STRN fct, MK_BAC args) |
create a master/slave link using the image of the ctx object self. … | |
MQ_EXTERN enum MkErrorE | MqSlaveCreate_RT (MK_RT const mkrt, MQ_CTX const ctx, MQ_SLAVE_ID const id, MQ_CTX const slave) |
create a master/slave link between the master-parent-context and the slave-parent-context … | |
MQ_EXTERN enum MkErrorE | MqSlaveDelete_RT (MK_RT const mkrt, MQ_CTX const ctx, MQ_SLAVE_ID const id) |
Delete a slave object from a master/slave link identified by id. … | |
bool | MqSlaveCheck (MQ_CTXN const ctx, MQ_SLAVE_ID const id) |
check if slave-id is valid | |
MQ_EXTERN enum MkErrorE | MqSlaveGet_RT (MK_RT const mkrt, MQ_CTX const ctx, MQ_SLAVE_ID const id, MQ_CTX *ctx_out) |
get the slave-context from a master-context … | |
MQ_EXTERN enum MkErrorE | MqSlaveGetProxy_RT (MK_RT const mkrt, MQ_CTX const ctx, MQ_SLAVE_ID const id, MQ_CTX *ctx_out) |
on slave return the master and on master return the slave identified by id. | |
MQ_EXTERN enum MkErrorE | MqSlaveGetFilter_RT (MK_RT const mkrt, MQ_CTX const ctx, MQ_CTX *ctx_out) |
get the filter-ctx or the master-ctx … | |
MQ_CTX | MqSlaveGetMaster (MQ_CTX const ctx) |
opposite function of MqSlaveGetFilter | |
bool | MqSlaveIs (MQ_CTXN const ctx) |
is the context a slave-context ? … | |
MqContextC - MqContextC_SlaveApi_Slave_C_API - function | |
MQ_EXTERN MQ_CTX | MqSlaveGetMasterP (MQ_CTX const ctx) |
Non-inline replacement for MqSlaveGetMaster … | |
MQ_EXTERN MK_BOOL | MqSlaveCheckP (MQ_CTXN const ctx, MQ_SLAVE_ID const id) |
Non-inline replacement for MqSlaveCheck … | |
MQ_EXTERN MK_BOOL | MqSlaveIsP (MQ_CTXN const ctx) |
Non-inline replacement for MqSlaveIs … | |
MqContextC - MqContextC_SlaveApi_Slave_C_API - overload | |
#define | MqSlaveGet_NULL(...) |
#define | MqSlaveGet(...) |
#define | MqSlaveGet_E(...) |
#define | MqSlaveGet_C(...) |
#define | MqSlaveGet_e(...) |
#define | MqSlaveGetFilter_NULL(...) |
#define | MqSlaveGetFilter(...) |
#define | MqSlaveGetFilter_E(...) |
#define | MqSlaveGetFilter_C(...) |
#define | MqSlaveGetFilter_e(...) |
#define | MqSlaveGetProxy_NULL(...) |
#define | MqSlaveGetProxy(...) |
#define | MqSlaveGetProxy_E(...) |
#define | MqSlaveGetProxy_C(...) |
#define | MqSlaveGetProxy_e(...) |
#define | MqSlaveCreate_NULL(...) |
#define | MqSlaveCreate(...) |
#define | MqSlaveCreate_E(...) |
#define | MqSlaveCreate_C(...) |
#define | MqSlaveDelete_NULL(...) |
#define | MqSlaveDelete(...) |
#define | MqSlaveDelete_E(...) |
#define | MqSlaveDelete_C(...) |
#define | MqSlaveWorker_NULL(...) |
#define | MqSlaveWorker(...) |
#define | MqSlaveWorker_3(ctx, id, fct) |
#define | MqSlaveWorker_2(ctx, id) |
#define | MqSlaveWorker_E(...) |
#define | MqSlaveWorker_C(...) |
MqContextC - create and manage a slave context …
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 | - |
#define MqSlaveCreate | ( | ... | ) |
Definition at line 771 of file msgque_overload_mq.h.
#define MqSlaveCreate_C | ( | ... | ) |
Definition at line 773 of file msgque_overload_mq.h.
#define MqSlaveCreate_E | ( | ... | ) |
Definition at line 772 of file msgque_overload_mq.h.
#define MqSlaveCreate_NULL | ( | ... | ) |
Definition at line 770 of file msgque_overload_mq.h.
#define MqSlaveDelete | ( | ... | ) |
Definition at line 775 of file msgque_overload_mq.h.
#define MqSlaveDelete_C | ( | ... | ) |
Definition at line 777 of file msgque_overload_mq.h.
#define MqSlaveDelete_E | ( | ... | ) |
Definition at line 776 of file msgque_overload_mq.h.
#define MqSlaveDelete_NULL | ( | ... | ) |
Definition at line 774 of file msgque_overload_mq.h.
#define MqSlaveGet | ( | ... | ) |
Definition at line 754 of file msgque_overload_mq.h.
#define MqSlaveGet_C | ( | ... | ) |
Definition at line 756 of file msgque_overload_mq.h.
#define MqSlaveGet_E | ( | ... | ) |
Definition at line 755 of file msgque_overload_mq.h.
#define MqSlaveGet_e | ( | ... | ) |
Definition at line 757 of file msgque_overload_mq.h.
#define MqSlaveGet_NULL | ( | ... | ) |
Definition at line 753 of file msgque_overload_mq.h.
#define MqSlaveGetFilter | ( | ... | ) |
Definition at line 759 of file msgque_overload_mq.h.
#define MqSlaveGetFilter_C | ( | ... | ) |
Definition at line 761 of file msgque_overload_mq.h.
#define MqSlaveGetFilter_E | ( | ... | ) |
Definition at line 760 of file msgque_overload_mq.h.
#define MqSlaveGetFilter_e | ( | ... | ) |
Definition at line 762 of file msgque_overload_mq.h.
#define MqSlaveGetFilter_NULL | ( | ... | ) |
Definition at line 758 of file msgque_overload_mq.h.
#define MqSlaveGetProxy | ( | ... | ) |
Definition at line 764 of file msgque_overload_mq.h.
#define MqSlaveGetProxy_C | ( | ... | ) |
Definition at line 766 of file msgque_overload_mq.h.
#define MqSlaveGetProxy_E | ( | ... | ) |
Definition at line 765 of file msgque_overload_mq.h.
#define MqSlaveGetProxy_e | ( | ... | ) |
Definition at line 767 of file msgque_overload_mq.h.
#define MqSlaveGetProxy_NULL | ( | ... | ) |
Definition at line 763 of file msgque_overload_mq.h.
#define MqSlaveWorker | ( | ... | ) |
Definition at line 779 of file msgque_overload_mq.h.
#define MqSlaveWorker_2 | ( | ctx, | |
id ) |
Definition at line 781 of file msgque_overload_mq.h.
#define MqSlaveWorker_3 | ( | ctx, | |
id, | |||
fct ) |
Definition at line 780 of file msgque_overload_mq.h.
#define MqSlaveWorker_C | ( | ... | ) |
Definition at line 783 of file msgque_overload_mq.h.
#define MqSlaveWorker_E | ( | ... | ) |
Definition at line 782 of file msgque_overload_mq.h.
#define MqSlaveWorker_NULL | ( | ... | ) |
Definition at line 778 of file msgque_overload_mq.h.
|
inline |
check if slave-id is valid
[in] | ctx | the master-context as PARENT or CHILD |
[in] | id | the SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal. |
true
= valid or false
= invalid Definition at line 7698 of file LibMqMsgque_mq.h.
MQ_EXTERN MK_BOOL MqSlaveCheckP | ( | MQ_CTXN const | ctx, |
MQ_SLAVE_ID const | id ) |
Non-inline replacement for MqSlaveCheck …
MQ_EXTERN enum MkErrorE MqSlaveCreate_RT | ( | MK_RT const | mkrt, |
MQ_CTX const | ctx, | ||
MQ_SLAVE_ID const | id, | ||
MQ_CTX const | slave ) |
create a master/slave link between the master-parent-context and the slave-parent-context …
The slave-context have to be a sub-class of MqContextC and is owned by the master-context. Owned mean that no other external references should be used.
The slave-context will be deleted if the master-context is deleted and the slave-context will create a child-context if the master-context create a child context.
Example from server.cs
→ with reflection support... only the class is required :
Example from server.cc
→ without reflection support... the factory is required :
and the factory is used to create the object :
[in] | mkrt | the MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only) |
[in] | ctx | the master context object as PARENT without a CHILD |
[in] | id | the SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal. |
[in] | slave | the slave context object as CLIENT-PARENT without a CHILD |
MQ_EXTERN enum MkErrorE MqSlaveDelete_RT | ( | MK_RT const | mkrt, |
MQ_CTX const | ctx, | ||
MQ_SLAVE_ID const | id ) |
Delete a slave object from a master/slave link identified by id. …
By default the slave-context object will be deleted if the master-context is deleted. Use this function to delete the parent-slave-context explicit and brake the master/slave link. If id is invalid nothing will happen. It is an error to delete a child-slave-context.
[in] | mkrt | the MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only) |
[in] | ctx | the master context object as PARENT without a CHILD |
[in] | id | the SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal. |
MQ_EXTERN enum MkErrorE MqSlaveGet_RT | ( | MK_RT const | mkrt, |
MQ_CTX const | ctx, | ||
MQ_SLAVE_ID const | id, | ||
MQ_CTX * | ctx_out ) |
get the slave-context from a master-context …
[in] | mkrt | the MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only) |
[in] | ctx | the master-context as PARENT or CHILD |
[in] | id | the SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal. |
[out] | ctx_out | the slave-context or MK_NULL on error |
MQ_EXTERN enum MkErrorE MqSlaveGetFilter_RT | ( | MK_RT const | mkrt, |
MQ_CTX const | ctx, | ||
MQ_CTX * | ctx_out ) |
get the filter-ctx or the master-ctx …
The functions MqSlaveGetFilter, MqSlaveGetMaster and MqSlaveGetProxy have the same purpose. A filter-pipeline has two ctx, one on the left and one on the right. The left-ctx is linked with the master-ctx and the right-ctx is linked to the slave-ctx. This function return the ctx wanted or an error if NOT available. The search is done using the following order:
[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] | ctx_out | the ctx or MK_NULL on error |
opposite function of MqSlaveGetFilter
MK_NULL
is returned Definition at line 7761 of file LibMqMsgque_mq.h.
Non-inline replacement for MqSlaveGetMaster …
MQ_EXTERN enum MkErrorE MqSlaveGetProxy_RT | ( | MK_RT const | mkrt, |
MQ_CTX const | ctx, | ||
MQ_SLAVE_ID const | id, | ||
MQ_CTX * | ctx_out ) |
on slave return the master and on master return the slave identified by id.
[in] | mkrt | the MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only) |
[in] | ctx | the master or slave-context as PARENT or CHILD |
[in] | id | the SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal. |
[out] | ctx_out | the other-context or MK_NULL on error |
|
inline |
is the context a slave-context ? …
[in] | ctx | the MqContextS instance to work on |
MK_YES
or MK_NO
Definition at line 7770 of file LibMqMsgque_mq.h.
MQ_EXTERN enum MkErrorE MqSlaveWorker_RT | ( | MK_RT const | mkrt, |
MQ_CTX const | ctx, | ||
MQ_SLAVE_ID const | id, | ||
MK_STRN | fct, | ||
MK_BAC | args ) |
create a master/slave link using the image of the ctx object self. …
The slave-context is started as an independent process or thread based on the StartAs argument.
The start of a "worker" can be done at:
Example from server.c
→ create a worker in a service-callback reading arguments from the service
[in] | mkrt | the MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only) |
[in] | ctx | the master context object as PARENT without a CHILD |
[in] | id | the SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal. |
[in] | fct | the MqFactoryS::originalIdent or MK_NULL or '\0' or "WORKER" . if ident is MK_NULL or '\0' or WORKER the factory of ctx will be used if ident is MqFactoryS::originalIdent the factory defined will be used |
[in] | args | command-line arguments passed to the worker-client or the worker-server. all arguments prior the first @ token are added to the worker-client and the other arguments to the worker-server. example: --debug 5 --name hello @ --name myserver |