Loading...
Searching...
No Matches
tclmqmsgque

A library to connect things, run a server and integrate an application.

SYNOPSIS

The tclmqmsgque package is the implementation of the Programming-Language-Micro-Kernel (PLMK) into the target-language Tcl.

  • package require tclmsgque::MqMsgque

The tclmqmsgque package is a composition of multiple classes defining the Programming-Language-Micro-Kernel (PLMK) :

object description
tclmsgque::MqMsgque the namespace with all tclmqmsgque specific definitions
tclmsgque::MqMsgque Attribute the interface to access the package specific attribute
tclmsgque::MqMsgque::MqClassC Attribute the interface to access the class specific attribute
$Instance Attribute the interface to access the instance specific attribute

To access all features without tclmsgque::MqMsgque prefix use:

  • namespace import tclmsgque::MqMsgque::*

Using the tclmqmsgque package ...

TCL package libraries

libtclmqmsgque.so A shared library or shared object is a computer file that contains executable code designed to be used by multiple computer programs or other libraries at runtime.
libtclmqmsgque.la A .la file is a text file used by the GNU libtools package to describe the files that make up the corresponding library.

> man n env

To access the tclmqmsgque package the environment variable TCLLIBPATH have to include the directory.
TCLLIBPATH
      If set, then it must contain a valid Tcl list giving directories to search during auto-load operations.
      Directories must be specified in Tcl format, using “/” as the path separator, regardless of platform.  
      This variable is only used when initializing the auto_path variable.

> man n pkg_create

::pkg::create is a utility procedure that is part of the standard Tcl library.
It is used to create an appropriate `package ifneeded` command for a given package specification.
It can be used to construct a `pkgIndex.tcl` file for use with the package mechanism.

> The syntax of the pkgIndex.tcl file is simple

package ifneeded tclmsgque::MqMsgque 9.0 [list load [file join $dir libtclmqmsgque.so]]

TABLE OF CONTENTS

BASICS
Index , Philosophy , ConfigFile
CLASS
MqMsgque PACKAGE , MqContextC , MqDumpC , MqFactoryC
CONTEXT
Class, Config, Link, Service, Send, Read, Route, Proxy, Slave, Storage, High, CallEnv, Error, Log
MISC
InstStor, Filter, Examples

INTRODUCTION

C-API: MQ_C_API - theLink - a API to link multiple package-items together to act as one application …

PHILOSOPHY

The theLink project is an infrastructure that allows multiple package-items to be linked together to act as one application.
To link, you need to distribute the work from one package-item to another package-item and wait for an answer or not.

Philosophy
Write Once → Run Everywhere

The package-item can be a thread, a separate local process that is started by fork or spawn, or even a network of multiple services on multiple hosts.

The package-item can be written in any language that is supported by the Programming-Language-Micro-Kernel (PLMK) support.
It even supports running multiple programming languages in a single piece of software.
Supported Languages are: (C,C++,C#,VB.NET,Java,Python,Ruby,Perl,PHP,Tcl or GO)

Strategy
It takes 4 years to write a programming-language, but it only takes 4 weeks to insert a micro-kernel.

The package-item is connected to one another via a pipe or a socket and is based on packages which are sent from one package-item to another package-item and back.

Conclusion
theLink is used to manage a network of multiple package-items using an API that is available in all major programming-languages.

PROGRAMMING

theLink is responsible for:

  • establishing and managing the package-items, local or remote
  • establishing and managing the connections between package-items
  • establishing and managing the routing between package-items
  • sending and receiving the package data, calling up a service
  • reading and writing data from or into a data-package
  • setup and maintain event-handling and scheduling
  • interception, distribution and processing of error messages

The LibMsgque library is separted into three programming-layers:

  1. The foundation-layer, used by theLink library programmer
  2. The kernel-layer, used by the Programming-Language-Micro-Kernel programmer
  3. The implementation-layer, used by the target-language programmer
foundation-layer
The foundation-layer implement the libmqmsgque library and is also responsible for the quality-target of the entire project.
  • establishing and managing the package-items
  • establishing and managing the connections
  • memory-management and garbage-collection
  • error-handling
  • logging and debugging
  • written in plain C
kernel-layer
The kernel-layer implement the Programming-Language-Micro-Kernel and is also responsible to generate and maintain the target-language-API source-code.
  • implementation of the managed-object technology
  • implementation of the token-stream-compiler technology
  • written in plain C, TCL and the target-language-API
implementation-layer
The implementation-layer is the API used by the target-language-programmer.
Target
!! This documentation describe the implementation-layer and target the Tcl programmer. !!

CONFIG FILE

C-API: MqConfigS::cfg - add libconfig configuration file …

introduction

A config-file is used to add configuration-values to a libmqmsgque-application using a structured text-file.

supported
By default command-line-options; filter-pipline and slave-worker-setup is supported.

A service-callback and "programming" is not supported. To "programm and modify" something use a scripting language like tcl or python.

goal
The goal is to give the user of a compiled application the ability to provide a single place for common-configuration-values.

technology

libconfig is used to parse a config-file using the application … --config fileName … option.

syntax
The config-file syntax is defined at: http://hyperrealm.github.io/libconfig/libconfig_manual.html

The following restrictions apply to the --config option.

  1. The config-file is parsed when the --config option is parsed
  2. An application is identfied in the config-file by groupname : { ... } ( ":" or "=" is allowed )
  3. The groupname is the return from MqClassIdentGet using hint from --ident-from prefix|factory
  4. The groupname is modified with the --name string, --prefix string or --ident-from prefix|factory naming-options
  5. The order of option-parsing is the order on the command-line
    MyClient … --XXX … --config YYY … --ZZZ …
    order MyClient : XXX < YYY < ZZZ
  6. For a pipe the config-file from the client is added to the end of the server-options :
    MyClient --AAA … --config BBB --CCC … @ Filter3 --name otto --DDD … @ MyServer --EEE …
    application groupname option-parsing-order
    MyClient MyClient AAA < BBB < CCC
    Filter3 otto DDD < BBB
    MyServer MyServer EEE < BBB
    This is required because the --name or --prefix option from DDD or EEE change the group read from the config-file
  7. attention! on a client or a non-pipe server it is a difference if the naming-option is set before or after the --config option
  8. All options set after the --config option overwrite the options from the config-file
  9. The filter ( groupname : { … filter : [ … ] } ) config-file-option define the server to start in a pipe and have to be an array of strings starting with the application-executable OR the factory-identifer

examples

1. Example from MyClient.config filter-pipeline with last server start in debug mode

# commandline OLD: MyClient @ Filter3 @ MyServer --debug 1
# commandline NEW: MyClient --config MyClient.config
version = "1.0" ; // string : version of the configuration file reader
default = "MyClient" ; // string : if the 'class' is unknown use 'default'
MyClient:
{
config:
{
# name = "myName" ; // string : displayname name of the 'context' (default: executable basename)
# identFrom = "prefix" ; // list : select how to identify the application from remote: 'prefix' or 'factory' (default: prefix)
# prefix = "" ; // string : set the 1'part of the visible displayname (default: "" = FactoryName)
# postfix = "" ; // string : set the 2'part of the visible displayname (default: "" = ConnectionName)
# string = false ; // bool : (default: no)
# startAs = "default" ; // string : from list (ref… MqStartE): default, spawn, thread, fork (default: default)
# daemon = "MyServer.pid" ; // string : file for PID
# timeout = 90 ; // int : user defined timeout to terminate a blocking function call (default: 90 sec)
# storage = "#memdb#" ; // string : storage file for the database: #memdb#, #tmpdb# or filename (default: #memdb#)
# runtime = { // struct (ref… MkRuntimeS) : runtime configuration (global)
# debug = 1 ; // int : set the debug-level, Valid values are 0 <= debug <= 9 using 0 for "no" and 9 for "max". (default: 0)
# silent = false ; // bool : write (no) or don't write (yes) any message to stdout or stderr (default: no)
# logfile = "stderr" ; // string : append to logfile, valid values are: stderr, stdout or a filename (default: stderr)
# };
# io = { // struct (ref… MqIoComE) : what kind of socket interface to use? (default: pipe)
# buffersize = 4096 // int : io buffersize (default: 4096)
# pkgsize = 10240 // int : io pkgsize (default: 10 * 1024)
# pipe = true; // struct (ref… MqIoPipeConfigS) → ONLY client (default: true)
# init = false; // struct (ref… MqIoInitConfigS) → ONLY server (default: false)
# tcp = { // struct (ref… MqIoTcpConfigS)
# port = "7777" ; // string : port number or well known port name
# host = "localhost" ; // string : hostname / interfacename
# myport = "1111" ; // string : client MY port number or well known port name
# myhost = "localhost" ; // string : client MY hostname / interfacename
# };
# uds = { // struct (ref… MqIoUdsConfigS)
# file = "filename" ; // string : name of a uds-socket-file (default: null)
# }
# };
};
# start executable "Filter3" in a "@" pipe and change application-name (groupname) to "otto"
filter = [ "Filter3", "--name", "otto" ] ; // array of string : filter pipeline name of "server"
};
# config section for "Filter3" start in the "pipe"
otto = {
filter = [ "MyServer" ] ;
}
# final "MyServer" set option "debug" to "1"
MyServer = {
config: { runtime: {debug = 1} }
# 'config.runtime.debug = 1' is NOT supported.
}

2. Example from libconfig.test filter-pipeline with last server connect by tcp/ip

# OLD: MyClient @ Filter3 @ --tcp --port $PORT
# NEW: MyClient --config configFile
version: 1.0
default = "MyClient"
MyClient: {
filter: [ "Filter3" ]
}
Filter3: {
filter: [ "--tcp", "--port", "$PORT" ]
}

MqMsgque PACKAGE

MqMsgque SETUP

Cleanup cleanup tclmqmsgque internal memory …
Setup

setup tclmqmsgque internal memory …

MqMsgque ENUM

enum MqWaitOnEventE wait for an event? …
enum MqStatusIsEF Information about how the context was created.
enum MqStartE User preferences on HOWTO start a new entity.
enum MqSlaveE predefined slave-id for well known slaves …
enum MqIdentE

identify the application using prefix (default) or factory

MqMsgque HELP

Help write tclmqmsgque specific user-help to stderr
HelpMsgque

return a page with the usage of all tclmqmsgque specific options

MqMsgque INIT

InitGetArg0 get the process startup-prefix argument
InitResetArg0 Reset the process-startup-prefix argument to an empty list …
InitSetArg0

set the process startup-prefix argument to bfl

MqMsgque MAIN

Main

Main entrypoint - start the application

MqMsgque DETAIL

C-API: MqMsgque_C_API - MqMsgque PACKAGE - the package is the toplevel structure of the tclmqmsgque

The tclmqmsgque package is loaded with:

package require tclmsgque::MqMsgque

and is a composition of one or more package-item and exact one package-main.

The tclmqmsgque package add the following classes into MkObjectC_C_API :

Object C-Short Description
MqContextC MQ_CTX MqContextC - the class known as ctx or context is the application-handle of the application-server and also the main data-handle
MqDumpC MQ_DMP MqDumpC - the class known as dmp or dump is used to export a tclmqmsgque data package as binary
MqFactoryC MQ_FCT MqFactoryC - the class known as fct or factory is used to provide an interface to create one or more new MqContextC

The tclmqmsgque package add the following types into MkObjectC_C_API :

ABSTRACT: MkTypeSTT (TypeTypeType = type of a TypeType)
|
|- ABSTRACT: MqCtxTypeC_TT (TypeType = type of a Type)
|  |
|  |- MqContextC_T
|
|- ABSTRACT: MkSuperTypeSTT (TypeType = type of a Type)
   |
   |- MqFactoryST, MqDumpST

MqMsgque SETUP

C-API: MqMsgque_Setup_C_API - MqMsgque PACKAGE - setup und cleanup the tclmqmsgque

For details about MqSetup and MqCleanup usage refer to MkKernel_Setup_libmkkernel_C_API

(static) MqMsgque Cleanup

top cleanup tclmqmsgque internal memory … → API: tcl_mqmsgque_MqMsgque_Cleanup

MkCleanup can only be called once and will be ignored if not called in the same thread as MqSetup. after a call to MqSetup the call to MkCleanup is possible again.

Attention
during cleanup objects will be deleted too -> the language interpreter have to be active

(static) MqMsgque Setup

top setup tclmqmsgque internal memory … → API: tcl_mqmsgque_MqMsgque_Setup

MqSetup can only be called once, additional call's will be ignored until a MqCleanup is called.

MqMsgque ENUM

C-API: MqMsgque_Enum_C_API - MqMsgque PACKAGE - enum definition …

read more at: MkKernel_Enum_C_API

enum MqIdentE

top identify the application using prefix (default) or factory … → API: tcl_mqmsgque_Get_MqIdentE_FromObj

See also
MqConfigGetIdentFrom, MqConfigSetIdentFrom, MqIdentE_ToString

(static) MqIdentE [MqMsgque IdentE_FromInt value:int32]

top return the MqIdentE from integer … → API: tcl_mqmsgque_MqMsgque_IdentE_FromInt

(static) int32 [MqMsgque IdentE_ToInt value:MqIdentE]

top return the MqIdentE as integer … → API: tcl_mqmsgque_MqMsgque_IdentE_ToInt

(static) string [MqMsgque IdentE_ToString value:MqIdentE]

top return the MqIdentE as string … → API: tcl_mqmsgque_MqMsgque_IdentE_ToString


enum MqSlaveE

top predefined slave-id for well known slaves … → API: tcl_mqmsgque_Get_MqSlaveE_FromObj

__parser__(enum-accept-integer=int32)
enum MqSlaveE {
MQ_SLAVE_MAX = 1024,
};
See also
MqServiceProxy, MqSlaveWorker, MqSlaveCreate, MqSlaveDelete, MqSlaveCheck, MqSlaveGet, MqSlaveGetProxy

(static) MqSlaveE [MqMsgque SlaveE_FromInt value:int32]

top return the MqSlaveE from integer … → API: tcl_mqmsgque_MqMsgque_SlaveE_FromInt

(static) int32 [MqMsgque SlaveE_ToInt value:MqSlaveE]

top return the MqSlaveE as integer … → API: tcl_mqmsgque_MqMsgque_SlaveE_ToInt

(static) string [MqMsgque SlaveE_ToString value:MqSlaveE]

top return the MqSlaveE as string … → API: tcl_mqmsgque_MqMsgque_SlaveE_ToString


enum MqStartE

top User preferences on HOWTO start a new entity. → API: tcl_mqmsgque_Get_MqStartE_FromObj

See also
MqConfigSetStartAs, MqConfigCheckStartAs, MqConfigGetStartAs, MqStartE_ToString

(static) MqStartE [MqMsgque StartE_FromInt value:int32]

top return the MqStartE from integer … → API: tcl_mqmsgque_MqMsgque_StartE_FromInt

(static) int32 [MqMsgque StartE_ToInt value:MqStartE]

top return the MqStartE as integer … → API: tcl_mqmsgque_MqMsgque_StartE_ToInt

(static) string [MqMsgque StartE_ToString value:MqStartE]

top return the MqStartE as string … → API: tcl_mqmsgque_MqMsgque_StartE_ToString


enum MqStatusIsEF

top Information about how the context was created. → API: tcl_mqmsgque_Get_MqStatusIsEF_FromObj

See also
MqConfigGetStatusIs, MqStatusIsEF_ToString

(static) MqStatusIsEF [MqMsgque StatusIsEF_FromInt value:int32]

top return the MqStatusIsEF from integer … → API: tcl_mqmsgque_MqMsgque_StatusIsEF_FromInt

(static) int32 [MqMsgque StatusIsEF_ToInt value:MqStatusIsEF]

top return the MqStatusIsEF as integer … → API: tcl_mqmsgque_MqMsgque_StatusIsEF_ToInt

(static) string [MqMsgque StatusIsEF_ToString value:MqStatusIsEF]

top return the MqStatusIsEF as string … → API: tcl_mqmsgque_MqMsgque_StatusIsEF_ToString


enum MqWaitOnEventE

top wait for an event? … → API: tcl_mqmsgque_Get_MqWaitOnEventE_FromObj

See also
MqProcessEvent

(static) MqWaitOnEventE [MqMsgque WaitOnEventE_FromInt value:int32]

top return the MqWaitOnEventE from integer … → API: tcl_mqmsgque_MqMsgque_WaitOnEventE_FromInt

(static) int32 [MqMsgque WaitOnEventE_ToInt value:MqWaitOnEventE]

top return the MqWaitOnEventE as integer … → API: tcl_mqmsgque_MqMsgque_WaitOnEventE_ToInt

(static) string [MqMsgque WaitOnEventE_ToString value:MqWaitOnEventE]

top return the MqWaitOnEventE as string … → API: tcl_mqmsgque_MqMsgque_WaitOnEventE_ToString

MqMsgque HELP

C-API: MqMsgque_Help_C_API - MqMsgque PACKAGE - access to a qualified help-message

(static) string [MqMsgque Help tool:string]

top write tclmqmsgque specific user-help to stderr → API: tcl_mqmsgque_MqMsgque_Help

Parameters
toolthe name of the tool (e.g. argv[0]) or NULL.
Returns
the help messages as string

If tool != NULL, the function will display a header like:

 tool [ARGUMENT]... syntax:
   aclient [OPTION]... @ tool [OPTION]... @...

on the help page.

(static) string [MqMsgque HelpMsgque]

top return a page with the usage of all tclmqmsgque specific options → API: tcl_mqmsgque_MqMsgque_HelpMsgque

MqMsgque INIT

C-API: MqMsgque_Init_C_API - MqMsgque PACKAGE - initialize the MqContextC startup and/or external-object-link

(static) MkBufferListC [MqMsgque InitGetArg0]

top get the process startup-prefix argument → API: tcl_mqmsgque_MqMsgque_InitGetArg0

Returns
a pointer to the initialization buffer (Only C-API)
Attention
if not set return a "MK_NULL" pointer

(static) MkBufferListC [MqMsgque InitResetArg0]

top Reset the process-startup-prefix argument to an empty list … → API: tcl_mqmsgque_MqMsgque_InitResetArg0

The startup-prefix have to be the name of the executable, found in the PATH environment variable, and additional arguments like the script name or the required startup options. The startup-prefix is used for two different purpose:

  • To start a new entity using the MqStartAs "--spawn" command-line option.
  • To replace the command-line-argument "... @ SELF ..." with "... @ startup-prefix ..." at LinkCreate.

Every use of this function will free the data of the previous startup-prefix. By default the startup-prefix is set during application startup by tclmqmsgque and have not to be initialized again.

Example from server.tcl initialize the startup-prefix with the data read from service-args

  method Ot_INIT {} {
    my SendSTART
    tclmsgque::MqMsgque InitSetArg0 [my ReadALL]
    my SendRETURN
  }
See also
MqInitSetArg0 MqInitGetArg0

(static) MqMsgque InitSetArg0 ?bfl:MkBufferListC...="MK_NULL"?

top set the process startup-prefix argument to bfl → API: tcl_mqmsgque_MqMsgque_InitSetArg0

The startup-prefix is the argument(s) required to start the application… this is minimal the binary-path for binaries (same as as used on command-line) or the interpreter+scriptFile for scripts.

Parameters
[in]bflthe object will be merged into the startup-prefix, afterwords the bfl is empty and can be deleted
Example
Initialize the application startup command in C
MqInitSetArg0(MkBufferListCreateV("myExec", "myExecArgument_1"));
MQ_EXTERN void MqInitSetArg0(MK_BAC bfl)
set the process startup-prefix argument to bfl

MqMsgque MAIN

C-API: MqMsgque_Main_C_API - MqMsgque PACKAGE - the package-main is a single piece of code evaluated only once at application startup …

Example from MyServer.tcl The package-main configure the factory and start the server.

package require tclmsgque::MqMsgque
namespace import tclmsgque::MqMsgque::*
namespace import tclmsgque::MkKernel::*

# package-item
::oo::class create MyServer {
  superclass MqContextC

  # service to serve all incoming requests for token "HLWO"
  method myFirstService {} {
    my SendSTART
    my SendSTR "[my ReadSTR] World"
    my SendRETURN
  }

  # define a service as link between the token "HLWO" and the callback "MyFirstService"
  method serverSetup {} {
    my ServiceCreate "HLWO" myFirstService
  }

  # factory startup (constructor)
  constructor {{tmpl ""}} {
    next $tmpl
    my ConfigSetServerSetup serverSetup
  }
} 

# package-main
tclmsgque::MqMsgque Main {

  # setup commandline arguments for later use
  set args  [MkBufferListC CreateLA {*}$argv]

  # create "MyServer" factory... and make it to the default.
  set fct   [[MqFactoryC Add MyServer] Default]

  # inspect commandline-argument for the "factory" to choose... and create a object
  set fct   [MqFactoryC GetCalledL $args]
  set srv   [$fct New]

  try {
    $srv LinkCreate $args
    $srv ProcessEvent MQ_WAIT_FOREVER
  } on error {} {
    $srv ErrorCatch
  } finally {
    $srv Exit
  }
}

(static) MqMsgque Main code:...

top Main entrypoint - start the application → API: MqMain

Tcl has a special requirement, for every new server-thread a new interpreter is created and
this interpreter source the toplevel file for initialization. This file is set on library startup and
can be changed with MqInitResetArg0. The problem is the server startup code from the toplevel. For internal
purpose this code should only be executed on application-startup (like the C main function)
and not for every thread again.


MqContextC

SUPER: MkObjectC, top
MqContextC CLASS

Export MqContextC - Export class functions …
Introspection MqContextC - Introspection class functions …
Misc

MqContextC - Misc class functions …

MqContextC TOR

Create create and initialize the MqContextC ...
new create and initialize the MqContextC ...
Delete

Destructor - delete a MqContextC instance …

MqContextC CLASS API

MqContextC - access data related to the factory-type of the object …

MqContextC CONFIG API

Get MqContextC - various function to 'get' the configuration-data from a context
Interface MqContextC - various function to setup a interface for the context
Misc MqContextC - various function to do 'misc' configuration …
Set

MqContextC - various function to 'set' the configuration-data in a context

MqContextC ENV API

MqContextC - protect and restore the service-environment …

MqContextC ERROR API

MqContextC - move and copy an error from a context

MqContextC HIGH API

MqContextC - User friendly replacement for the MqContextC_SendApi_C_API and the MqContextC_ReadApi_C_API

MqContextC LINK API

MqContextC - setup and manage a client-server-link

MqContextC LOG API

MqContextC - log the output to a string or a MkLogFileC

MqContextC MISC API

MqContextC - various functions to work on a context

MqContextC PROXY API

MqContextC - copy data from the read-data-package of the sourceCtx to the send-data-package of the targetCtx

MqContextC READ API

Atom MqContextC - read a single-data-item outof a read-data-package
Block MqContextC - read a block-of-data outof a read-data-package
Misc

MqContextC - various functions to work on a read-data-package

MqContextC ROUTE API

MqContextC - setup and manage a routing-link

MqContextC SEND API

Atom MqContextC - append a native PRIMITIVE TYPE value to the send-data-package
Basics MqContextC - finish the send-data-block and call synchronous/asynchronous a remote-service
Block MqContextC - a wrapper to send a list-block or a transaction-block
Return

MqContextC - finish the send-data-block on the server and optional return the results. …

MqContextC SERVICE API

MqContextC - create and manage a service …

MqContextC SLAVE API

MqContextC - create and manage a slave context …

MqContextC STORAGE API

MqContextC - setup and manage a storage used to persist data-packages

MqContextC DETAIL

C-API: MqContextC_C_API - MqContextC - the class known as ctx or context is the application-handle of the application-server and also the main data-handle

The context is the package-item with the required features and created by the implementation-layer-programmer. The context can be a client or a server.

HOWTO client-context

The client-context-creation is triggerd by the software-workflow on demand. The client is calling the MqLinkCreate to create a connection to the server using the connection-arguments to specify the target.

The life-cycle of a client is:

ContextCreate create and initialize the MqContextC ...
LinkCreate make ctx to a parent-context and setup a new client-server-link
SendTT MqContextC - append a native PRIMITIVE TYPE value to the send-data-package
ReadTT read a PRIMITIVE TYPE from the read-data-package
LinkDelete close the client-server-link
ContextDelete Destructor - delete a MqContextC instance …
Exit delete the context and exit the current process or thread …

HOWTO server-context

The server-context-creation is always triggerd by the MqLinkCreate command of the client. The server is usually using a factory-constructor to call the MqContextCreate and finally to call the MqContextDelete.
The server-context is fully under control of the client.

The life-cycle of a server is:

SETUPdefine a class and add the setup/cleanup code
IServerSetup define the server-setup-interface (callback) used on startup …
ServiceCreate create a link between a service-token and a service-callback
IServerCleanup define the server-cleanup-interface (callback) used on cleanup …
ServiceDelete delete a service. …
STARTUPdefine the factory and start the listener
FactoryAdd add a new MqFactoryC identified by factory-identifier and defined by factory-constructor
FactoryNew create a new MqContextC from a MqFactoryC
LinkCreate make ctx to a parent-context and setup a new client-server-link
ProcessEvent enter the event-loop and wait for an incoming service-request. …
WORKprocess the service-calls and exit on end
ReadTT read a PRIMITIVE TYPE from the read-data-package
SendTT MqContextC - append a native PRIMITIVE TYPE value to the send-data-package
Exit delete the context and exit the current process or thread …

MqContextC CTOR and DTOR

command alias
(constructor,static) MqContextC [MqContextC Create ?tmpl:MqContextC="MK_NULL"?] tclmsgque::MqContextC new ?tmpl:MqContextC=""?
(destructor) $ctx Delete rename $ctx ""

MqContextC CLASS

NAVI: top, up

MqContextC CLASS EXPORT

HandleResolve Handle-Resolve-Slot - return a MqContextC from netHdl or "MK_NULL" if invalid…
HandleGet

Handle-Get-Slot - returns a export-hdl to the MqContextC useable for external storage

MqContextC CLASS INTROSPECTION

Instances get head-instance from linked-list of MqContextS type …
Next get next instance from linked-list of MqContextS type
Prev

get previous instance from linked-list of MqContextS type

MqContextC CLASS MISC

GetNull

Null-Slot - return a MqContextC typed NULL instance …

MqContextC CLASS DETAILS

C-API: MqContextC_Class_C_API - MqContextC - define the class …

MqContextC CLASS EXPORT

MqContextC - Export class functions …

(static) MqContextC [MqContextC HandleResolve netHdl:MK_HDL]

top Handle-Resolve-Slot - return a MqContextC from netHdl or "MK_NULL" if invalid… → API: tcl_mqmsgque_MqContextC_HandleResolve

The MqContextHandleResolve undo the MqContextHandleGet and is intended to export a unique identifer into external code not belonging to the Programming-Language-Micro-Kernel (PLMK).

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]netHdlhandle former exported with MqContextHandleGet
Returns
the required handle or "MK_NULL" if netHdl is invalid

MK_HDL [$ctx HandleGet]

top Handle-Get-Slot - returns a export-hdl to the MqContextC useable for external storage → API: tcl_mkkernel_MkObjectC_HandleGet

The export-hdl is a reference to an instance that can be stored in software and converted back into an instance using the MqContextHandleResolve.

The export-hdl is only valid until the Programming-Language-Micro-Kernel (PLMK) ends.

example: The export-hdl is used in rpc to identify an object across the network.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Returns
the required export-hdl

MqContextC CLASS INTROSPECTION

MqContextC - Introspection class functions …

(static) MqContextC [MqContextC Instances]

top get head-instance from linked-list of MqContextS type … → API: tcl_mqmsgque_MqContextC_Instances

The head-instance is the last instance created.

MqContextC [$ctx Next]

top get next instance from linked-list of MqContextS type → API: tcl_mqmsgque_MqContextC_Next

MqContextC [$ctx Prev]

top get previous instance from linked-list of MqContextS type → API: tcl_mqmsgque_MqContextC_Prev

MqContextC CLASS MISC

MqContextC - Misc class functions …

(static) MqContextC [MqContextC GetNull]

top Null-Slot - return a MqContextC typed NULL instance … → API: tcl_mqmsgque_MqContextC_GetNull

MqContextC TOR

C-API: MqContextC_TOR_C_API - MqContextC - various functions to create, initialize and destroy a context

(constructor,static) MqContextC [MqContextC Create ?tmpl:MqContextC="MK_NULL"?]

top create and initialize the MqContextC ... → API: tcl_mqmsgque_MqContextC_Create

This function is used to create a single new context… primary on the client. to create multiple new context on a server… a MqFactoryC is used.

The new instance belongs to the caller and may have to be released if necessary. A manual release using ContextDelete is always possible, but the instance can no longer be used afterwards.

Example from MyClient.tcl create a context using the static tclmqmsgque CTOR

package require tclmsgque::MqMsgque

# create a context using the static tclmsgque CTOR method "Create"
set ctx [tclmsgque::MqMsgque::MqContextC Create]
try {
  $ctx ConfigSetName "MyClient"
  $ctx LinkCreate {*}$argv
  $ctx SendSTART
  $ctx SendSTR "Hello"
  $ctx SendEND_AND_WAIT "HLWO" 
  puts [$ctx ReadSTR]
} on error {} {
  $ctx ErrorCatch
} finally {
  # delete the context using the tclmsgque APPLICATION-DTOR method "Exit"
  $ctx Exit
}
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]typetype type of the object like MqContextC_T or a new type created with MkTypeDup2. (default: "MK_NULL", reuse the MkTypeSTT from tmpl or use MqContextC_T if tmpl = "MK_NULL")
[in]tmplan other context-data-structure used as template to initialize the configuration data. This template is used for a child to get the configuration data from the parent. (default: "MK_NULL", create an initial context)
Returns
The newly created MqContextC instance, the instance is owned by the caller
See also
MqContextDelete, MqExit

(constructor,static) MqContextC [MqContextC new ?tmpl:MqContextC="MK_NULL"?]

top create and initialize the MqContextC ... → API: tcl_mqmsgque_MqContextC_new

This function is used to create a single new context… primary on the client. to create multiple new context on a server… a MqFactoryC is used.

The new instance belongs to the caller and may have to be released if necessary. A manual release using ContextDelete is always possible, but the instance can no longer be used afterwards.

Example from MyClient.tcl create a context using the static tclmqmsgque CTOR

package require tclmsgque::MqMsgque

# create a context using the static tclmsgque CTOR method "Create"
set ctx [tclmsgque::MqMsgque::MqContextC Create]
try {
  $ctx ConfigSetName "MyClient"
  $ctx LinkCreate {*}$argv
  $ctx SendSTART
  $ctx SendSTR "Hello"
  $ctx SendEND_AND_WAIT "HLWO" 
  puts [$ctx ReadSTR]
} on error {} {
  $ctx ErrorCatch
} finally {
  # delete the context using the tclmsgque APPLICATION-DTOR method "Exit"
  $ctx Exit
}
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]typetype type of the object like MqContextC_T or a new type created with MkTypeDup2. (default: "MK_NULL", reuse the MkTypeSTT from tmpl or use MqContextC_T if tmpl = "MK_NULL")
[in]tmplan other context-data-structure used as template to initialize the configuration data. This template is used for a child to get the configuration data from the parent. (default: "MK_NULL", create an initial context)
Returns
The newly created MqContextC instance, the instance is owned by the caller
See also
MqContextDelete, MqExit

(destructor) $ctx Delete

top Destructor - delete a MqContextC instance … → API: MqContextDelete_RT

Shutdown the client-server-link, free the memory and set the ctx to "MK_NULL". The context can not be reused.

Example from MyClient2.tcl delete a application-context using the tclmqmsgque DTOR

package require tclmsgque::MqMsgque
# create a context using the default CTOR method "new"
set ctx [tclmsgque::MqMsgque::MqContextC new]
try {
$ctx ConfigSetName "MyClient"
$ctx LinkCreate {*}$argv
$ctx SendSTART
$ctx SendSTR Hello
$ctx SendEND_AND_WAIT "HLWO"
puts [$ctx ReadSTR]
} on error {} {
$ctx ErrorCatch
} finally {
# delete context using the DTOR method "Delete"
$ctx Delete
}
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
See also
MqContextCreate

MqContextC CLASS API

NAVI: top, up
ClassFactoryGet get the MqFactoryC used by the MqContextC
ClassFactorySet link the MqContextC to a new MqFactoryC
ClassIdentGet get the application-identification
ClassIdentSet link the MqContextC to a new MqFactoryC identified by ident
ClassOriginalIdentGet

get the MqFactoryS::originalIdent from the MqContextC

MqContextC CLASS API DETAILS

C-API: MqContextC_ClassApi_C_API - MqContextC - access data related to the factory-type of the object …

The type of an object is related to the MqFactoryC. The factory decide which class a new created object has. The factory has two identifiers:

The relevance of the MqContextC CLASS API based type system, provided by MqFactoryC, decreased with the rise of the MANAGED OBJECT technology.
The MqContextC CLASS API based type system has more influence for target-languages without reflection, like C or C++.
The factory is something like a constructor but only support the application-context MqContextC .
The MqContextC ROUTE API using the MqClassIdentGet from MqFactoryC to identify an application from remote.

MqFactoryC [$ctx ClassFactoryGet]

top get the MqFactoryC used by the MqContextC → API: tcl_mqmsgque_MqContextC_ClassFactoryGet

Parameters
[in]ctxthe MqContextC to extract the MqFactoryC from
Returns
the MqFactoryC

$ctx ClassFactorySet item:MqFactoryC

top link the MqContextC to a new MqFactoryC → API: tcl_mqmsgque_MqContextC_ClassFactorySet

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextC to be linked with the MqFactoryC
[in]itemthe MqFactoryC to link with
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

string [$ctx ClassIdentGet]

top get the application-identification … → API: tcl_mqmsgque_MqContextC_ClassIdentGet

Parameters
[in]ctxthe MqContextC to extract the ident from
Returns
the identifer or an empty string if ident was not set

An application has TWO possible names:

  1. The name from the context the application was configured with.
  2. The name from the factory the application was created with.

The --ident-from prefix|factory value decide which on is used.

The application-identification is defined by MqConfigS::identFrom :

MqFactoryS::originalIdentif ident == MQ_IDENT_FACTORY
MqConfigS::prefixif ident == MQ_IDENT_PREFIX (default)

The MqFactoryS::originalIdent is the official name of the MqFactoryC and is defined by the application-programmer with MqFactoryAdd or MqFactoryDup2.

The MqConfigS::prefix is the official name of the MqContextC that startet first, usually the server-name, and is set by the application-user with --prefix string at startup or with the MqConfigSetPrefix at setup.

When the server starts, the MqClassIdentGet value is send from the server to the client and the client initializes the MqLinkS::targetIdent with this value. This value identifes the server from remote and is used by the MqContextC ROUTE API to select which server receive the routing-package.

The client usually get the factory and the idenfication from the: MqFactoryInitial.

Example: Change the factory-identifier of MqFactoryInitial to the value "TestClient" with:

C# MqFactoryC.Get("initial").Dup2("TestClient").Initial()
TCL [[tclmsgque::MqFactoryC Get "initial"] Dup2 "TestClient"] Initial
Note
After the link-start, the MqLinkS::targetIdent is no longer changed.
Attention
The string is owned by tclmqmsgque -> do not free !!

$ctx ClassIdentSet ident:string

top link the MqContextC to a new MqFactoryC identified by ident → API: tcl_mqmsgque_MqContextC_ClassIdentSet

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextC to set the ident
[in]identthe MqFactoryS::originalIdent to link with
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
this function does not replace the ident of the current factory linked to context… this function replace the entire factory with a new factory identified by name. if the factory is not found or the link is already connected… an error is retured.

string [$ctx ClassOriginalIdentGet]

top get the MqFactoryS::originalIdent from the MqContextC → API: tcl_mqmsgque_MqContextC_ClassOriginalIdentGet

Parameters
[in]ctxthe MqContextC to extract the original-ident from
Returns
the identifer or an empty string if no factory is available
Attention
the string is owned by tclmqmsgque -> do not free !!

MqContextC CONFIG API

NAVI: top, up

MqContextC CONFIG API GET

ConfigGetBuffersize get the minimum of the read/send buffersize of the socket
ConfigGetIdentFrom get the MqConfigS::identFrom
ConfigGetIoPipe return the MqIoPipeConfigS
ConfigGetIoTcp get the configuration-data of the tcp-client-server-link
ConfigGetIoTcpL get the configuration-data of the tcp-client-server-link as MkBufferListC
ConfigGetIoUds return the MqIoUdsConfigS
ConfigGetIsParent does the context object is a parent ? An objext is a parent id the MqConfigS::parent attribute is "MK_NULL"
ConfigGetIsServer does the context object is a server ?
ConfigGetIsString does the context object is using the string-mode ?
ConfigGetName get the name of the context object
ConfigGetPkgsize get the maximun size of a BDY package
ConfigGetPostfix get the MqConfigS::postfix
ConfigGetPrefix get the MqConfigS::prefix
ConfigGetStartAs return the MqConfigS::startAs value
ConfigGetStatusIs return the MqContextS::statusIs value
ConfigGetStorage get the storage of the context object
ConfigGetTimeout get the timeout value of the context object
ConfigSetConfigFile

set the config-file and parse for well-known config-items

MqContextC CONFIG API INTERFACE

ConfigSetBgError set the MqSetupS::BgError
ConfigSetEvent set the MqSetupS::Event
ConfigSetServerCleanup set the MqSetupS::ServerCleanup
ConfigSetServerSetup

set the MqSetupS::ServerSetup

MqContextC CONFIG API MISC

ConfigReset

clean the MqContextS::config data

MqContextC CONFIG API SET

ConfigCheckStartAs check if MqConfigS::startAs can be set to data
ConfigSetAllDebug set the MkRuntimeS::debug value
ConfigSetAllTimeout set the MqIoConfigS::timeout value
ConfigSetBuffersize set the MqIoConfigS::buffersize value
ConfigSetDaemon start the server-context as daemon …
ConfigSetIdentFrom set the MqConfigS::identFrom value
ConfigSetIgnoreExit set the MqSetupS::ignoreExit value
ConfigSetIoPipe set the pipe configuration data …
ConfigSetIoTcp configure a context to use a tcp-client-server-link
ConfigSetIoTcpL configure a context to use a tcp-client-server-link
ConfigSetIoUds configure a context to use a uds-client-server-link
ConfigSetIsServer set the MqSetupS::isServer value
ConfigSetIsString set the MqConfigS::native value 'S'string or 'L'owEndian or 'B'igEndian
ConfigSetName set the MqConfigS::dispname value and cleanup old value
ConfigSetPkgsize set the MqIoConfigS::pkgsize value
ConfigSetPostfix set the client-part (2) of the application-identifer MqConfigS::dispname
ConfigSetPrefix set the server-part (1) of the application-identifer MqConfigS::dispname
ConfigSetStartAs set the MqConfigS::startAs value
ConfigSetStartAsString set the MqConfigS::startAs value using string default, thread, fork or spawn
ConfigSetStorage set the Storage value and cleanup old value
ConfigSetTimeout

set the MqIoConfigS::timeout value

MqContextC CONFIG API DETAILS

C-API: MqContextC_ConfigApi_C_API - MqContextC - various functions to config a context

The configuration is done persistent using config-api functions or on link-setup using command-line-arguments.

Options API
Naming Options
--config fileName, --name string, --prefix string, --postfix string, --ident-from prefix|factory
Startup Options
--tcp --host string --port int --myhost string --myport int, --uds --file fileName, --pipe, --thread --spawn --fork, --daemon pidfile
Runtime Options
--logfile fileName, --silent, --debug
Misc Options
--buffersize int, --pkgsize int, --timeout int, --string
Interface API
interface: $ctx ConfigSetServerSetup ?callback:callable="MK_NULL"?
interface: $ctx ConfigSetServerCleanup ?callback:callable="MK_NULL"?
interface: $ctx ConfigSetBgError ?callback:callable="MK_NULL"?
interface: $ctx ConfigSetEvent ?callback:callable="MK_NULL"?
Function API

CONFIG OPTION DETAILS

CONFIG NAMING OPTIONS DETAILS

--config fileName

set: $ctx ConfigSetConfigFile filename:string

add libconfig configuration file …

introduction

A config-file is used to add configuration-values to a libmqmsgque-application using a structured text-file.

supported
By default command-line-options; filter-pipline and slave-worker-setup is supported.

A service-callback and "programming" is not supported. To "programm and modify" something use a scripting language like tcl or python.

goal
The goal is to give the user of a compiled application the ability to provide a single place for common-configuration-values.

technology

libconfig is used to parse a config-file using the application … --config fileName … option.

syntax
The config-file syntax is defined at: http://hyperrealm.github.io/libconfig/libconfig_manual.html

The following restrictions apply to the --config option.

  1. The config-file is parsed when the --config option is parsed
  2. An application is identfied in the config-file by groupname : { ... } ( ":" or "=" is allowed )
  3. The groupname is the return from MqClassIdentGet using hint from --ident-from prefix|factory
  4. The groupname is modified with the --name string, --prefix string or --ident-from prefix|factory naming-options
  5. The order of option-parsing is the order on the command-line
    MyClient … --XXX … --config YYY … --ZZZ …
    order MyClient : XXX < YYY < ZZZ
  6. For a pipe the config-file from the client is added to the end of the server-options :
    MyClient --AAA … --config BBB --CCC … @ Filter3 --name otto --DDD … @ MyServer --EEE …
    application groupname option-parsing-order
    MyClient MyClient AAA < BBB < CCC
    Filter3 otto DDD < BBB
    MyServer MyServer EEE < BBB
    This is required because the --name or --prefix option from DDD or EEE change the group read from the config-file
  7. attention! on a client or a non-pipe server it is a difference if the naming-option is set before or after the --config option
  8. All options set after the --config option overwrite the options from the config-file
  9. The filter ( groupname : { … filter : [ … ] } ) config-file-option define the server to start in a pipe and have to be an array of strings starting with the application-executable OR the factory-identifer

examples

1. Example from MyClient.config filter-pipeline with last server start in debug mode

# commandline OLD: MyClient @ Filter3 @ MyServer --debug 1
# commandline NEW: MyClient --config MyClient.config
version = "1.0" ; // string : version of the configuration file reader
default = "MyClient" ; // string : if the 'class' is unknown use 'default'
MyClient:
{
config:
{
# name = "myName" ; // string : displayname name of the 'context' (default: executable basename)
# identFrom = "prefix" ; // list : select how to identify the application from remote: 'prefix' or 'factory' (default: prefix)
# prefix = "" ; // string : set the 1'part of the visible displayname (default: "" = FactoryName)
# postfix = "" ; // string : set the 2'part of the visible displayname (default: "" = ConnectionName)
# string = false ; // bool : (default: no)
# startAs = "default" ; // string : from list (ref… MqStartE): default, spawn, thread, fork (default: default)
# daemon = "MyServer.pid" ; // string : file for PID
# timeout = 90 ; // int : user defined timeout to terminate a blocking function call (default: 90 sec)
# storage = "#memdb#" ; // string : storage file for the database: #memdb#, #tmpdb# or filename (default: #memdb#)
# runtime = { // struct (ref… MkRuntimeS) : runtime configuration (global)
# debug = 1 ; // int : set the debug-level, Valid values are 0 <= debug <= 9 using 0 for "no" and 9 for "max". (default: 0)
# silent = false ; // bool : write (no) or don't write (yes) any message to stdout or stderr (default: no)
# logfile = "stderr" ; // string : append to logfile, valid values are: stderr, stdout or a filename (default: stderr)
# };
# io = { // struct (ref… MqIoComE) : what kind of socket interface to use? (default: pipe)
# buffersize = 4096 // int : io buffersize (default: 4096)
# pkgsize = 10240 // int : io pkgsize (default: 10 * 1024)
# pipe = true; // struct (ref… MqIoPipeConfigS) → ONLY client (default: true)
# init = false; // struct (ref… MqIoInitConfigS) → ONLY server (default: false)
# tcp = { // struct (ref… MqIoTcpConfigS)
# port = "7777" ; // string : port number or well known port name
# host = "localhost" ; // string : hostname / interfacename
# myport = "1111" ; // string : client MY port number or well known port name
# myhost = "localhost" ; // string : client MY hostname / interfacename
# };
# uds = { // struct (ref… MqIoUdsConfigS)
# file = "filename" ; // string : name of a uds-socket-file (default: null)
# }
# };
};
# start executable "Filter3" in a "@" pipe and change application-name (groupname) to "otto"
filter = [ "Filter3", "--name", "otto" ] ; // array of string : filter pipeline name of "server"
};
# config section for "Filter3" start in the "pipe"
otto = {
filter = [ "MyServer" ] ;
}
# final "MyServer" set option "debug" to "1"
MyServer = {
config: { runtime: {debug = 1} }
# 'config.runtime.debug = 1' is NOT supported.
}

2. Example from libconfig.test filter-pipeline with last server connect by tcp/ip

# OLD: MyClient @ Filter3 @ --tcp --port $PORT
# NEW: MyClient --config configFile
version: 1.0
default = "MyClient"
MyClient: {
filter: [ "Filter3" ]
}
Filter3: {
filter: [ "--tcp", "--port", "$PORT" ]
}

--name string

attribute: MqConfigS::dispname, getter: MqContextC_ConfigGetName, setter: MqContextC_ConfigSetName
set the display-name of the context

The display-name is used as:

  • A prefix in the local debug/error/log output:
    • C> (dispname) [2009-01-12:16-22-27] [4-0-sIoCheckArg]: option: io->com = PIPE

The dispname is initialized with:

Example
use MqConfigS::prefix and MqConfigS::postfix to set the MqConfigS::dispname :
  • prefix postfix dispname
    client -1-1 client-1-1
Attention

--prefix string

attribute: MqConfigS::prefix, getter: MqContextC_ConfigGetPrefix, setter: MqContextC_ConfigSetPrefix
set the server-part (1) of the application-identifer MqConfigS::dispname

The prefix is used for:

  1. MqConfigS::dispname initialization
  2. application-identifer if --ident-from prefix|factory is set to prefix (default)
  3. groupname in --config fileName is used as application-identifer

The prefix is initialize with:

  1. the basename of the executable if NO factory is used
  2. the MqFactoryS::originalIdent
  3. the $ctx ConfigSetPrefix data:string or the $ctx ConfigSetName data:string function
  4. the --name string OR the --prefix string option
Attention
if the --name string is explicitly set, then --prefix string and --postfix string have no effect

--postfix string

attribute: MqConfigS::postfix, getter: MqContextC_ConfigGetPostfix, setter: MqContextC_ConfigSetPostfix
set the client-part (2) of the application-identifer MqConfigS::dispname

The postfix is used for:

  1. MqConfigS::dispname initialization

The postfix is initialize with:

  1. an empty string
  2. the $ctx ConfigSetPostfix data:string function
  3. the client postfix at server-startup
  4. the --postfix string option
Attention
if the --name string is explicitly set, then --prefix string and --postfix string have no effect

--storage fileName

attribute: MqConfigS::storage, getter: MqContextC_ConfigGetStorage, setter: MqContextC_ConfigSetStorage

--ident-from prefix|factory

attribute: MqConfigS::identFrom, getter: MqContextC_ConfigGetIdentFrom, setter: MqContextC_ConfigSetIdentFrom
select how to identify the application from remote …

An application has TWO possible names:

  1. The name from the context the application was configured with.
  2. The name from the factory the application was created with.

The --ident-from prefix|factory value decide which on is used.

The application-identification is defined by MqConfigS::identFrom :

MqFactoryS::originalIdentif ident == MQ_IDENT_FACTORY
MqConfigS::prefixif ident == MQ_IDENT_PREFIX (default)

The MqFactoryS::originalIdent is the official name of the MqFactoryC and is defined by the application-programmer with MqFactoryAdd or MqFactoryDup2.

The MqConfigS::prefix is the official name of the MqContextC that startet first, usually the server-name, and is set by the application-user with --prefix string at startup or with the MqConfigSetPrefix at setup.

When the server starts, the MqClassIdentGet value is send from the server to the client and the client initializes the MqLinkS::targetIdent with this value. This value identifes the server from remote and is used by the MqContextC ROUTE API to select which server receive the routing-package.

The client usually get the factory and the idenfication from the: MqFactoryInitial.

Example: Change the factory-identifier of MqFactoryInitial to the value "TestClient" with:

C# MqFactoryC.Get("initial").Dup2("TestClient").Initial()
TCL [[tclmsgque::MqFactoryC Get "initial"] Dup2 "TestClient"] Initial
Note
After the link-start, the MqLinkS::targetIdent is no longer changed.

CONFIG STARTUP OPTIONS DETAILS

--tcp --host string --port int --myhost string --myport int

attribute: MqIoTcpConfigS, getter: MqContextC_ConfigGetIoTcp, setter: MqContextC_ConfigSetIoTcp
configure a context to use a tcp-client-server-link

Parameters
[in]hostclient: name of the remote interface (default: localhost)
server: name of the local interface (default: listen on all interfaces)
[in]portclient: name of the remote port
server: name of the local port
[in]myhostclient: name of the local interface
[in]myportclient: name of the local port

--uds --file fileName

attribute: MqIoUdsConfigS, getter: MqContextC_ConfigGetIoUds, setter: MqContextC_ConfigSetIoUds
configure a context to use a uds-client-server-link

The uds-socket (http://en.wikipedia.org/wiki/Unix_domain_socket) is usually 50% faster than a local tcp communication but only available on UNIX.

Parameters
[in]filename of a uds-socket-file (default: "MK_NULL")

--pipe

attribute: MqIoPipeConfigS, getter: MqContextC_ConfigGetIoPipe, setter: MqContextC_ConfigSetIoPipe
configure a context to use a pipe-client-server-link

The socket option is special because it is used only for internal purpose to submit the socket from the client to the server started as pipe by the client.

Parameters
[in]hdlthe file-descriptor-number (default: not set)

--thread --spawn --fork

attribute: MqConfigS::startAs, getter: MqContextC_ConfigGetStartAs, setter: MqContextC_ConfigSetStartAs
create a new application-context as thread, spawn or fork …

A new application-context is created if:

  • a tcp-uds-server listen on socket and get a connection-request from a client.
    This require: MqFactoryC and IServerSetup .
  • a filter-context create a new filter-object
  • a server-context create a new worker-context using MqSlaveWorker
  • a server-context start a new client-server-link using SELF as executable-name using MqLinkCreate

The allowed integer values for MqConfigS::startAs are:

  • MQ_START_DEFAULT = 0, use application-context default entity creation
  • MQ_START_FORK = 1, create entity as fork
  • MQ_START_THREAD = 2, create entity as thread
  • MQ_START_SPAWN = 3, create entity as spawn process

(default: do not create a new application-context)

--daemon pidfile

set: $ctx ConfigSetDaemon pidfile:string

This option is not available for tclmqmsgque.

CONFIG RUNTIME OPTIONS DETAILS

--logfile fileName

attribute: MkRuntimeS::logfile, getter: MkRuntimeC_GetLogfile, setter: MkRuntimeC_SetLogfile

--silent

attribute: MkRuntimeS::isSilent, getter: MkRuntimeC_GetIsSilent, setter: MkRuntimeC_SetIsSilent

--debug

attribute: MkRuntimeS::debug, getter: MkRuntimeC_GetDebug, setter: MkRuntimeC_SetDebug

CONFIG MISC OPTIONS DETAILS

--buffersize int

attribute: MqIoConfigS::buffersize, getter: MqContextC_ConfigGetBuffersize, setter: MqContextC_ConfigSetBuffersize
set the OS specific value for the socket-operation-buffer (default: OS specific)

--pkgsize int

attribute: MqIoConfigS::pkgsize, getter: MqContextC_ConfigGetPkgsize, setter: MqContextC_ConfigSetPkgsize
set maximum package size (default: 10 KiB)

--timeout int

attribute: MqIoConfigS::timeout, getter: MqContextC_ConfigGetTimeout, setter: MqContextC_ConfigSetTimeout
user defined timeout to terminate a blocking function call (default: 90 sec)

--string

attribute: MqConfigS::native, getter: MqContextC_ConfigGetIsString, setter: MqContextC_ConfigSetIsString
define if data is string or little or big endian …

CONFIG INTERFACE API

interface: $ctx ConfigSetServerSetup ?callback:callable="MK_NULL"?

define the server-setup-interface (callback) used on startup …

This interface is used to configure a new server-context-link, like a constructor, and is called at the end of MqLinkCreate or MqLinkCreateChild. This interface is called for every new incoming connection request and is used to define context specific services using MqServiceCreate or to initialize context-specific variables. As side-effect this interface set MqSetupS::isServer to true.

IServerSetup : callback signature
1. The *service-ctx* is the *context* for which the service was defined.
2. If the *callback* is **not** an instance of the calling *context*, the *service-ctx* is added as an argument.
callback-args := service-ctx:MqContextC[in]
[static] proc callback { callback-args ?additional-args...? } ...
[own] ::oo::class create XXX {
superclass MqContextC
method callback { ?additional-args...? } ...
[instance] ::oo::class create YYY {
method callback { callback-args ?additional-args...? } ...
[class] ::oo::class create ZZZ {
self method callback { callback-args ?additional-args...? } ...
read more at: Callback signature

Read more about how to define a service-callback in theLink .

interface: $ctx ConfigSetServerCleanup ?callback:callable="MK_NULL"?

define the server-cleanup-interface (callback) used on cleanup …

This interface is used to cleanup an old server-context-link, like a destructor, and is called at the beginning of MqLinkDelete to free context-specific variables. As side-effect this interface set MqSetupS::isServer to true.

IServerCleanup : callback signature
1. The *service-ctx* is the *context* for which the service was defined.
2. If the *callback* is **not** an instance of the calling *context*, the *service-ctx* is added as an argument.
callback-args := service-ctx:MqContextC[in]
[static] proc callback { callback-args ?additional-args...? } ...
[own] ::oo::class create XXX {
superclass MqContextC
method callback { ?additional-args...? } ...
[instance] ::oo::class create YYY {
method callback { callback-args ?additional-args...? } ...
[class] ::oo::class create ZZZ {
self method callback { callback-args ?additional-args...? } ...
read more at: Callback signature

Read more about how to define a service-callback in theLink .

interface: $ctx ConfigSetBgError ?callback:callable="MK_NULL"?

define the background-error-interface

A background error is an error without a link to an application-context and happen if an MqSendEND call fails or if an other asynchronous task fails. if the interface is not defined the error is printed to stderr and the application continue to work. if the interface is defined the context is set to error and the callback is called to process this error. Inside the callback the error is available using ErrorGetNum and ErrorGetText and can be cleared using ErrorReset.

IBgError : callback signature
1. The *service-ctx* is the *context* for which the service was defined.
2. If the *callback* is **not** an instance of the calling *context*, the *service-ctx* is added as an argument.
callback-args := service-ctx:MqContextC[in]
[static] proc callback { callback-args ?additional-args...? } ...
[own] ::oo::class create XXX {
superclass MqContextC
method callback { ?additional-args...? } ...
[instance] ::oo::class create YYY {
method callback { callback-args ?additional-args...? } ...
[class] ::oo::class create ZZZ {
self method callback { callback-args ?additional-args...? } ...
read more at: Callback signature

Read more about how to define a service-callback in theLink .

interface: $ctx ConfigSetEvent ?callback:callable="MK_NULL"?

Create a link to the calling tool event-handling queue …

Event-Handling is used to process tasks in the background to give the tool-user the feeling of a non-blocking application. For example Tcl using the event-handling to update the Tk user-interface while the application is waiting for data. The event handling function is called on idle-time and is designed for a very short function execution time. Do only one action per function call. This function will be called with a ~10000 usec interval to guarantee a parallel like execution.

Attention
1. The Event-Handler is used to start background processing during idel-time.
2. If MqSetupS::ignoreExit is set… and the process/thread is already on shutdown… the process/thread will continue to work as long as background tasks are available.
3. The process will only exit if all Event-Handler return ErrorSetCONTINUE to signal that no other background tasks are available.
example: example/LANG/Filter4.EXT
IEvent : callback signature
1. The *service-ctx* is the *context* for which the service was defined.
2. If the *callback* is **not** an instance of the calling *context*, the *service-ctx* is added as an argument.
callback-args := service-ctx:MqContextC[in]
[static] proc callback { callback-args ?additional-args...? } ...
[own] ::oo::class create XXX {
superclass MqContextC
method callback { ?additional-args...? } ...
[instance] ::oo::class create YYY {
method callback { callback-args ?additional-args...? } ...
[class] ::oo::class create ZZZ {
self method callback { callback-args ?additional-args...? } ...
read more at: Callback signature

Read more about how to define a service-callback in theLink .

MqContextC CONFIG API GET

C-API: MqContextC_ConfigApi_Get_C_API - MqContextC - various function to 'get' the configuration-data from a context

int32 [$ctx ConfigGetBuffersize]

top get the minimum of the read/send buffersize of the socket → API: tcl_mqmsgque_MqContextC_ConfigGetBuffersize

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the context.config.buffersize(R/S) value

MqIdentE [$ctx ConfigGetIdentFrom]

top get the MqConfigS::identFrom → API: tcl_mqmsgque_MqContextC_ConfigGetIdentFrom

Parameters
[in]ctxthe MqContextS instance to work on
Returns
prefix or factory

int32 [$ctx ConfigGetIoPipe]

top return the MqIoPipeConfigS → API: tcl_mqmsgque_MqContextC_ConfigGetIoPipe

Parameters
[in]ctxthe MqContextS instance to work on

{host:string port:string myhost:string myport:string} [$ctx ConfigGetIoTcp]

top get the configuration-data of the tcp-client-server-link … → API: tcl_mqmsgque_MqContextC_ConfigGetIoTcp

Parameters
[in]ctxthe MqContextS instance to work on
[out]host_outclient: name of the remote interface (default: localhost)
server: name of the local interface (default: listen on all interfaces)
[out]port_outclient: name of the remote port
server: name of the local port
[out]myhost_outclient: name of the local interface
[out]myport_outclient: name of the local port
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
  • if the config-value is not defined… the out-value will be set to "MK_NULL"
  • if the the out-value is "MK_NULL" … nothing will be done

MkBufferListC [$ctx ConfigGetIoTcpL]

top get the configuration-data of the tcp-client-server-link as MkBufferListC … → API: tcl_mqmsgque_MqContextC_ConfigGetIoTcpL

host
clientname of the remote interface (default: localhost)
servername of the local interface (default: listen on all interfaces
port
clientname of the remote port
servername of the local port
myhostname of the local interface
myportname of the local port
Parameters
[in]ctxthe MqContextS instance to work on
[out]vals_outthe contain host, port, myhost and myport data
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
the vals_out is owned by tclmqmsgque ... do not free !

string [$ctx ConfigGetIoUds]

top return the MqIoUdsConfigS → API: tcl_mqmsgque_MqContextC_ConfigGetIoUds

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the context.config.io.uds.file value

bool [$ctx ConfigGetIsParent]

top does the context object is a parent ? An objext is a parent id the MqConfigS::parent attribute is "MK_NULL" → API: tcl_mqmsgque_MqContextC_ConfigGetIsParent

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the (ctx->config.parent == NULL) value

bool [$ctx ConfigGetIsServer]

top does the context object is a server ? → API: tcl_mqmsgque_MqContextC_ConfigGetIsServer

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the (ctx->setup.isServer == true) value

bool [$ctx ConfigGetIsString]

top does the context object is using the string-mode ? → API: tcl_mqmsgque_MqContextC_ConfigGetIsString

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the (ctx->config.native == 'S') value

string [$ctx ConfigGetName]

top get the name of the context object → API: tcl_mqmsgque_MqContextC_ConfigGetName

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the context.config.name value
Attention
the string is owned by tclmqmsgque -> do not free !!

int32 [$ctx ConfigGetPkgsize]

top get the maximun size of a BDY package → API: tcl_mqmsgque_MqContextC_ConfigGetPkgsize

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the context.config.pkgsize(R/S) value

string [$ctx ConfigGetPostfix]

top get the MqConfigS::postfix → API: tcl_mqmsgque_MqContextC_ConfigGetPostfix

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the value requested
Attention
the string is owned by tclmqmsgque -> do not free !!

string [$ctx ConfigGetPrefix]

top get the MqConfigS::prefix → API: tcl_mqmsgque_MqContextC_ConfigGetPrefix

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the value requested
Attention
the string is owned by tclmqmsgque -> do not free !!

MqStartE [$ctx ConfigGetStartAs]

top return the MqConfigS::startAs value → API: tcl_mqmsgque_MqContextC_ConfigGetStartAs

MqStatusIsEF [$ctx ConfigGetStatusIs]

top return the MqContextS::statusIs value → API: tcl_mqmsgque_MqContextC_ConfigGetStatusIs

string [$ctx ConfigGetStorage]

top get the storage of the context object → API: tcl_mqmsgque_MqContextC_ConfigGetStorage

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the context.config.storage value
Attention
the string is owned by tclmqmsgque -> do not free !!

MkTimeoutE|int32 [$ctx ConfigGetTimeout]

top get the timeout value of the context object → API: tcl_mqmsgque_MqContextC_ConfigGetTimeout

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the context.config.timeout value

$ctx ConfigSetConfigFile filename:string

top set the config-file and parse for well-known config-items → API: tcl_mqmsgque_MqContextC_ConfigSetConfigFile

Read more at MqConfigS::cfg

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]filenamename of the config-file for input
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

MqContextC CONFIG API INTERFACE

C-API: MqContextC_ConfigApi_Interface_C_API - MqContextC - various function to setup a interface for the context

The "Setup"-Callback is special because this callback have to be callable by the server child and/or the slave context.

To distinguish the server child and slave the following functions are used:

$ctx ConfigSetBgError ?callback:callable="MK_NULL"?

top set the MqSetupS::BgError → API: tcl_mqmsgque_MqContextC_ConfigSetBgError

define the background-error-interface

A background error is an error without a link to an application-context and happen if an MqSendEND call fails or if an other asynchronous task fails. if the interface is not defined the error is printed to stderr and the application continue to work. if the interface is defined the context is set to error and the callback is called to process this error. Inside the callback the error is available using ErrorGetNum and ErrorGetText and can be cleared using ErrorReset.

IBgError : callback signature
1. The *service-ctx* is the *context* for which the service was defined.
2. If the *callback* is **not** an instance of the calling *context*, the *service-ctx* is added as an argument.
callback-args := service-ctx:MqContextC[in]
[static] proc callback { callback-args ?additional-args...? } ...
[own] ::oo::class create XXX {
superclass MqContextC
method callback { ?additional-args...? } ...
[instance] ::oo::class create YYY {
method callback { callback-args ?additional-args...? } ...
[class] ::oo::class create ZZZ {
self method callback { callback-args ?additional-args...? } ...
read more at: Callback signature

This function register a callback and is used to configure the application for a specific task.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]fCallfunction called with callback as argument to work on an specific task.
[in]callbackargument for fCall, for a target-language this is the target-language-callback-hdl.
[in]fFreecleanup the callback, called at the destruction of ctx.
[in]fCopycopy-constructor of the callback, used if the ctx is used to initialize an other newctx.

$ctx ConfigSetEvent ?callback:callable="MK_NULL"?

top set the MqSetupS::Event → API: tcl_mqmsgque_MqContextC_ConfigSetEvent

Create a link to the calling tool event-handling queue …

Event-Handling is used to process tasks in the background to give the tool-user the feeling of a non-blocking application. For example Tcl using the event-handling to update the Tk user-interface while the application is waiting for data. The event handling function is called on idle-time and is designed for a very short function execution time. Do only one action per function call. This function will be called with a ~10000 usec interval to guarantee a parallel like execution.

Attention
1. The Event-Handler is used to start background processing during idel-time.
2. If MqSetupS::ignoreExit is set… and the process/thread is already on shutdown… the process/thread will continue to work as long as background tasks are available.
3. The process will only exit if all Event-Handler return ErrorSetCONTINUE to signal that no other background tasks are available.
example: example/LANG/Filter4.EXT
IEvent : callback signature
1. The *service-ctx* is the *context* for which the service was defined.
2. If the *callback* is **not** an instance of the calling *context*, the *service-ctx* is added as an argument.
callback-args := service-ctx:MqContextC[in]
[static] proc callback { callback-args ?additional-args...? } ...
[own] ::oo::class create XXX {
superclass MqContextC
method callback { ?additional-args...? } ...
[instance] ::oo::class create YYY {
method callback { callback-args ?additional-args...? } ...
[class] ::oo::class create ZZZ {
self method callback { callback-args ?additional-args...? } ...
read more at: Callback signature

This function register a callback and is used to configure the application for a specific task.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]fCallfunction called with callback as argument to work on an specific task.
[in]callbackargument for fCall, for a target-language this is the target-language-callback-hdl.
[in]fFreecleanup the callback, called at the destruction of ctx.
[in]fCopycopy-constructor of the callback, used if the ctx is used to initialize an other newctx.
Attention

$ctx ConfigSetServerCleanup ?callback:callable="MK_NULL"?

top set the MqSetupS::ServerCleanup → API: tcl_mqmsgque_MqContextC_ConfigSetServerCleanup

define the server-cleanup-interface (callback) used on cleanup …

This interface is used to cleanup an old server-context-link, like a destructor, and is called at the beginning of MqLinkDelete to free context-specific variables. As side-effect this interface set MqSetupS::isServer to true.

IServerCleanup : callback signature
1. The *service-ctx* is the *context* for which the service was defined.
2. If the *callback* is **not** an instance of the calling *context*, the *service-ctx* is added as an argument.
callback-args := service-ctx:MqContextC[in]
[static] proc callback { callback-args ?additional-args...? } ...
[own] ::oo::class create XXX {
superclass MqContextC
method callback { ?additional-args...? } ...
[instance] ::oo::class create YYY {
method callback { callback-args ?additional-args...? } ...
[class] ::oo::class create ZZZ {
self method callback { callback-args ?additional-args...? } ...
read more at: Callback signature

This function register a callback and is used to configure the application for a specific task.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]fCallfunction called with callback as argument to work on an specific task.
[in]callbackargument for fCall, for a target-language this is the target-language-callback-hdl.
[in]fFreecleanup the callback, called at the destruction of ctx.
[in]fCopycopy-constructor of the callback, used if the ctx is used to initialize an other newctx.

$ctx ConfigSetServerSetup ?callback:callable="MK_NULL"?

top set the MqSetupS::ServerSetup → API: tcl_mqmsgque_MqContextC_ConfigSetServerSetup

define the server-cleanup-interface (callback) used on cleanup …

This interface is used to cleanup an old server-context-link, like a destructor, and is called at the beginning of MqLinkDelete to free context-specific variables. As side-effect this interface set MqSetupS::isServer to true.

IServerCleanup : callback signature
1. The *service-ctx* is the *context* for which the service was defined.
2. If the *callback* is **not** an instance of the calling *context*, the *service-ctx* is added as an argument.
callback-args := service-ctx:MqContextC[in]
[static] proc callback { callback-args ?additional-args...? } ...
[own] ::oo::class create XXX {
superclass MqContextC
method callback { ?additional-args...? } ...
[instance] ::oo::class create YYY {
method callback { callback-args ?additional-args...? } ...
[class] ::oo::class create ZZZ {
self method callback { callback-args ?additional-args...? } ...
read more at: Callback signature

This function register a callback and is used to configure the application for a specific task.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]fCallfunction called with callback as argument to work on an specific task.
[in]callbackargument for fCall, for a target-language this is the target-language-callback-hdl.
[in]fFreecleanup the callback, called at the destruction of ctx.
[in]fCopycopy-constructor of the callback, used if the ctx is used to initialize an other newctx.

MqContextC CONFIG API MISC

C-API: MqContextC_ConfigApi_Misc_C_API - MqContextC - various function to do 'misc' configuration …

$ctx ConfigReset

top clean the MqContextS::config data → API: tcl_mqmsgque_MqContextC_ConfigReset

MqContextC CONFIG API SET

C-API: MqContextC_ConfigApi_Set_C_API - MqContextC - various function to 'set' the configuration-data in a context

bool [$ctx ConfigCheckStartAs data:MqStartE]

top check if MqConfigS::startAs can be set to data → API: tcl_mqmsgque_MqContextC_ConfigCheckStartAs

$ctx ConfigSetAllDebug data:int32

top set the MkRuntimeS::debug value → API: tcl_mqmsgque_MqContextC_ConfigSetAllDebug

set all childs and all slaves and the link target parter… too

$ctx ConfigSetAllTimeout data:MkTimeoutE|int32

top set the MqIoConfigS::timeout value → API: tcl_mqmsgque_MqContextC_ConfigSetAllTimeout

set all childs and all slaves too

$ctx ConfigSetBuffersize data:int32

top set the MqIoConfigS::buffersize value → API: tcl_mqmsgque_MqContextC_ConfigSetBuffersize

$ctx ConfigSetDaemon pidfile:string

top start the server-context as daemon … → API: tcl_mqmsgque_MqContextC_ConfigSetDaemon

A daemon is a server-process without any link to the parent-process. A daemon-process has closed all default IO (e.g stdout, stdin, stderr) and forked into the background. (default: no daemon)

MQ_CTX const ctx,
MK_STRN pidfile
) {
if (MQ_IS_SERVER(ctx)) {
if (MqContextCT_X(ctx)->ignoreFork == true) {
return MkErrorDbV_1_XS (MK_ERROR_OPTION_FORBIDDEN, "--daemon", "current");
} else {
MkErrorCheck (MkSysDaemonize(MkOBJ(ctx), pidfile));
}
} else {
return MkErrorDbV_1_XS (MK_ERROR_OPTION_FORBIDDEN, "--daemon", "client");
}
return MK_OK;
return MkErrorStack_1X(ctx);
}
Attention
this option require the fork system-call and is not compatible with threads.
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]pidfilewrite the PID of the daemon into this file (default: NULL, do not start as daemon)
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx ConfigSetIdentFrom data:MqIdentE

top set the MqConfigS::identFrom value → API: tcl_mqmsgque_MqContextC_ConfigSetIdentFrom

$ctx ConfigSetIgnoreExit data:bool

top set the MqSetupS::ignoreExit value → API: tcl_mqmsgque_MqContextC_ConfigSetIgnoreExit

$ctx ConfigSetIoPipe fh:int32

top set the pipe configuration data … → API: tcl_mqmsgque_MqContextC_ConfigSetIoPipe

This is configuration option is only useful for a (x)inetd setup to use the stdin (socket=0) as send/recv communication socket

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]fhthe name of the known socket
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx ConfigSetIoTcp ?host:string="NULL"? ?port:string="NULL"? ?myhost:string="NULL"? ?myport:string="NULL"?

top configure a context to use a tcp-client-server-link … → API: tcl_mqmsgque_MqContextC_ConfigSetIoTcp

Parameters
[in]hostclient: name of the remote interface (default: localhost)
server: name of the local interface (default: listen on all interfaces)
[in]portclient: name of the remote port
server: name of the local port
[in]myhostclient: name of the local interface
[in]myportclient: name of the local port
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx ConfigSetIoTcpL vals:MkBufferListC

top configure a context to use a tcp-client-server-link … → API: tcl_mqmsgque_MqContextC_ConfigSetIoTcpL

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]valsa list with host, port, myhost, myport
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx ConfigSetIoUds file:string

top configure a context to use a uds-client-server-link … → API: tcl_mqmsgque_MqContextC_ConfigSetIoUds

The uds-socket (http://en.wikipedia.org/wiki/Unix_domain_socket) is usually 50% faster than a local tcp communication but only available on UNIX.

Parameters
[in]filename of a uds-socket-file (default: "MK_NULL")
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx ConfigSetIsServer data:bool

top set the MqSetupS::isServer value → API: tcl_mqmsgque_MqContextC_ConfigSetIsServer

$ctx ConfigSetIsString data:bool

top set the MqConfigS::native value 'S'string or 'L'owEndian or 'B'igEndian → API: tcl_mqmsgque_MqContextC_ConfigSetIsString

Attention
only the client can set this option... the server get this option from the client and using this function is ignored.

$ctx ConfigSetName data:string

top set the MqConfigS::dispname value and cleanup old value → API: tcl_mqmsgque_MqContextC_ConfigSetName

$ctx ConfigSetPkgsize data:int32

top set the MqIoConfigS::pkgsize value → API: tcl_mqmsgque_MqContextC_ConfigSetPkgsize

$ctx ConfigSetPostfix data:string

top set the client-part (2) of the application-identifer MqConfigS::dispname … → API: tcl_mqmsgque_MqContextC_ConfigSetPostfix

The postfix is used for:

  1. MqConfigS::dispname initialization

The postfix is initialize with:

  1. an empty string
  2. the $ctx ConfigSetPostfix data:string function
  3. the client postfix at server-startup
  4. the --postfix string option
Attention
if the --name string is explicitly set, then --prefix string and --postfix string have no effect

$ctx ConfigSetPrefix data:string

top set the server-part (1) of the application-identifer MqConfigS::dispname … → API: tcl_mqmsgque_MqContextC_ConfigSetPrefix

The prefix is used for:

  1. MqConfigS::dispname initialization
  2. application-identifer if --ident-from prefix|factory is set to prefix (default)
  3. groupname in --config fileName is used as application-identifer

The prefix is initialize with:

  1. the basename of the executable if NO factory is used
  2. the MqFactoryS::originalIdent
  3. the $ctx ConfigSetPrefix data:string or the $ctx ConfigSetName data:string function
  4. the --name string OR the --prefix string option
Attention
if the --name string is explicitly set, then --prefix string and --postfix string have no effect

$ctx ConfigSetStartAs data:MqStartE

top set the MqConfigS::startAs value → API: tcl_mqmsgque_MqContextC_ConfigSetStartAs

$ctx ConfigSetStartAsString data:string

top set the MqConfigS::startAs value using string default, thread, fork or spawn → API: tcl_mqmsgque_MqContextC_ConfigSetStartAsString

$ctx ConfigSetStorage data:string

top set the Storage value and cleanup old value → API: tcl_mqmsgque_MqContextC_ConfigSetStorage

$ctx ConfigSetTimeout data:MkTimeoutE|int32

top set the MqIoConfigS::timeout value → API: tcl_mqmsgque_MqContextC_ConfigSetTimeout

MqContextC ENV API

NAVI: top, up
EnvProtect protect the service-environment
EnvRestore

restore the service-environment

MqContextC ENV API DETAILS

C-API: MqContextC_EnvApi_C_API - MqContextC - protect and restore the service-environment …

The "Env" style functions are used to secure the service-environment (defined in MqEnvS)
and is required.. under special conditions... to proper answer the original service call at the
end of the service-processing.
By default tclmqmsgque guarantee the proper management of the environment on behalf of the user.
Under normal conditions the user don't need these functions.

The folllowing design-goals were defined:

  • normal condition...
    • Every tclmqmsgque function does protect the original service-environment by default
    • esay goal to remember: come-in == come-out
  • special condition...
    • After loading the read-data-package...
    • the service-environment must be in the same condition as when the read-data-package was saved.

The two design-goals from above are in conflict and the both functions MqEnvProtect and MqEnvRestore are used to solve this conflict.

Example from server.tcl protect the environment and import from database

        # PROTECT the original service-call
        my EnvProtect
        # OVERWRITE the original service-call with data from the database
        $dump Import [self]
        set ret [my ReadALL]
        # RESTORE the original service-call
        my EnvRestore
        # ANSWER the original service-call
        my Send "R" "L" $ret

$ctx EnvProtect

top protect the service-environment → API: tcl_mqmsgque_MqContextC_EnvProtect

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on

$ctx EnvRestore

top restore the service-environment → API: tcl_mqmsgque_MqContextC_EnvRestore

Parameters
[in]ctxthe MqContextS instance to work on

MqContextC ERROR API

NAVI: top, up
ErrorCopy copy a MkErrorS from the sourceCtx to the targetCtx
ErrorFORMAT helper used to access MkErrorDEFAULT from MqContextC
ErrorMove

move a MkErrorS from the sourceCtx to the targetCtx

MqContextC ERROR API DETAILS

C-API: MqContextC_ErrorApi_C_API - MqContextC - move and copy an error from a context

MkErrorE [$targetCtx ErrorCopy sourceCtx:MqContextC]

top copy a MkErrorS from the sourceCtx to the targetCtx … → API: tcl_mqmsgque_MqContextC_ErrorCopy

In tclmqmsgque the a MkRuntimeC is only one error-object per thread but this error-object has also addiitional attributes to identify the source of the error. In addition the tclmqmsgque has also an extended-error-object MqErrorS which also has error-specific-attributes. The MqContextErrorCopy is used to copy an error frome sourceCtx to targetCtx and keep the additional attributes in sync.

Note
  • by default… every error set in a slave is also set in the master.
  • by default… the error is only copied if sourceCtx and targetCtx are different.
  • by default… the error is not copied if targetCtx MqConfigS::master of sourceCtx.
  • by default… the copy only happen if sourceCtx has an error.
  • on copy… the error of sourceCtx will be reset.
See also
MqContextErrorMove
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
targetCtxthe MqContextC object and the target of the error
sourceCtxthe MqContextC object and the source of the error

MkErrorC [$fmtobj ErrorFORMAT]

top helper used to access MkErrorDEFAULT from MqContextC → API: tcl_mqmsgque_MqContextC_ErrorFORMAT

MkErrorE [$targetCtx ErrorMove sourceCtx:MqContextC]

top move a MkErrorS from the sourceCtx to the targetCtx … → API: tcl_mqmsgque_MqContextC_ErrorMove

Note
  • by default… every error set in a slave is also set in the master.
  • by default… the error is only copied if sourceCtx and targetCtx are different.
  • by default… the error is not copied if targetCtx MqConfigS::master of sourceCtx.
  • by default… the copy only happen if sourceCtx has an error.
  • on copy… the error of sourceCtx will be reset.
See also
MqContextErrorCopy
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
targetCtxthe MqContextC object and the target of the error
sourceCtxthe MqContextC object and the source of the error and cleared

MqContextC HIGH API

NAVI: top, up
Send

user friendly replacement for the MqContextC_SendApi_C_API

MqContextC HIGH API DETAILS

C-API: MqContextC_HighApi_C_API - MqContextC - User friendly replacement for the MqContextC_SendApi_C_API and the MqContextC_ReadApi_C_API

User Friendly mean, replacing many lines of code by a single line of code.
The basic idea is, to use a format-signature to identify the additional command-line-arguments (args…).

The pseudo syntax is:

MqSend( "CALL-SIGNATUR",call-args …,"TOKEN-SIGNATURE",send-args …,read-args …);
CALL-SIGNATUR = "[E|W|C|S|T|R|t|r]" or ?call-args?
E = MqSendEND ?t-arg = 0?
S = MqSendEND_AND_SUB, c-arg, ?t-arg = MK_TIMEOUT_DEFAULT?
t = expect timeout value as t-arg in call-arg
r = switch 'rpc-flag' on to enable 'rpc' style parsing of the TOKEN-SIGNATURE
call-args = ?c-arg?, ?i-arg?, ?t-arg?
?c-arg? = callback ... function, service
?i-arg? = ident ...... MQ_TOK service-identifer to receive the result
?t-arg? = timeout .... MK_TIME_T in seconds
TOKEN-SIGNATUR = "service-ident:send-signature@read-signature"
service-ident = MQ_TOK service identifier to call a remote service
send-signature = ?(…)? or multiple [Y|O|S|I|F|W|D|G|C|B|U|L] or […]
?(…)? = only as FIRST arg, only for MqSendEND_AND_TRANSACTION
read-signature = multiple [Y|O|S|I|F|W|D|G|C|B|U|L] or . or * or […]
MK_TIMEOUT_DEFAULT
time_t MK_TIME_T
#define MqSend(...)
#define MqReadI64(...)
#define MqReadSTR(...)
#define MqReadI16(...)
#define MqReadDBL(...)
#define MqReadBFL(...)
#define MqReadBUF(...)
#define MqReadLONG(...)
#define MqReadI8(...)
#define MqReadBIN(...)
#define MqReadFLT(...)
#define MqReadALL(...)
#define MqReadBOL(...)
#define MqReadI32(...)
#define MqReadL_START(...)
#define MqReadL_END(...)
#define MqSendBIN(...)
#define MqSendLONG(...)
#define MqSendI8(...)
#define MqSendBOL(...)
#define MqSendI64(...)
#define MqSendI32(...)
#define MqSendBFL(...)
#define MqSendI16(...)
#define MqSendSTR(...)
#define MqSendFLT(...)
#define MqSendDBL(...)
#define MqSendBUF(...)
#define MqSendEND_AND_TRANSACTION(...)
#define MqSendEND_AND_CALLBACK(...)
#define MqSendEND_AND_SUB(...)
#define MqSendEND_AND_WAIT(...)
#define MqSendEND(...)
#define MqSendL_START(...)
#define MqSendT_END(...)
#define MqSendL_END(...)
#define MqSendT_START(...)
#define MqSendRETURN(...)
MK_STRN MQ_TOK
MqContextC - a char[4+1] or hex[8+1] string used to unique identify a service …

The following parts from the MqContextC_SendApi_C_API will be replaced by the MqContextC_HighApi_C_API

API Function Usage
MqSendSTART -> start a service call or a answer
SendATOM -> write a single argument into the data-package
SendEND -> send the service-call to the receiver
ReadATOM -> read a single argument from the data-package
SendRETURN -> answer a service call

The replacement is defined by two parts, a High_CALL_SIGNATURE and a High_TOKEN_SIGNATURE. Both parts are strings and descripe a type or an action of a vararg argument.

Example: a typical code replacement in C looks like

MkErrorCheck( MqSend( ctx, "Wt", 15, "SUBI:IDC@D", 5, 6.3, "HALLO", &doubleVal ) );

and replaces the following commands...

MkErrorCheck( MqSendSTART( ctx ) );
MkErrorCheck( MqSendI32( ctx, 5 ) );
MkErrorCheck( MqSendDBL( ctx, 6.3 ) );
MkErrorCheck( MqSendSTR( ctx, "HALLO" ) );
MkErrorCheck( MqSendEND_AND_WAIT( ctx, "SUBI", 15 ) );
MkErrorCheck( MqReadDBL( ctx, &doubleVal ) );
#define MqSendSTART(...)

High_CALL_SIGNATURE

The Call-Signature is a string of call-signature-char (CFC) starting with "E", "W", "C", "S" or "R" followed optional with "t"

CFC Required Reference call-args Default Usage
E yes once no yes MqSendEND
W yes once no no MqSendEND_AND_WAIT
C yes once function or service no MqSendEND_AND_CALLBACK
S yes once function or service no MqSendEND_AND_SUB
T yes once service-ident no MqSendEND_AND_TRANSACTION
R yes once no no MqSendRETURN
t no W,S,T seconds MK_TIMEOUT_USER set the TIMEOUT

High_TOKEN_SIGNATURE

  1. The token-signature has the usage "service-ident : send-signature @ read-signature" and is used to identify the target-service and the required arguments.
  2. The service-ident is identified by the MQ_TOK item followed by a [:] and the send-signature.
  3. The send-signature has one type-identifer for every send-argument. The send-argument is identified by a arg-signature-char (ASC) and is defined in MkTypeE.
  4. The MkTypeE is used in the MkBufferU and descripe the type of a vararg argument or action.
ASC MkTypeE Usage Number of arguments required
"Y" MK_I8 MkBufferAtomU.I8 1
"O" MK_BOL MkBufferAtomU.BOL 1
"S" MK_I16 MkBufferAtomU.I16 1
"I" MK_I32 MkBufferAtomU.I32 1
"F" MK_FLT MkBufferAtomU.FLT 1
"W" MK_I64 MkBufferAtomU.I64 1
"D" MK_DBL MkBufferAtomU.DBL 1
"G" MK_LONG 32bit=I, 64bit=W 1
"B" MK_BIN MkBufferU.B 1 -> MkBinaryR reference
"C" MK_STR MkBufferU.C 1
"U" MK_BUF MkBufferC . 1 -> typeless Buffer able to hold every kind of data
"L" MK_BFL MkBufferListC . 1 -> list of MkBufferC .
"." MK_BUF MkBufferC . 1 -> READ ONLY - like 'U' but return the Buffer-Value and not the MkBufferC .
"*" MK_BFL MkBufferListC . 1 -> READ ONLY - like 'L' but collect ALL remaining data as ONE MkBufferListC .
"[" MqSendL_START 0 -> Start of List
"]" MqSendL_END 0 -> End of List
"(" MqSendT_START 0 -> Start of Transaction Object, only as FIRST parameter
")" MqSendT_END 0 -> End of Transaction Object, only ONE supported
":" END of SERVICE-IDENT * -> next SEND_SIGNATURE
"@" END of SEND-SIGN. * -> next READ-SIGNATURE

Example from server.tcl in a service-call send the server-configuratien back to the client

  method Ot_CNFG {} {
    my SendSTART
    my SendBOL [my ConfigGetIsServer]
    my SendBOL [my LinkIsParent]
    my SendBOL [my SlaveIs]
    my SendBOL [my ConfigGetIsString]
    my SendBOL [MkRuntimeC GetIsSilent]
    my SendBOL [my LinkIsConnected]
    my SendSTR [my ConfigGetName]
    my SendI32 [MkRuntimeC GetDebug]
    my SendI32 [my LinkGetCtxId]
    my SendSTR [my ServiceTokenGet]
    my SendRETURN
  }

$ctx Send cstr:string args:args...

top user friendly replacement for the MqContextC_SendApi_C_API … → API: MqSend_RT

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]cstrthe High_CALL_SIGNATURE
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqSendVL2

MqContextC LINK API

NAVI: top, up
LinkConnect re-connect a client-server-link after a server crash or a network downtime …
LinkCreate make ctx to a parent-context and setup a new client-server-link
LinkCreateChild make a context to a child-context on-top of an existing parent-client-server-link
LinkDelete close the client-server-link
LinkGetCtxId get an identifier which is unique per parent-or-child-context
LinkGetParent get the initial parent-context from a client/server link …
LinkGetTargetIdent get the ident of the link-target
LinkIsConnected is the context connected? …
LinkIsParent is the context a parent-context? …
LinkShutdown

shutdown the communication with a server

MqContextC LINK API DETAILS

C-API: MqContextC_LinkApi_C_API - MqContextC - setup and manage a client-server-link

The client-server-link connect two context, a client-parent-context and a server-parent-context. The link can be local (connect two context on the same host) or can be remote (connect two context on different hosts). On-Top the parent-context multiple child-context are allowed.

  !on remote host!                                  !on local host!

      server1---------x                     x----------server2
         |            |                     |             |
         |     child-context-1       child-context-2      |
         |            |                     |             |                      server
 parent-context-1-----x                     x-----parent-context-2
         |                                                |
 (MqConfigS::server)                 (example: MqConfigS::server --fork --uds … --file …)
         |                                                |
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
         |                                                |
      (--tcp)                                  (--pipe, --uds, --tcp)
         |                                                |
 parent-context-1-----x                     x-----parent-context-2
         |            |                     |             |                      client
         |     child-context-1       child-context-2      |
         |            |                     |             |
         x------------x--------client-------x-------------x

                           !on local host!

Definition of a "client-context"

  • every new client-parent-context create a new client-server-link and perform the connect system-call.
  • every new client-server-link start a new server-object and creating a new server-parent-context
  • every deletion of the client-parent-context stop the previous started server-object and delete the server-parent-context
  • the client-context get all the error/warning/info messages from the server-context

Definition of a "server-context"

  • every new server-parent-context is created by request from the client-parent-context:
  • in remote mode every new server-parent-context wait for a tcp or uds connection request using the accept system-call.
client --tcp --host REMOTE_HOST --port REMOTE_PORT ... or
client --uds --file MYFILE ...
  • in local mode new server-parent-context is started by the client-parent-context as pipe:
    client @ server
    • a server-context have to implement the IServerSetup and the MqFactoryC interface.
    • a server-context have to enter the event-loop and wait for incoming service-request using MqProcessEvent together with the MQ_WAIT_FOREVER.

Definition of a "parent-context"

  • the parent is the first context created and is created with MqLinkCreate
  • every new parent-context on the client create a new communication to a server.
  • every new parent-context on the client connect to a new parent-context on the server
  • every new parent-context on the server create a new thread or process.
  • the parent-context control the socket communication interface

Definition of a "child-context"

  • the child-context is the second or more context and is created with MqLinkCreateChild.
  • every new child-context on the client create a new child-context on the server.
  • every new child-context is totally independent from the parent-context setup and is able to serve its own services.
  • the child-context is using the parent-context as a tunnel.
  • the child-context is using the the thread or process of the parent-context.
  • the parent of a child-context can be a parent-context or an other child-context. A tree like structure is created.
  • the child-context is using the communication interface from the parent-context.
  • if a context is deleted (parent or child) the depending context (parent or child) is deleted too.

$ctx LinkConnect

top re-connect a client-server-link after a server crash or a network downtime … → API: tcl_mqmsgque_MqContextC_LinkConnect

Do nothing if the client-server-link is already connected. This function is only useful in an event-function (IEvent) if the link-disconnect (ErrorIsEXIT) is ignored (ErrorReset). Read more from the: /example/tcl/Filter4.tcl example.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx LinkCreate ?args:MkBufferListC...="MK_NULL"?

top make ctx to a parent-context and setup a new client-server-link … → API: tcl_mqmsgque_MqContextC_LinkCreate

The goal of the MqLinkCreate is to setup a link to a new server-context on the SERVER.

The link is created with MqIoComE to a server started with MqStartE.

The argument args is a list of command-line-arguments to configure the client-server-link including the @ item to add server-command-line-arguments.

The following special-keyword as first argument after @ is recognized:

factory-name
A known factory previous added with MqFactoryAdd.
MqFactoryAdd_1("myFeature");
...
MqLinkCreate(ctx,...,"@",myFeature,...);
#define MqFactoryAdd_1(fct)
SELF
Recognized as the initial-factory-name. (e.g. MqFactoryInitial)
The startup with "@ SELF arg1…" will be "@ executable factory-name arg1…"
WORKER
Recognized as the own executable name.
The startup from "@ WORKER arg1…" will be "@ executable arg1…"
If the ctx is not the server-context… (e.g MqSetupS::isServer == true) the default-factory (e.g. MqFactoryDefault) will be used.

The executable is defined by (static) MqMsgque InitSetArg0 ?bfl:MkBufferListC...="MK_NULL"? and will be automatical set for a non C / C++ language.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]argscommand-line-arguments to configure the client-server-link
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx LinkCreateChild parent:MqContextC ?args:MkBufferListC...="MK_NULL"?

top make a context to a child-context on-top of an existing parent-client-server-link … → API: tcl_mqmsgque_MqContextC_LinkCreateChild

A child is using the same process or thread as the parent but a different namespace. With a different namespace a child is able to act on different services on the shared server.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]parentthe parent-context defined with MqLinkCreate
[in]argscommand-line-arguments to configure the client-server-link without the "@" item.
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx LinkDelete

top close the client-server-link … → API: tcl_mqmsgque_MqContextC_LinkDelete

On a client the context will be set to not-connected and the function MqLinkIsConnected will return false. On a server the context will be deleted but only if MqSetupS::ignoreExit is not set to true. If the link is already not-connected nothing will happen.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on

int32 [$ctx LinkGetCtxId]

top get an identifier which is unique per parent-or-child-context … → API: tcl_mqmsgque_MqContextC_LinkGetCtxId

The context-identifier is a number and is used in the protocol to link a data-package to a context-pointer. This is necessary because the communication interface is shared between the parent-context and the child-context. This number is unique.

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the identifier as number

MqContextC [$ctx LinkGetParent]

top get the initial parent-context from a client/server link … → API: tcl_mqmsgque_MqContextC_LinkGetParent

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the parent-context or "MK_NULL" if ctx is "MK_NULL"

string [$ctx LinkGetTargetIdent]

top get the ident of the link-target … → API: tcl_mqmsgque_MqContextC_LinkGetTargetIdent

This function is only useful if the link is up and running.

Parameters
[in]ctxthe MqContextS instance to work on
Returns
get the ident of the link-target or "MK_NULL" if not connected

bool [$ctx LinkIsConnected]

top is the context connected? … → API: tcl_mqmsgque_MqContextC_LinkIsConnected

A context is connected if the MqLinkCreate command was successful. A context is not connected if:

  • the context has just been created and not connected
  • the link was deleted with MqLinkDelete
Parameters
[in]ctxthe MqContextS instance to work on
Returns
a boolean value, true or false

bool [$ctx LinkIsParent]

top is the context a parent-context? … → API: tcl_mqmsgque_MqContextC_LinkIsParent

A context is a parent-context if it was created with MqLinkCreate

Parameters
[in]ctxthe MqContextS instance to work on
Returns
a boolean value, true or false

$ctx LinkShutdown

top shutdown the communication with a server → API: tcl_mqmsgque_MqContextC_LinkShutdown

The following tasks are performend:

  • shutdown all childs
  • shutdown all slaves
  • client send the shutdown-sequence to the server
  • server answer the shutdown-sequence from the client
  • if parantshutdown the communication infrastructure
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

MqContextC LOG API

NAVI: top, up
Log log the MqContextC
LogConfig log the MqContextC part MqConfigS
LogEnv log the MqContextC part MqEnvS
LogLink log the MqContextC part MqLinkS
LogSetup log the MqContextC part MqSetupS
LogShort log the MqContextC with less info then MqContextLog
LogType log the MqContextC part MkTypeS
LogParentOrChild is ctx a PARENT or a CHILD ? …
LogServerOrClient

is ctx a SERVER or a CLIENT ? …

MqContextC LOG API DETAILS

C-API: MqContextC_LogApi_C_API - MqContextC - log the output to a string or a MkLogFileC

Logging is an important part of the debugging and validation task.

The logging target is set with MkRuntimeSetLogfile wich accepts a filename or the special token stdout or stderr.

Many logging functions have common parameters:

Parameters
[in]fmtobjmanaged object used to format the log-message (default="MK_NULL" → use default-format)
[in]callfunca user-defined postfix to identify the calling function or the environment (default=name-of-function)
[in]debugthe debug level from MkRuntimeS::debug, use 0 <= debug <= 9 (default=0)

$ctx Log ?fmtobj:MkObjectC="MK_NULL"? ?debug:int32=0? ?callfunc:string="MK_NULL"? ?lvl:int32=0?

top log the MqContextC … → API: tcl_mqmsgque_MqContextC_Log

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]fmtobjmanaged object used to format the log-message (default="MK_NULL" → use default-format)
[in]debugthe debug level from MkRuntimeS::debug, use 0 <= debug <= 9 (default=0)
[in]callfunca user-defined postfix to identify the calling function or the environment (default=name-of-function)
[in]lvla user-defined prefix starting with "" for lvl=0 and increase with " " for lvl+1 (default=0)
See also
MqContextC_C_API MqContextLogShort

$ctx LogConfig ?fmtobj:MkObjectC="MK_NULL"? ?debug:int32=0? ?callfunc:string="MK_NULL"? ?lvl:int32=0?

top log the MqContextC part MqConfigS … → API: tcl_mqmsgque_MqContextC_LogConfig

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]fmtobjmanaged object used to format the log-message (default="MK_NULL" → use default-format)
[in]debugthe debug level from MkRuntimeS::debug, use 0 <= debug <= 9 (default=0)
[in]callfunca user-defined postfix to identify the calling function or the environment (default=name-of-function)
[in]lvla user-defined prefix starting with "" for lvl=0 and increase with " " for lvl+1 (default=0)

$ctx LogEnv ?fmtobj:MkObjectC="MK_NULL"? ?debug:int32=0? ?callfunc:string="MK_NULL"? ?lvl:int32=0?

top log the MqContextC part MqEnvS … → API: tcl_mqmsgque_MqContextC_LogEnv

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]fmtobjmanaged object used to format the log-message (default="MK_NULL" → use default-format)
[in]debugthe debug level from MkRuntimeS::debug, use 0 <= debug <= 9 (default=0)
[in]callfunca user-defined postfix to identify the calling function or the environment (default=name-of-function)
[in]lvla user-defined prefix starting with "" for lvl=0 and increase with " " for lvl+1 (default=0)
See also
MqContextC_EnvApi_C_API

$ctx LogLink ?fmtobj:MkObjectC="MK_NULL"? ?debug:int32=0? ?callfunc:string="MK_NULL"? ?lvl:int32=0?

top log the MqContextC part MqLinkS … → API: tcl_mqmsgque_MqContextC_LogLink

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]fmtobjmanaged object used to format the log-message (default="MK_NULL" → use default-format)
[in]debugthe debug level from MkRuntimeS::debug, use 0 <= debug <= 9 (default=0)
[in]callfunca user-defined postfix to identify the calling function or the environment (default=name-of-function)
[in]lvla user-defined prefix starting with "" for lvl=0 and increase with " " for lvl+1 (default=0)

$ctx LogSetup ?fmtobj:MkObjectC="MK_NULL"? ?debug:int32=0? ?callfunc:string="MK_NULL"? ?lvl:int32=0?

top log the MqContextC part MqSetupS … → API: tcl_mqmsgque_MqContextC_LogSetup

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]fmtobjmanaged object used to format the log-message (default="MK_NULL" → use default-format)
[in]debugthe debug level from MkRuntimeS::debug, use 0 <= debug <= 9 (default=0)
[in]callfunca user-defined postfix to identify the calling function or the environment (default=name-of-function)
[in]lvla user-defined prefix starting with "" for lvl=0 and increase with " " for lvl+1 (default=0)

$ctx LogShort ?fmtobj:MkObjectC="MK_NULL"? ?debug:int32=0? ?callfunc:string="MK_NULL"? ?lvl:int32=0? ?label:string="NULL"?

top log the MqContextC with less info then MqContextLog … → API: tcl_mqmsgque_MqContextC_LogShort

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]fmtobjmanaged object used to format the log-message (default="MK_NULL" → use default-format)
[in]labela string to identify a task or object
[in]debugthe debug level from MkRuntimeS::debug, use 0 <= debug <= 9 (default=0)
[in]callfunca user-defined postfix to identify the calling function or the environment (default=name-of-function)
[in]lvla user-defined prefix starting with "" for lvl=0 and increase with " " for lvl+1 (default=0)
See also
MqContextC_C_API MqContextLog

$ctx LogType ?fmtobj:MkObjectC="MK_NULL"? ?debug:int32=0? ?callfunc:string="MK_NULL"? ?lvl:int32=0?

top log the MqContextC part MkTypeS … → API: tcl_mqmsgque_MqContextC_LogType

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]fmtobjmanaged object used to format the log-message (default="MK_NULL" → use default-format)
[in]debugthe debug level from MkRuntimeS::debug, use 0 <= debug <= 9 (default=0)
[in]callfunca user-defined postfix to identify the calling function or the environment (default=name-of-function)
[in]lvla user-defined prefix starting with "" for lvl=0 and increase with " " for lvl+1 (default=0)
See also
MqContextC_C_API MqContextLog

string [$ctx LogParentOrChild]

top is ctx a PARENT or a CHILD ? … → API: tcl_mqmsgque_MqContextC_LogParentOrChild

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the string PARENT or CHILD

string [$ctx LogServerOrClient]

top is ctx a SERVER or a CLIENT ? … → API: tcl_mqmsgque_MqContextC_LogServerOrClient

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the string SERVER or CLIENT

MqContextC MISC API

NAVI: top, up
GetBuffer get the MqContextS::ctxbuf object
ToString String-Slot - returns the string representation of the inst
Exit delete the context and exit the current process or thread …
GetRoot get the Root (toplevel initial context)
ProcessEvent

enter the event-loop and wait for an incoming service-request. …

MqContextC MISC API DETAILS

C-API: MqContextC_MiscApi_C_API - MqContextC - various functions to work on a context

MkBufferC [$ctx GetBuffer]

top get the MqContextS::ctxbuf object → API: tcl_mqmsgque_MqContextC_GetBuffer

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Returns
the context->ctxbuf object
Attention
(do not free) The memory of the out/return value belongs to the called TclMqMsgque function and therefore never becomes "MK_NULL" for a non-error result.
For details on the out/return value, see: MkKernel_Storage_C_API.

string [$ctx ToString]

top String-Slot - returns the string representation of the inst … → API: tcl_mqmsgque_MqContextC_ToString

The string is a human-readable form of the data stored in the object.

See also
slot: every class should provide a ToString function by default.
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Returns
the requested string or "MK_NULL" on error
Note
(do not free) The memory of the out/return value belongs to the called TclMqMsgque function and therefore never becomes "MK_NULL" for a non-error result.
For details on the out/return value, see: MkKernel_Storage_C_API.

$ctx Exit ?callfunc:string="MK_NULL"? ?callfile:string="MK_NULL"? ?callline:int32=-1?

top delete the context and exit the current process or thread … → API: tcl_mqmsgque_MqContextC_Exit

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]callfunca user-defined postfix to identify the calling function or the environment (default=name-of-function)
[in]callfilethe name of the file the call take place (e.g. FILE)
[in]calllinethe number of the line the call take place (e.g. LINE)

To delete an application is a difficult task because the link-target have to be informed. This information is send as shutdown-event and finally as socket-exit after application-exit. This library tries to perform this two steps even if the default exit function is called. This is no problem because the second step (socket-exit) is enough to signal a link-down. It is not secure to depend only on socket-exit for application exit because sometimes the sockets stop working or the link-target does not get a socket-exit. For example the pipe-link on windows. The client can not exit and create a socket-exit error on the server because the server is still running without receiving a shutdown-event. A second argument for using the MqExit function is, that it can be used for process and thread exit. A thread, started by tclmqmsgque, does exit but the process continue to work. To make it short use MqExit to exit your application.

The following steps are performed:

  • delete the client-server-link using: MqLinkDelete
  • if available call the context-specific-exit-handler: MqCtxTypeS::fProcessExit
  • or call application-default-exit-handler
  • it is a panic-error to call MqExit twice for the same object
Attention
It is a bad practice to call MqExit from inside a service.

potential problems

  1. If you call MqExit on a service in a c++ (p)thread on linux … an SIGABRT is raised… ??? this problem is related with the "internal thread cleanup"… call ErrorSetEXIT to exit from a service handle

MqContextC [$ctx GetRoot]

top get the Root (toplevel initial context) → API: tcl_mqmsgque_MqContextC_GetRoot

$ctx ProcessEvent ?wait:MqWaitOnEventE=NO? ?timeout:MkTimeoutE|int32=DEFAULT?

top enter the event-loop and wait for an incoming service-request. … → API: tcl_mqmsgque_MqContextC_ProcessEvent

This function is used to enter the event-loop and start listen on open file-handles and to call IEvent on idle.
This function is mostly used on a server to enter the event-loop and wait for an incoming service request or on a client/server with all functions which exchange data like MqContextC SEND API, MqLinkConnect etc.

Attention
Be aware that the read-data-package is only valid until the event-loop is entered. During event-loop new data may be available for the ctx and the read-data-package will be overwritten.
See also
MqRouteTraverse
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]waitthe operation-mode used to define the behaviour, possible values are:
MQ_WAIT_NO 0

Check for one event but do not wait …

If an event is available process the event, but only one. If no event is available return with MK_CONTINUE. This is the default.

MQ_WAIT_ONCE 1

Wait maximum timeout seconds for one new event, doesn't matter which context the event belongs to or raise an timeout-error


attention: During serving an event and this event uses the MqContextC SEND API or an other MqProcessEvent … an additional event could be served as well.


error: An asynchronous error (_ERR) always belong to the parent-context of the socket connection

  • if $ctx ConfigSetBgError ?callback:callable="MK_NULL"? is set.. the current context returns MK_OK.
  • if $ctx ConfigSetBgError ?callback:callable="MK_NULL"? is not set.. the current context the returns MK_ERROR and an error is raised.
MQ_WAIT_OWN 2

Wait maximum timeout seconds for one new event that belongs to the current context or raise an timeout-error


error: An asynchronous error (_ERR) always belong to the parent-context of the socket connection

  • if $ctx ConfigSetBgError ?callback:callable="MK_NULL"? is set.. the current context will not return and continue working.
  • if $ctx ConfigSetBgError ?callback:callable="MK_NULL"? is not set.. the current context returns MK_ERROR and an error is raised.
MQ_WAIT_FOREVER 3

Wait maximum timeout seconds for an event or raise an timeout-error

  • If an event was found process the event.
  • If an event was not found, raise a timeout-error. After the event was processed continue to listen for a the new event.

This function will only come back on error or on exit.

[in]timeoutin seconds until a timeout-error is raised, possible values are:
integer >0 use this value as number of seconds.
MK_TIMEOUT_DEFAULT -1 MK_TIMEOUT_USER for MQ_WAIT_ONCE or MK_TIMEOUT_MAX for MQ_WAIT_FOREVER. - request the default timeout value
MK_TIMEOUT_USER -2 request the user defined timeout value from MqIoConfigS::timeout
MK_TIMEOUT_MAX -3 request the maximum possible (infinite) timeout value
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

MqContextC PROXY API

NAVI: top, up
ProxyForward send the entire read-data-package-data to the link-target
ProxyItem

Copy a single-data-item from the sourceCtx to the targetCtx.

MqContextC PROXY API DETAILS

C-API: MqContextC_ProxyApi_C_API - MqContextC - copy data from the read-data-package of the sourceCtx to the send-data-package of the targetCtx

The proxy-feature is used in a filter-setup to process-and-forward incoming data.

See also
MqDumpC

Example: A typical proxy-setup in pseudo C++ code

void myService () {
MqContextC *ftr = SlaveGetFilter(); // get the "slave" with id "1" (the filter)
...
ftr->SendSTART(); // start the FORWARD
while (ReadItemExists()) { // read ALL data from the ORIGINAL service-call
ProxyItem(ftr); // forward a SINGEL item from "this" to "ftr"
}
...
ftr->SendEND_AND_WAIT("MYTK"); // send the data.package to "ftr"
...
SendSTART(); // start the ANSWER
while (ftr->ReadItemExists()) { // read ALL data from the "MYTK" service-call
ftr->ProxyItem(this); // forward a SINGEL item from "ftr" to "this"
}
SendRETURN(); // answer the ORIGINAL service call
}

$sourceCtx ProxyForward targetCtx:MqContextC ?dump:MqDumpC="MK_NULL"? ?timeout:MkTimeoutE|int32=DEFAULT?

top send the entire read-data-package-data to the link-target … → API: tcl_mqmsgque_MqContextC_ProxyForward

The goal of this function is to link two context, typically a master and a slave (filter). This function is typically used in a service or and event callback to send the entire package and wait for the answer.

Example of a typical usage in pseudo c++

void myService () {
MqContextC *ftr = SlaveGetFilter(); // get the "slave" with id "1" (the filter)
...
ProxyForward(ftr); // forward AND send the entire ENTIRE package from "this" to "ftr"
...
SendRETURN(); // answer the ORIGINAL service call
}
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]sourceCtxthe source of the copy
[in,out]targetCtxthe target of the copy
[in]dumpif not "MK_NULL", the value is the source of the copy, dump is the return from MqDumpExport,
[in]timeoutin seconds until a timeout-error is raised (possible values like ProcessEvent) (MK_TIMEOUT_DEFAULT=MK_TIMEOUT_USER)
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqProxyItem MqServiceProxy MqServiceProxyCtx

$sourceCtx ProxyItem targetCtx:MqContextC

top Copy a single-data-item from the sourceCtx to the targetCtx. → API: tcl_mqmsgque_MqContextC_ProxyItem

MqContextC - copy data from the read-data-package of the sourceCtx to the send-data-package of the targetCtx

The proxy-feature is used in a filter-setup to process-and-forward incoming data.

See also
MqDumpC

Example: A typical proxy-setup in pseudo C++ code

void myService () {
MqContextC *ftr = SlaveGetFilter(); // get the "slave" with id "1" (the filter)
...
ftr->SendSTART(); // start the FORWARD
while (ReadItemExists()) { // read ALL data from the ORIGINAL service-call
ProxyItem(ftr); // forward a SINGEL item from "this" to "ftr"
}
...
ftr->SendEND_AND_WAIT("MYTK"); // send the data.package to "ftr"
...
SendSTART(); // start the ANSWER
while (ftr->ReadItemExists()) { // read ALL data from the "MYTK" service-call
ftr->ProxyItem(this); // forward a SINGEL item from "ftr" to "this"
}
SendRETURN(); // answer the ORIGINAL service call
}
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]sourceCtxthe source of the copy
[in,out]targetCtxthe target of the copy
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqProxyForward MqServiceProxy MqServiceProxyCtx

MqContextC READ API

NAVI: top, up

MqContextC READ API ATOM

ReadTT read a PRIMITIVE TYPE from the read-data-package
ReadALL get a temporary MkBufferListC from all data in the read-data-package
ReadBFL get a temporary MkBufferListC from next list-item in the read-data-package
ReadBinaryR read a MkBinaryR from the read-data-package
ReadBUF get a temporary MkBufferC from the read-data-package
ReadHDL read the handle from the read-data-package
ReadLIST get all arguments as native list …
ReadLONG read the long native object from the read-data-package
ReadNEXT get the next argument as native object …
ReadStringR

read a MkStringR from the read-data-package

MqContextC READ API BLOCK

ReadL_END finish to extract a list-items from the read-data-package. …
ReadL_START start to extract a list-items from the read-data-package. …
ReadT_END finish to extract a longterm-transaction-item from the read-data-package. …
ReadT_START

start to extract a longterm-transaction-item from the read-data-package. …

MqContextC READ API MISC

ReadGetNextType get the type (MkTypeE) of the next Item in the read-data-buffer or "0" if not available
ReadGetNumItems get the number of items left in the read-data-package
ReadItemExists check if an item exists in the read-data-package
ReadUndo

undo the last MqContextC READ API function call …

MqContextC READ API DETAILS

C-API: MqContextC_ReadApi_C_API - MqContextC - extract data from an incoming read-data-package

A data-package is read in two different scenarios:

  • on a server to serve an incoming service-call from the client
  • on a client to process the return-data from a previous service-call

Reading data is a passive-task and the opposite of sending data, which is an active-task. Passive means that the reading process is triggered by an incoming-data-package and not by the software workflow or by the user.
There is a read function and some help functions for each basic type defined in MkBufferC .

Read-Safe
Each service-call has a private read-data-package. This means that during a service-call that is in progress, another service-call can be served without damaging the read-data-package of the current service-call.
Type-Safe
A data-item in a read-data-package is type safe, this mean that every read of a data-item have to match the data-type of the previous write. One exception is available, the cast from and to the string data-type (TYPE=C) is allowed.

Example from server.tcl read-safety: Make a nested service-call

  method Ot_CSV1 {} {

    # read the input-data from the CSV1-service-call
    # client → server
    set inI   [my ReadI32]
    incr inI

    # call the CSV2-service at the client, wait 10sec for timeout
    # server → client → server
    set retI  [my Send "Wt" 10 "CSV2:I@I" $inI]
    incr retI

    # answer the CSV1-service-call with the result from the CSV2-service-call
    # server → client
    my Send "R" "I" $retI
  }

MqContextC READ API ATOM

C-API: MqContextC_ReadApi_Atom_C_API - MqContextC - read a single-data-item outof a read-data-package

MkBufferListC [$ctx ReadALL ?val_inout:MkBufferListC="MK_NULL"?]

top get a temporary MkBufferListC from all data in the read-data-package … → API: tcl_mqmsgque_MqContextC_ReadALL

If the val_inout is "MK_NULL" than a temporary MkBufferListC is returned. If the val_inout is not "MK_NULL" than the memory of the val_inout is reused.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]val_inoutthe MkBufferListC - the storage of the input is reused
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqReadBFL
Attention
(do not free) The memory of the out/return value belongs to the called TclMqMsgque function and therefore never becomes "MK_NULL" for a non-error result.
For details on the out/return value, see: MkKernel_Storage_C_API.

MkBufferListC [$ctx ReadBFL]

top get a temporary MkBufferListC from next list-item in the read-data-package … → API: tcl_mqmsgque_MqContextC_ReadBFL

If the next item in the read-data-package is a list-item, (created with MqReadL_START and $ctx ReadL_END), only return this item. If the next item in the read-data-package is not a list-item than return an error. If you require all data in the read-data-package returned as single MkBufferListC than use MqReadALL.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]val_outthe MkBufferListC as return-value
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqReadALL
Attention
(do not free) The memory of the out/return value belongs to the called TclMqMsgque function and therefore never becomes "MK_NULL" for a non-error result.
For details on the out/return value, see: MkKernel_Storage_C_API.

binary [$ctx ReadBinaryR]

top read a MkBinaryR from the read-data-package … → API: tcl_mqmsgque_MqContextC_ReadBinaryR

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]val_outthe MkBinaryR to return
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

MqSendSTR

MkBufferC [$ctx ReadBUF]

top get a temporary MkBufferC from the read-data-package … → API: tcl_mqmsgque_MqContextC_ReadBUF

Return a temporary-data-item from the read-data-package. The lifetime of the MkBufferC is only the current callback up to the next read operation in the same parent-context. This object is owned by TclMqMsgque and must not be freed.

Example from server.tcl read and update a MkBufferC

        # START - ReadBUF - Example, read a buffer-object and append a string
        set buf [my ReadBUF]
        $buf AppendSTR "- a really log text to overwrite the already allocated space"
        my SendBUF $buf
        set i   [my ReadI32]
        my SendI32 [expr {$i+1}]
        rename $buf ""
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]val_outThe out-value of type MkBufferC. 1) It is an error if the out-value is "MK_NULL", 2. If there is an error, the out-value remains unchanged.
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Error Messages
  1. if ctx is "MK_NULL"
  2. if ctx is not connected
  3. if val_out is null
  4. if are no items to return
  5. if the data-package is corrupt
Attention
(do not free) The memory of the out/return value belongs to the called TclMqMsgque function and therefore never becomes "MK_NULL" for a non-error result.
For details on the out/return value, see: MkKernel_Storage_C_API.

MK_HDL [$ctx ReadHDL]

top read the handle from the read-data-package → API: tcl_mqmsgque_MqContextC_ReadHDL

See also
MqSendHDL, MK_HDL
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]val_outthe handle-object to read
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
this is NON portable

[list...] [$ctx ReadLIST]

top get all arguments as native list … → API: MqReadLIST_RT

The MqReadLIST is a function what interacts with the Target-Programming-Language (TPL) list-object.

There is no guarantee that a list-object will be available. Therefore, this function is an add-on and will only be implemented when possible.

Example from example/tcl/server.tcl start a WORKER using all arguments from the service-call.

# start worker with arguments from the service-call using the current executable
my SlaveWorker $id "WORKER" {*}[my ReadLIST] --name wk-cl-$id @ --name wk-sv-$id
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]val_outthe native list as return
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqReadBFL MqReadNEXT

long [$ctx ReadLONG]

top read the long native object from the read-data-package → API: tcl_mqmsgque_MqContextC_ReadLONG

on 64bit use a MqReadI64 and on 32bit use a MqReadI32

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]val_outthe native long object to read
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
this is NON portable

obj [$ctx ReadNEXT]

top get the next argument as native object … → API: MqReadNEXT_RT

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]val_outthe native object as return
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqReadLIST MqReadBUF

string [$ctx ReadStringR]

top read a MkStringR from the read-data-package … → API: tcl_mqmsgque_MqContextC_ReadStringR

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]val_outthe MkStringR to return
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

MqSendSTR

[$ctx ReadTT]

top

The ReadTT provide a single function for every PRIMITIVE TYPE

attributereturncommand

C-API :

int8[$ctx ReadI8]MqReadI8_RT
int16[$ctx ReadI16]MqReadI16_RT
int32[$ctx ReadI32]MqReadI32_RT
int64[$ctx ReadI64]MqReadI64_RT
string[$ctx ReadSTR]MqReadSTR_RT
binary[$ctx ReadBIN]MqReadBIN_RT
bool[$ctx ReadBOL]MqReadBOL_RT
float[$ctx ReadFLT]MqReadFLT_RT
double[$ctx ReadDBL]

MqReadDBL_RT

read a PRIMITIVE TYPE from the read-data-package

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]val_outthe value to read
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

MqContextC READ API BLOCK

C-API: MqContextC_ReadApi_Block_C_API - MqContextC - read a block-of-data outof a read-data-package

$ctx ReadL_END

top finish to extract a list-items from the read-data-package. … → API: tcl_mqmsgque_MqContextC_ReadL_END

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx ReadL_START ?buf:MkBufferC="MK_NULL"?

top start to extract a list-items from the read-data-package. … → API: tcl_mqmsgque_MqContextC_ReadL_START

Initialize the read with the current body-item or an optional MkBufferC. This command requires a final $ctx ReadL_END to finish the read.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]bufan optional MkBufferC as result from a previous RMqReadBUF call or "MK_NULL" to use the next item from the read-data-package.
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx ReadT_END

top finish to extract a longterm-transaction-item from the read-data-package. … → API: tcl_mqmsgque_MqContextC_ReadT_END

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx ReadT_START

top start to extract a longterm-transaction-item from the read-data-package. … → API: tcl_mqmsgque_MqContextC_ReadT_START

Initialize the read with the current-item or an optional MkBufferC. The current-item have to be the first item in the read-data-package. This command requires a final $ctx ReadL_END to finish the read.

Example from server.tcl read the results from a service-call with transaction-support

  method Ot_TRN2 {} {
    my variable i j
    my ReadT_START
    set i [my ReadI32]
    my ReadT_END
    set j [my ReadI32]
  }
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

MqContextC READ API MISC

C-API: MqContextC_ReadApi_Misc_C_API - MqContextC - various functions to work on a read-data-package

MkTypeE [$ctx ReadGetNextType]

top get the type (MkTypeE) of the next Item in the read-data-buffer or "0" if not available → API: tcl_mqmsgque_MqContextC_ReadGetNextType

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the type

int32 [$ctx ReadGetNumItems]

top get the number of items left in the read-data-package … → API: tcl_mqmsgque_MqContextC_ReadGetNumItems

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the number of items as integer

bool [$ctx ReadItemExists]

top check if an item exists in the read-data-package … → API: tcl_mqmsgque_MqContextC_ReadItemExists

Parameters
[in]ctxthe MqContextS instance to work on
Returns
boolean, true or false

$ctx ReadUndo

top undo the last MqContextC READ API function call … → API: tcl_mqmsgque_MqContextC_ReadUndo

Put the internal position-pointer to the start of the last read body-item. The next read function call will extract the same item again. Only one undo level is supported.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

MqContextC ROUTE API

NAVI: top, up
RouteCreate create/delete a routing-link between context an a service using route
RouteDelete delete a routing-link created with MqRouteCreate
RouteGetPath return the absolut route-connection-string up to the current ctx
RouteGetTree create an overview about all available routing-target and services …
RouteResolve return a list of all context belonging to ident
RouteTraverse

traverse a tree down and call service if available.

MqContextC ROUTE API DETAILS

C-API: MqContextC_RouteApi_C_API - 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 Service-Level-Routing is using a round-robin-proxy-service on the hub-context to forward an incoming package to the routing-target.
  • The Package-Level-Routing is using a routing-database to route the data on the package-level without a service involved.

The difference between Service-Level-Routing and Package-Level-Routing is the public versa private behaviour.

  • The Service-Level-Routing route EVERY package send to the hub-context using the service-token to the routing-target, this behaviour is called public.
  • The Package-Level-Routing route ONLY the package(s) from the creator (owner) of the route, this behaviour is called private.

Summary:

TCP/IP layer model

The TCP/IP model define the following layers (from: https://www.geeksforgeeks.org/tcp-ip-model/) :

Network Access Layer
This layer corresponds to the combination of Data Link Layer and Physical Layer of the OSI model. It looks out for hardware addressing and the protocols present in this layer allows for the physical transmission of data.
Internet Layer
This layer parallels the functions of OSI’s Network layer. It defines the protocols which are responsible for logical transmission of data over the entire network
The main protocols residing at this layer are :
  1. IP – stands for Internet Protocol and it is responsible for delivering packages from the source host to the destination host by looking at the IP addresses in the package headers. IP has 2 versions: IPv4 and IPv6. IPv4 is the one that most of the websites are using currently. But IPv6 is growing as the number of IPv4 addresses are limited in number when compared to the number of users.
  2. ICMP – stands for Internet Control Message Protocol. It is encapsulated within IP datagrams and is responsible for providing hosts with information about network problems.
  3. ARP – stands for Address Resolution Protocol. Its job is to find the hardware address of a host from a known IP address. ARP has several types: Reverse ARP, Proxy ARP, Gratuitous ARP and Inverse ARP.
Host-to-Host Layer
This layer is analogous to the transport layer of the OSI model. It is responsible for end-to-end communication and error-free delivery of data. It shields the upper-layer applications from the complexities of data.
The two main protocols present in this layer are :
  1. Transmission Control Protocol (TCP) – It is known to provide reliable and error-free communication between end systems. It performs sequencing and segmentation of data. It also has acknowledgment feature and controls the flow of the data through flow control mechanism. It is a very effective protocol but has a lot of overhead due to such features. Increased overhead leads to increased cost.
  2. User Datagram Protocol (UDP) – On the other hand does not provide any such features. It is the go-to protocol if your application does not require reliable transport as it is very cost-effective. Unlike TCP, which is connection-oriented protocol, UDP is connectionless.
Application Layer
This layer performs the functions of top three layers of the OSI model: Application, Presentation and Session Layer. It is responsible for node-to-node communication and controls user-interface specifications. Some of the protocols present in this layer are: HTTP, HTTPS, FTP, TFTP, Telnet, SSH, SMTP, SNMP, NTP, DNS, DHCP, NFS, X Window, LPD. Have a look at Protocols in Application Layer for some information about these protocols.
Protocols other than those present in the linked article are :
  1. HTTP and HTTPS – HTTP stands for Hypertext transfer protocol. It is used by the World Wide Web to manage communications between web browsers and servers. HTTPS stands for HTTP-Secure. It is a combination of HTTP with SSL(Secure Socket Layer). It is efficient in cases where the browser need to fill out forms, sign in, authenticate and carry out bank transactions.
  2. SSH – SSH stands for Secure Shell. It is a terminal emulations software similar to Telnet. The reason SSH is more preferred is because of its ability to maintain the encrypted connection. It sets up a secure session over a TCP/IP connection.
  3. NTP – NTP stands for Network Time Protocol. It is used to synchronize the clocks on our computer to one standard time source. It is very useful in situations like bank transactions. Assume the following situation without the presence of NTP. Suppose you carry out a transaction, where your computer reads the time at 2:30 PM while the server records it at 2:28 PM. The server can crash very badly if it’s out of sync.

LibMqMsgque layer model

The libmqmsgque layer model is an extension to the TCP/IP layer model.

TCP/IP Application Layer
This layer is used for the libmqmsgque protocol - The protocol is the "language" of the libmqmsgque
library. The layer is defined as protocol-message-format and as protocol-flow-format.
  1. protocol-message-format - Example from protocoll_mq.h this is the "syntax" of the protocol.
    struct HdrS {
    MK_STRB ID[4] ;
    MK_STRB native ;
    MK_STRB charA ;
    union HdrIU ctxId ;
    MK_STRB charS ;
    union HdrIU bdySize ;
    MK_STRB charO ;
    MK_STRB tok[HDR_TOK_LEN] ;
    MK_STRB charT ;
    union HdrIU transSId ;
    MK_STRB charR ;
    union HdrIU routeId ;
    MK_STRB charC ;
    MK_STRB hs ;
    MK_STRB charE ;
    MK_STRB tt ;
    MK_STRB charF ;
    };
    struct BdyS {
    MK_STRB ID[4] ;
    //MK_STRB charN ; ///< <TT>size: 1 .............. -> total: 4 .. -> character .. -> "+"</TT>
    union HdrIU numItems;
    MK_STRB charE ;
    };
    struct LtrS {
    MK_STRB ID[4] ;
    //MK_STRB charN ; ///< <TT>size: 1 .............. -> total: 4 .. -> character .. -> "+"</TT>
    MK_BINB ltrP[HDR_ID_SIZE] ;
    MK_STRB charE ;
    };
    #define LTR_SIZE (3 + 1 + HDR_ID_SIZE + 1)
    struct RouS {
    MK_STRB ID[4] ;
    //MK_STRB charN ; ///< <TT>size: 1 .............. -> total: 4 .. -> character .. -> "+"</TT>
    MK_BINB rouP[HDR_ID_SIZE] ;
    MK_STRB charE ;
    };
    #define ROU_SIZE (3 + 1 + HDR_ID_SIZE + 1)
    struct PackageS {
    struct HdrS hdr ;
    struct BdyS bdy ;
    };
  2. protocol-flow-format - this is the "grammatic" of the protocol.
LibMqMsgque Service Layer

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:

  • report error messages from the slave-context to the master-context
  • to create a slave-child-context if a master-child-context is created
  • to delete a slave-context if a master-context is deleted

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"

  • the master-context is a parent-context without a child-context available.
  • the master-context is a client-context or a server-context.
  • the link between the master-context and the slave-context is done using MqSlaveWorker or MqSlaveCreate

Definition of the "slave-context"

  • the slave-context is a parent-context without a child-context available.
  • the slave-context is a client-context.
  • the slave-context lifetime is controlled by the master-context.
  • the slave-context report all error-messages to the master-context.
  • the slave-context is identified by a unique-slave-id starting with 0.
  • a special form of a slave-context is a worker-context

Definition of the "worker-context"

  • the worker-context is a slave-context using the image of the master-context self.
  • the master-context can be a server-context or a client-context.
  • the worker-context is created using MqSlaveWorker
  • the worker-context is identified by a unique-slave-id starting with 0.

Definition of the "slave-id"

  • the slave-id is defined at enum MqSlaveE
  • a slave is identified in his master-context by a slave-id
  • the slave-id work like a defined well-known-port-number in /etc/services
  • the slave-id is an integer value with valid values > 0
  • it is a good practice to plan the usage of your slave-id(s)
  • slave
    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
    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 -- #
  • the loopback has always the slave-id = 0 .
  • the loopback has the same class as the parent, if reflection is not available the MqFactoryInitial is used.
  • the loopback is used to call a service on the same process or thread.
  • the loopback is a special filter without an additional process or thread to be started.
  • the loopback is only internal accessible
  • the service called by the loopback need the same attention as the service called by the filter, the context of the service is the loopback-context.
  • the loopback can call MqServiceCreate to create a new link between a service-token and a service-method, by default all services from the master-context (the owner of the loopback) are also accessible by the loopback.
  • in the service use MqSlaveGetMaster to get the master-context from the loopback-context.
  • Example from MyLoopServer.tcl create a new loop-server
    package require tclmsgque::MqMsgque
    namespace import tclmsgque::MqMsgque::*
    
    ::oo::class create MyLoopServer {
      superclass MqContextC
      export variable
    
      # factory startup
      constructor {{tmpl ""}} {
        my variable mydata;
        next $tmpl
        my ConfigSetServerSetup ServerSetup
        # set the "mydata" attribute to the master-context
        set mydata  "Hello World";
      }
    
      # service to serve all EXTERNAL requests for token "HLWO"
      method HLWO_srv {} {
        # get the "loopback" context
        set loop  [my SlaveGet LOOPBACK]
        # call the LOOP service on the SAME server
        $loop Send "W" "LOOP"
        # answer HLWO with string-return from LOOP
        my Send "R" "C" [$loop ReadSTR]
      }
    
      # service to serve all INTERNAL requests for token "LOOP"
      method LOOP_srv {} {
        # get the "master" context
        set master  [my SlaveGetMaster]
        # answer LOOP with data from MASTER->mydata attribute
        $master variable mydata
        my Send "R" "C" $mydata
      }
    
      # setup a server-context - called for every new server-context
      method ServerSetup {} {
        # EXTERNAL: link the "HLWO" service with "HLWO_srv"
        my ServiceCreate "HLWO" HLWO_srv
        # INTERNAL: link the "LOOP" service with "LOOP_srv"
        [my SlaveGet MQ_SLAVE_LOOPBACK] ServiceCreate "LOOP" LOOP_srv
      }
    }
    
    tclmsgque::MqMsgque Main {
    
      # create "MyLoopServer" factory... and the instance
      set srv   [[MqFactoryC Add MyLoopServer] New]
    
      try {
        $srv LinkCreate $argv
        $srv ProcessEvent MQ_WAIT_FOREVER
      } on error {} {
        $srv ErrorCatch
      } finally {
        $srv Exit
      }
    }
    

Performance analyse

The performance-test is created with:
  • pipe
    • Nhi1Exec perfclient.c --parent --wrk ? @ perfserver.c
  • spawn, fork, thread
    • Nhi1Exec -r=uds perfserver.c --spawn|fork|thread
    • Nhi1Exec -r=uds perfclient.c --parent --wrk ?
  • the number of workers are set with the –wrk option
  • the cpu is a xeon with 4/8
  • the performance is calculated as worker-context-created / time-in-sec with a ~2sec (default) measurement period.
performance-test code:
  • The test-setup is done as:
      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 
performance-test results:
  • results generated using the debug environment
    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 -

example (C++ syntax)

Route-Connection-String

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

*
|-header
|-GUI-|
frontend-| |-footer
|
|-DB
*

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)

Service-Layer-Routing

The LibMqMsgque-Service-Layer-Routing create proxy-services (MqServiceProxyRoundRobin ...) between frontend and footer. (example c++)

// 1. on "frontend" create a route to the service "MYSV" on the "footer" passing "GUI"
DOING: frontendCtx.RouteCreate("GUI/footer", "MYSV");
// 2. on "frontend" call the route using the "loopback" slave
DOING: frontendCtx.SlaveGet(MQ_SLAVE_LOOPBACK).Send("W", "MYSV:..@..", ..);
// 3. on "frontend/GUI" proxy "footer"
INTERNAL: frontendCtx.ServiceProxyRoundRobin("MYSV", GUICtx);
INTERNAL: GUICtx.ServiceProxyRoundRobin("MYSV", footerCtx);
// 4. on "footer" call the service "MYSV"
SETUP: footerCtx.ServiceCreate("MYSV", ...);
@ MQ_SLAVE_LOOPBACK
internal: the loopback-slave-id, (call my own services)

The MqRouteCreate will take the following action:

  1. create a round-robin-proxy on frontend and on GUI using service MYSV
  2. check if service MYSV is available on footer

Attention:

  1. With the proxy on frontend/GUI no other service with the name MYSV on frontend/GUI is possible and every service-call to frontend or GUI using the service MYSV will be redirected to the service MYSV on footer.
  2. The live-time of the Service-Layer-Routing is up to the next MqRouteDelete call using the same arguments. If the proxy-to-footer becomes invalid on a the GUI-context the routing-link will be recreated.
  3. The MqRouteCreate can be used multiple times with the same Route-Connection-String and service-token and overwrite=true to guarantee that a route is available.

Package-Layer-Routing

...

$ctx RouteCreate route:string service:string ?overwrite:bool=false?

top create/delete a routing-link between context an a service using route → API: tcl_mqmsgque_MqContextC_RouteCreate

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]routethe absolute or relative path to the target-context, if NULL or '\0' the current context is returned.
[in]servicethe service token on the target context
[in]overwriteif overwrite=false an error is raised if the service already exists.
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqRouteCreate, MqRouteDelete

$ctx RouteDelete route:string service:string ?overwrite:bool=false?

top delete a routing-link created with MqRouteCreate → API: tcl_mqmsgque_MqContextC_RouteDelete

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]routethe absolute or relative path to the target-context, if NULL or '\0' the current context is returned.
[in]servicethe service token on the target context
[in]overwriteif overwrite=false an error is raised if the service already exists.
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqRouteCreate, MqRouteDelete

string [$ctx RouteGetPath]

top return the absolut route-connection-string up to the current ctx … → API: tcl_mqmsgque_MqContextC_RouteGetPath

The absolut route-connection-string is the route starting at root (e.g. "/").

Attention
  • The path_out returned is owned by the loopback-slave -> do not free.
  • The path_out returned is only valid until the next call to the loopback-slave.
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]path_outthe return path or "MK_NULL" on error
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqRouteGetTree

MkBufferListC [$ctx RouteGetTree]

top create an overview about all available routing-target and services … → API: tcl_mqmsgque_MqContextC_RouteGetTree

The data returned is a list of "ROUTE|IDENT|SERVICE,..." string items.

Example from MyWorker.tcl get the "Tree" as service

    void TREE () {
      Send("R", "L", RouteGetTree());
    }

Example from tests/route2.test -> route2-1-0

  • Get a list of all services on all servers reachable by test-context.
 /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:

  • root is cl-0
  • multiple other clients, parallel to cl-0, are reachable: cl-0-....
  • multiple servers involved: sv...
  • multiple services reachable: FINL,FOID,HLWO,HLWS,PATH,TREE
Attention
  • The list-object returned is owned by MqRouteGetTree and is only valid until the next call to MqRouteGetTree.
  • On error the list-object will be empty.
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]treeP_outthe tree-object with the results…
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqRouteGetPath

[MqContextC...] [$ctx RouteResolve ident:string ?retnum:int32=-1?]

top return a list of all context belonging to ident … → API: tcl_mqmsgque_MqContextC_RouteResolve

This api-proc is used to return all context with MqLinkS::targetIdent == ident .

In addition the following special ident are recognized:

  • EMPTY or "MK_NULL" or DOT=. or ClassIdentGet -> The loopback-slave
  • DOUBLE-DOT=.. -> On the server the server-context and on the slave the master-context

Example from server.tcl in a service call return all connected targets

        foreach myctx [my RouteResolve [my ReadSTR]] {
          my SendSTR [$myctx LinkGetTargetIdent]
        }
See also
MqRouteTraverse
Attention
1. (do not free) The memory of the out/return value belongs to the called TclMqMsgque function and therefore never becomes "MK_NULL" for a non-error result.
For details on the out/return value, see: MkKernel_Storage_C_API.
2. The maximun number of items in the return-array is MQ_ROUTE_CTX_MAX .
3. (C-API) The last item in the return-array is always a "MK_NULL".
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]identThe identifer to search the context for
[in]retnumThe maximum number-of-items accepted in the result-array, if <0 than MQ_ROUTE_CTX_MAX is used.
Returns
An array of MqContextC, the last item is a "MK_NULL".

$ctx RouteTraverse service:string ?args:MkBufferListC...="MK_NULL"?

top traverse a tree down and call service if available. → API: tcl_mqmsgque_MqContextC_RouteTraverse

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.

Note
- Internal the service is called using the loopback-slave context, be aware to call MqSlaveGetMaster first to start on the master-context.
- It is not an error if a service does not exists on a specific route starting from ctx.

The following internal tasks are performed ( C notation ) :

  1. Call MqSendEND_AND_WAIT on the MQ_SLAVE_LOOPBACK if the service exists.
  2. Call MqRouteResolve with "*" to get all routes starting from the ctx up to MQ_ROUTE_CTX_MAX routes :
    int flag[MQ_ROUTE_CTX_MAX] = {0};
    MQ_CTX_A rr = MqRouteResolve(ctx, "*", -1);
  3. Call MqRouteTraverse on every route from rr with :
    // call for a "routing" setup/check using all rrctx from "rr->list" in parallel.
    // -> use "flag" to check if a callback was called.
    for (int i=0; i<rr.size; i++) {
    MQ_CTX rrctx = rr.data[i];
    if (MQ_IS_LOOPBACK(rrctx)) continue;
    if (MQ_IS_SERVER(rrctx) && ctx == rrctx) continue;
    MqSendSTART_E(rrctx);
    MqSendSTR_E(rrctx,service);
    MqSendBFL_E(rrctx,args);
    if (MkErrorCheckI(MqSendEND_AND_CALLBACK(rrctx,"_RTR",sRouteTool_CB,&flag[i],NULL,MK_TIMEOUT_DEFAULT))) {
    pContextErrorCopy ( ctx,rrctx);
    goto error;
    }
    }
    The sRouteTool_CB set the flag[i] to 1 to signal done.
  4. Call MqProcessEvent to wait for an answer and check on error with timeout MK_TIMEOUT_DEFAULT.
    // wait to finish all "calls" from obove - using "flag" to check if wait is still required.
    for (int i=0; i<rr.size; i++) {
    MQ_CTX rrctx = rr.data[i];
    if (MQ_IS_LOOPBACK(rrctx)) continue;
    if (MQ_IS_SERVER(rrctx) && ctx == rrctx) continue;
    while (flag[i] == 0) { // just be shure the CB is still "open=0"
    if (MkErrorCheckI(MqProcessEvent(rrctx, MQ_WAIT_OWN, MK_TIMEOUT_DEFAULT))) {
    MqContextErrorCopy (ctx,rrctx);
    goto error;
    }
    }
    }
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]servicethe service token to be called
[in]argscommand-line-arguments passed as arguments to the service call

MqContextC SEND API

NAVI: top, up

MqContextC SEND API ATOM

SendTT MqContextC - append a native PRIMITIVE TYPE value to the send-data-package
SendBFL append a MkBufferListC object to the send-data-package object …
SendBinaryR append a MkBinaryR object to the send-data-package. …
SendBUF append a MkBufferC object to the send-data-package object …
SendBUS_FLAT append a MkBufferStreamC object to the send-data-package object …
SendHDL send the handle to the send-data-package
SendL_FLAT append a MkBufferListC object as flat list of items to the send-data-package object …
SendLONG send the long native object to the send-data-package
SendStringR

MqContextC - append a native PRIMITIVE TYPE value to the send-data-package

MqContextC SEND API BASICS

SendEND MqContextC - finish the send-data-block and call synchronous/asynchronous a remote-service
SendEND_AND_CALLBACK finish the send-data-block, call the remote service, do not-wait for the result but expect the result on a callback
SendEND_AND_SUB finish the send-data-block, call the remote service, do wait for the result and expect multiple sub-results on a callback
SendEND_AND_TRANSACTION finish the send-data-block, call the remote service to do a longterm-transaction-call
SendEND_AND_WAIT finish the send-data-block, call the remote service and wait for result…
SendSTART initialize the send-data-package. …
SendSYNC

garantee that all pending asynchronous-service-calls are processed. …

MqContextC SEND API BLOCK

SendL_END finish to append an embedded body-list-item to the send-data-package. …
SendL_START start to append an embedded body-list-item to the send-data-package. …
SendT_END closed a longterm-transaction-item
SendT_START

open a longterm-transaction-item

MqContextC SEND API RETURN

SendERROR send the data from the MkErrorC to the link target . …
SendRETURN MqContextC - finish the send-data-block on the server and optional return the results. …
SendRETURN_SUB

return Sub-Data-Blocks required by MqSendEND_AND_SUB

MqContextC SEND API DETAILS

C-API: MqContextC_SendApi_C_API - MqContextC - construct an outgoing send-data-package

A data-package is send in two different scenarios:

  1. on a client to call a service on the server
  2. on a server to answer a service call from the client

Sending data is an active task and the opposite of reading data, which is a passive task. Active means that the send process is triggered by the software workflow or by the user.
For each basic type defined in MkBufferC, there is a send function and some help functions.

Send-Safe
Sending data is an atomic task and must not be interrupted between MqSendSTART and MqSendEND. The MqContextC HIGH API is uninterruptible by design.
Basic rule: process first and send all data last.

If timeout != 0 is used, the application enters the event loop and waits in the current process or thread for timeout seconds until the service call is finished.
While waiting for a result, the application can continue to work on other events that are in the same or in a different process or thread.

Recursion-Safe
If another-service-call arrives while waiting for a response from a previous-service-call, the previous-service-call will NOT end until processing of the other-service-call is complete.

Example-1: a service call, send and read a data-package

On a client: perform a service call

send the service-call MqSendSTARTSendTT... → MqSendEND_AND_WAIT
read the result packageReadTT... → ...

on a server: answer a service call

read the service-call ReadTT... → ...
send the result packageMqSendSTARTSendTT... → MqSendRETURN

Important in the code from above is the last command MqSendEND_AND_WAIT because this is just one of five possibilities:

command synchron database result
MqSendEND no no no
MqSendEND_AND_WAIT yes no single return data
MqSendEND_AND_SUB yes no multiple return data
MqSendEND_AND_CALLBACK no no single return data
MqSendEND_AND_TRANSACTION no yes two return data

To send a data-package is one task, to send it to the right receiver is an other one. The right receiver is identified using the token parameter argument. This parameter have to be a 4 character string. You'll probably ask "why 4?" the answer is that this string should be "human" readable and easy to "compare". As solution this string is mapped to a 4 byte integer used to find the proper key/value entry in the service-hash-table on the server. (in short: to search an integer is much faster as to search a string)

Example-2: (in C) At the client, calling the service and wait for an answer

...
enum MkErrorE MyServiceCall(MQ_CTX const ctx) {
// ... do some work
MqSendSTART_E(ctx); // init the Send-Buffer object
MqSendI32_E(ctx,int_value); // 1. argument: a MK_I32 value
MqSendSTR_E(ctx,"num:01"); // 2. argument: a MK_STRN value
MqSendBIN_E(ctx,mypicture,size); // 3. argument: a MK_BIN picture of size length
MqSendEND_AND_WAIT_E(ctx,"SRV1",60); // call service "SRV1" and wait max 60sec for the results
// ... get the results
MK_I32 retI = MqReadI32_e(ctx); // expect ONE integer as result
// ... do some work
return MK_OK;
error: // default error-handler
return MkErrorStack_1X(ctx); // on error, build up the error-stack
}
#define error
#define MkErrorStack_1X(...)
MkErrorE
MK_OK
signed int MK_I32
#define MqReadI32_e(...)
#define MqSendSTR_E(...)
#define MqSendI32_E(...)
#define MqSendBIN_E(...)
#define MqSendSTART_E(...)
#define MqSendEND_AND_WAIT_E(...)
PUBLIC data structure for the tclmqmsgque-specific-data

... or using the MqContextC HIGH API

...
enum MkErrorE MyServiceCall(MQ_CTX const ctx) {
// ... do some work
MqSend_E(ctx, "W", "SRV1:ICB", int_value, "num:01", mypicture, size);
// ... get the results
MK_I32 retI = MqReadI32_e(ctx); // expect ONE integer as result
// ... do some work
return MK_OK;
error: // default error-handler
return MkErrorStack_1X(ctx); // on error, build up the error-stack
}
#define MqSend_E(...)

Example-3: (in C) At the server, answer the service call

...
static MkErrorE SRV1(MQ_CTX const ctx, MK_PTR data) { // the name "SRV1" can be free chosen
// ... do some work
MK_I32 myInt = MqReadI32_e(ctx); // read a MK_I32 value
MK_STRN myStr = MqReadSTR_e(ctx); // read a MK_STR value
MK_BUF myPic = MqReadBUF_e(ctx); // read a MkBuffer64S object to store the picture data
// ... do some work
MqSendSTART_E(ctx); // init the Send-Buffer object
MqSendI32_E(ctx,int_ret); // return argument: a MK_I32 value
error: // something is wrong, error back
return MqSendRETURN(ctx); // send the package as an answer of a previous service-call
}
MK_PTRB * MK_PTR
const MK_STRB * MK_STRN
#define MqReadBUF_e(...)
#define MqReadSTR_e(...)

... or using the MqContextC HIGH API

...
static MkErrorE SRV1(MQ_CTX const ctx, MK_PTR data) { // the name "SRV1" can be free chosen
// ... do some work
MK_I32 myInt = MqReadI32_e(ctx); // read a MK_I32 value
MK_STRN myStr = MqReadSTR_e(ctx); // read a MK_STR value
MK_BUF myPic = MqReadBUF_e(ctx); // read a MkBuffer64S object to store the picture data
// ... do some work
return MqSend(ctx, "R", "I", int_ret); // send the package as an answer of a previous service-call
}

MqContextC SEND API ATOM

C-API: MqContextC_SendApi_Atom_C_API - MqContextC - append a native PRIMITIVE TYPE value to the send-data-package

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]valthe value to appending
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx SendBFL val:MkBufferListC

top append a MkBufferListC object to the send-data-package object … → API: tcl_mqmsgque_MqContextC_SendBFL

The items of the list are send as list using MqSendL_START and MqSendL_END.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]valthe pointer to an MkBufferListC object to send
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
If val == NULL an empty binary (size=0) will be send.
See also
MqSendL_FLAT

$ctx SendBinaryR val:binary

top append a MkBinaryR object to the send-data-package. … → API: tcl_mqmsgque_MqContextC_SendBinaryR

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]valthe value to appending
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
If val == NULL an empty byte-array ([]) will be send.

$ctx SendBUF val:MkBufferC

top append a MkBufferC object to the send-data-package object … → API: tcl_mqmsgque_MqContextC_SendBUF

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]valthe value to appending
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
If val == NULL an error is raised.

$ctx SendBUS_FLAT val:MkBufferStreamC

top append a MkBufferStreamC object to the send-data-package object … → API: tcl_mqmsgque_MqContextC_SendBUS_FLAT

The items of the stream are send flast as the stream is appended to the send-data-package.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]valthe pointer to an MkBufferStreamC object to send
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
If val == NULL an empty binary (size=0) will be send.
See also
MqSendL_FLAT

$ctx SendHDL val:MK_HDL

top send the handle to the send-data-package → API: tcl_mqmsgque_MqContextC_SendHDL

See also
MqReadHDL, MK_HDL
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]valthe handle-object to send
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
this is NON portable

$ctx SendL_FLAT val:MkBufferListC

top append a MkBufferListC object as flat list of items to the send-data-package object … → API: tcl_mqmsgque_MqContextC_SendL_FLAT

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]valthe pointer to an MkBufferListC object to send
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqSendBFL

$ctx SendLONG val:long

top send the long native object to the send-data-package → API: tcl_mqmsgque_MqContextC_SendLONG

on 64bit use a MqSendI64 and on 32bit use a MqSendI32

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]valthe native long object to send
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
this is NON portable
See also
MqReadLONG

$ctx SendStringR val:string

top MqContextC - append a native PRIMITIVE TYPE value to the send-data-package … → API: tcl_mqmsgque_MqContextC_SendStringR

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]valthe value to appending
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
If val == NULL the string "MK_NULL" will be send.
See also
MqReadSTR

$ctx SendTT val:int8

top

The SendTT provide a single function for every PRIMITIVE TYPE

attributereturncommand

C-API :

$ctx SendI8 val:int8MqSendI8_RT
$ctx SendI16 val:int16MqSendI16_RT
$ctx SendI32 val:int32MqSendI32_RT
$ctx SendI64 val:int64MqSendI64_RT
$ctx SendSTR val:stringMqSendSTR_RT
$ctx SendBIN val:binaryMqSendBIN_RT
$ctx SendBOL val:boolMqSendBOL_RT
$ctx SendFLT val:floatMqSendFLT_RT
$ctx SendDBL val:double

MqSendDBL_RT

MqContextC - append a native PRIMITIVE TYPE value to the send-data-package

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]valthe value to appending
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

MqContextC SEND API BASICS

C-API: MqContextC_SendApi_Basics_C_API - MqContextC - finish the send-data-block and call synchronous/asynchronous a remote-service

calling a remote service and wait timeout seconds for an result. If timeout == 0 it is an asynchronous-service-call and if the timeout > 0 it is a synchronous-service-call.

service-call blocking timeout
synchronous yes timeout > 0
asynchronous no timeout == 0

blocking mean waiting max timeout seconds to finishing the service-call:

  • If the service-call is finished in less than timeout seconds… the results are available and can be processed.
  • If the service-call is NOT finished in timeout seconds… an timeout-error is created and the transaction will be canceled.

If an error was raised on the server during the service-processing… the following error-handling will be available

  1. on a synchronous-service-call the error will be the result of the service-call
  2. on a asynchronous-service-call with callback the error will be the result of the callback
  3. on a asynchronous-service-call without callback the error will be send asynchronous from the server to the client . On the client the error will be raised on the NEXT event-handlng-command or as background-error if the MqSetupS::BgError function was defined.
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
[in]timeoutin seconds until a timeout-error is raised (possible values like ProcessEvent) (MK_TIMEOUT_DEFAULT=0)
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqSendSYNC

$ctx SendEND token:string[4] ?timeout:MkTimeoutE|int32=DEFAULT?

top MqContextC - finish the send-data-block and call synchronous/asynchronous a remote-service … → API: tcl_mqmsgque_MqContextC_SendEND

calling a remote service and wait timeout seconds for an result. If timeout == 0 it is an asynchronous-service-call and if the timeout > 0 it is a synchronous-service-call.

service-call blocking timeout
synchronous yes timeout > 0
asynchronous no timeout == 0

blocking mean waiting max timeout seconds to finishing the service-call:

  • If the service-call is finished in less than timeout seconds… the results are available and can be processed.
  • If the service-call is NOT finished in timeout seconds… an timeout-error is created and the transaction will be canceled.

If an error was raised on the server during the service-processing… the following error-handling will be available

  1. on a synchronous-service-call the error will be the result of the service-call
  2. on a asynchronous-service-call with callback the error will be the result of the callback
  3. on a asynchronous-service-call without callback the error will be send asynchronous from the server to the client . On the client the error will be raised on the NEXT event-handlng-command or as background-error if the MqSetupS::BgError function was defined.
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
[in]timeoutin seconds until a timeout-error is raised (possible values like ProcessEvent) (MK_TIMEOUT_DEFAULT=0)
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqSendSYNC

$ctx SendEND_AND_CALLBACK token:string[4] callback:callable ?timeout:MkTimeoutE|int32=DEFAULT?

top finish the send-data-block, call the remote service, do not-wait for the result but expect the result on a callback … → API: tcl_mqmsgque_MqContextC_SendEND_AND_CALLBACK

This function will never block and return immediately. Usually multiple MqSendEND_AND_CALLBACK are send and finally multiple MqProcessEvent are called to wait for the results.

Example from route_mq.c (C) call a service using a callback

int i;
int flag[MQ_ROUTE_CTX_MAX] = {0};
// call for a "routing" setup/check using all rrctx from "rr->list" in parallel.
// -> use "flag" to check if a callback was called.
for (i=0; i<rr->num; i++) {
MQ_CTX rrctx = rr->list[i];
MqSendSTART_E(rrctx);
MqSendSTR_E(rrctx,routeCUR);
MqSendSTR_E(rrctx,service);
MqSendBOL_E(rrctx,isCreate);
MqSendBOL_E(rrctx,overwrite);
if (MkErrorCheckI(MqSendEND_AND_CALLBACK(rrctx,"_ROU",sRouteTool_CB,&flag[i],NULL,MK_TIMEOUT_DEFAULT))) {
MqContextErrorCopy ( ctx,rrctx);
goto error;
}
}
// wait to finish all "calls" from obove - using "flag" to check if wait is still required.
for (i=0; i<rr->num; i++) {
MQ_CTX rrctx = rr->list[i];
while (flag[i] == 0) { // just be shure the CB is still "open=0"
if (MkErrorCheckI(MqProcessEvent(rrctx, MQ_WAIT_OWN, MK_TIMEOUT_DEFAULT))) {
MqContextErrorCopy ( ctx,rrctx);
goto error;
}
}
}

Be aware of the followig limitatitions if multiple MqSendEND_AND_CALLBACK are called with different ctx:

See also
MqRouteTraverse
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
[in]fCallthe function to process the service-call results
[in]callbacka user defined additional data-argument for the callback function (C-API only)
[in]fFreethe function to free the data-argument after use (C-API only)
[in]timeoutin seconds until a timeout-error is raised (possible values like ProcessEvent) (MK_TIMEOUT_DEFAULT= 0)
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Note
It is a good-practice to protect a bulk of asyncrone-service-calls with a MqSendSYNC or with a MqProcessEvent and MQ_WAIT_OWN .
MqSendEND_AND_CALLBACK : callback signature
1. The *service-ctx* is the *context* for which the service was defined.
2. If the *callback* is **not** an instance of the calling *context*, the *service-ctx* is added as an argument.
callback-args := service-ctx:MqContextC[in]
[static] proc callback { callback-args ?additional-args...? } ...
[own] ::oo::class create XXX {
superclass MqContextC
method callback { ?additional-args...? } ...
[instance] ::oo::class create YYY {
method callback { callback-args ?additional-args...? } ...
[class] ::oo::class create ZZZ {
self method callback { callback-args ?additional-args...? } ...
read more at: Callback signature

$ctx SendEND_AND_SUB token:string[4] callback:callable ?timeout:MkTimeoutE|int32=DEFAULT?

top finish the send-data-block, call the remote service, do wait for the result and expect multiple sub-results on a callback … → API: tcl_mqmsgque_MqContextC_SendEND_AND_SUB

The goal of this service-call is, to split a big data-block into multiple pieces. A typical solution would be a database-application doing a select and sending EVERY row as a $ctx SendRETURN_SUB. At the end ONE final and EMPTY $ctx SendRETURN is used to delete the open transaction and finish the service call.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
[in]fCallthe function to process the service-call results
[in]callbacka user defined additional data-argument for the callback function (C-API only)
[in]fFreethe function to free the data-argument after use (C-API only)
[in]timeoutin seconds until a timeout-error is raised (possible values like ProcessEvent) (MK_TIMEOUT_DEFAULT=MK_TIMEOUT_USER)
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
By default, the callback for the last packet ( $ctx SendRETURN) is only called if the packet contains a data-item or on an error. If the packet is empty, only the transaction is closed.
See also
MqSendEND_AND_WAIT MqSendEND_AND_CALLBACK MqSendRETURN_SUB MqSendRETURN
MqSendEND_AND_SUB : callback signature
1. The *service-ctx* is the *context* for which the service was defined.
2. If the *callback* is **not** an instance of the calling *context*, the *service-ctx* is added as an argument.
callback-args := service-ctx:MqContextC[in]
[static] proc callback { callback-args ?additional-args...? } ...
[own] ::oo::class create XXX {
superclass MqContextC
method callback { ?additional-args...? } ...
[instance] ::oo::class create YYY {
method callback { callback-args ?additional-args...? } ...
[class] ::oo::class create ZZZ {
self method callback { callback-args ?additional-args...? } ...
read more at: Callback signature

$ctx SendEND_AND_TRANSACTION token:string[4] callback:string[4] ?timeout:MkTimeoutE|int32=DEFAULT?

top finish the send-data-block, call the remote service to do a longterm-transaction-call … → API: tcl_mqmsgque_MqContextC_SendEND_AND_TRANSACTION

A longterm-transaction is a service-call with guaranteed delivery. guaranteed mean that the transaction is using the MqContextC STORAGE API to keep every step persistent being able to recover a step if something unexpected happen.

To link the result with the calling-environment a private transaction-item is used to save the calling-environment to the local-storage. If the local-storage is persistent, the calling-environment will even survive an application restart.
If the result from the public service-call arrives, the transaction-item will be extracted from the result and the private calling-environment will be initialized from the local-storage.

To create a persistent-transaction the MqContextC STORAGE API have to be setup as persistent. By default, an in-memory MqContextC STORAGE API is used.

The longterm-transaction-call has TWO results…

  • the FIRST result is a acknowledge that the longterm-transaction was stored in the remote database
  • the SECOND result is the result of the service-call

In difference to MqSendEND_AND_WAIT and MqSendEND_AND_CALLBACK a longterm-transaction-call have to survive an application restart. To achieve this goal… two features have to be available to process the results:

transaction-item

The transaction-item is the entry-id from the local internal database and is the public handle of the private data. If the transaction-item-private-data should be persistent (survive an application restart) the internal database have to be persistent using the Storage option.
The transaction-item-private-data requires a MqSendT_STARTMqSendT_END at the beginning of the send-data-package.
The list of data-items in the transaction-item-private-data have to be provided by the programmer and is used to initialise the environment in the callback (for example an external database-entry-id).
In the transaction-callback the transaction-item-private-data have to be extracted with MqReadT_STARTMqReadT_END at the beginning of the read-data-package.

transaction-callback

The transaction-callback have to be a MqContextC_ServiceApi_Identifer defined with MqServiceCreate in the application setup code (like IServerSetup) and have to be available after an application restart.

If an error is raised on the server during the database-insert the function will return this error immediately. During waiting for the return the event-loop is used to process other events. Use IEvent to add your tasks into the event loop.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
[in]callbackthe MqContextC_ServiceApi_Identifer of the MqContextC_ServiceApi_Callback
[in]timeoutin seconds until a timeout-error is raised (possible values like ProcessEvent) (MK_TIMEOUT_DEFAULT=MK_TIMEOUT_USER)
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

Example from MyTransaction.tcl make a logterm-transaction-call using the LOW and the HIGH api

package require tclmsgque::MqMsgque
namespace import tclmsgque::MqMsgque::*
namespace import tclmsgque::MkKernel::*

proc callback {ctx} {
  $ctx ReadT_START
  set myPrivateHandle [$ctx ReadSTR]
  $ctx ReadT_END
  set myServiceResult [$ctx ReadI32]

  puts "myPrivateHandle=$myPrivateHandle, myServiceResult=$myServiceResult"
}

# setup the client-context
set ctx [MqContextC new]

try {

  $ctx ConfigSetName "MyTransaction"

  # setup commandline arguments used for parsing
  set args [MkBufferListC CreateLA {*}$argv]

  # check if the '--token' option is available, default "SRVC"
  set token [$args CheckOptionSTR "--token" "SRVC"]
   
  # connect to the server
  $ctx LinkCreate $args
   
  # register callback
  $ctx ServiceCreate CLB1 callback
   
  # send block using the LOW-Api
  $ctx SendSTART
  $ctx SendT_START
  $ctx SendSTR "Privat_Data_1"
  $ctx SendT_END
  $ctx SendI32 11111
  $ctx SendEND_AND_TRANSACTION $token CLB1
   
  # send block using the HIGN-Api -> same as above, but shorter
  $ctx Send "T" CLB1 "$token:(C)I" "Privat_Data_2" 22222
   
  # now we wait for exact ONE result of the $ctx
  $ctx ProcessEvent MQ_WAIT_OWN

} on error {} {
  $ctx ErrorCatch
} finally {
  $ctx Exit
}

$ctx SendEND_AND_WAIT token:string[4] ?timeout:MkTimeoutE|int32=DEFAULT?

top finish the send-data-block, call the remote service and wait for result… → API: tcl_mqmsgque_MqContextC_SendEND_AND_WAIT

If an error is raised on the server during the service-processing the function will return this error immediately. During waiting for the return the event-loop is used to process other events. Use IEvent to add your tasks into the event loop.

See also
MqRouteTraverse
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
[in]timeoutin seconds until a timeout-error is raised (possible values like ProcessEvent) (MK_TIMEOUT_DEFAULT=MK_TIMEOUT_USER)
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx SendSTART

top initialize the send-data-package. … → API: tcl_mqmsgque_MqContextC_SendSTART

This function must be the first statement in a send-data-block.

If the socket is closed or failed, the connection is established with a MqLinkConnect.
Note that during MqLinkConnect the event-loop is called and your read-data-package may be invalid.

‍It is recommended to perform all READ operations first and then all SEND operations.

From MqSendSTART to MqSendEND is a send-data-block and no event-loop action is allowed between them.

‍The event-loop could modify the already started send-data-package and corrupt the data.

Note
  • There is only one send-data-package per context.
  • You should assume that any meta-function-call can enter the event-loop.
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx SendSYNC

top garantee that all pending asynchronous-service-calls are processed. … → API: tcl_mqmsgque_MqContextC_SendSYNC

The asynchronous-service-call is defined at: MqContextC_ServiceApi_C_API.

All service-calls to a specific ctx are queued in a service-call-pipeleine. The synchronous-service-call is blocking the service-call-pipeleine until the synchronous-service-call is finished. The asynchronous-service-call does NOT blocking the pipeline and so all asynchronous-service-call are processed in parallel. The MqSendSYNC is used if multiple asynchronous-service-calls are done to a single ctx and this ctx should be blocked until all asynchronous-service-calls are finished. The MqSendSYNC is just an normal blocking synchronous-service-call which is only finished after all asynchronous-service-calls are finished.

Example from perfclient.c sending a bulk of asynchronous-sevice-requests

StatTimerSP itemT = StatCreate (mqctx,sec,num);
{
StatCtxSP stat = StatCtxCreate (mqctx, "--send");
// init
PerfSendPackageStart(mqctx,9999);
MqSendEND_E (mqctx, "RDUL", 0);
// test
StatInit (itemT);
// TEST: start as many as possible asyncron-service-calles in "itemT" intervall.
while (StatCheck(itemT)) {
PerfSendPackageStart(mqctx, StatCount(itemT));
MqSendEND_E (mqctx, "RDUL", 0);
}
// just sync with the server
StatCtxCalc (stat, itemT, -1);
StatCtxPrint (stat);
StatCtxDelete (&stat);
}

The last MqSendSYNC garantee the all previous asynchronous-service-calls are finished.

MqContextC SEND API BLOCK

C-API: MqContextC_SendApi_Block_C_API - MqContextC - a wrapper to send a list-block or a transaction-block

start to append an embedded body-list-item to the send-data-package. …

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Example
Create a body-list-item in C
MqSendL_START(send); // start a list-item
MqSendI32(send,myInt); // first list-sub-item
MqSendSTR(send,"myString"); // second list- sub-item
// ... do additional MqSend?
MqSendL_END(send); // finish a list-item

$ctx SendL_END

top finish to append an embedded body-list-item to the send-data-package. … → API: tcl_mqmsgque_MqContextC_SendL_END

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx SendL_START

top start to append an embedded body-list-item to the send-data-package. … → API: tcl_mqmsgque_MqContextC_SendL_START

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Example
Create a body-list-item in C
MqSendL_START(send); // start a list-item
MqSendI32(send,myInt); // first list-sub-item
MqSendSTR(send,"myString"); // second list- sub-item
// ... do additional MqSend?
MqSendL_END(send); // finish a list-item

$ctx SendT_END

top closed a longterm-transaction-item … → API: tcl_mqmsgque_MqContextC_SendT_END

finish a setup-block started with MqSendT_START. read more at MqSendEND_AND_TRANSACTION.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx SendT_START

top open a longterm-transaction-item … → API: tcl_mqmsgque_MqContextC_SendT_START

Every longterm-transaction-item have to be closed with MqSendT_END. Between MqSendT_START and MqSendT_END, a non specified number of other items can be added. These items are saved in a local database (in-memory or file-based) and the rowid is send as transaction-id to the link-target. By Default only the in-memory-database is used. To switch to a file-based database use the MqStorageOpen function.

Example from server.tcl make a service-call with transaction-support

  method Ot_TRNS {} {
    my variable i j
    my Send "T" TRN2 "ECOI:(I)I" 9876 [my ReadI32]
    my ProcessEvent MQ_WAIT_ONCE
    my Send "R" "II" $i $j
  }
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

MqContextC SEND API RETURN

C-API: MqContextC_SendApi_Return_C_API - MqContextC - finish the send-data-block on the server and optional return the results. …

Every service-handler have to use this function at the end to return the results or the error. If an error is returned the local MkErrorC is reset. The following behaviour is used:

  • if a shortterm transaction is ongoing this function return the data or the error to the link target
  • if the answer does not return any data no previous MqSendSTART is required.
  • if no transaction is ongoing this function does just return. If an error is available report an asynchronous error to the link target.
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx SendERROR

top send the data from the MkErrorC to the link target . … → API: tcl_mqmsgque_MqContextC_SendERROR

If an error is available the error-number and the error-text is send to the link target. After send the error is reset. This function only raise an error if the sending self fails or the MkErrorDEFAULT is set and the ctx is a client-context.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx SendRETURN

top MqContextC - finish the send-data-block on the server and optional return the results. … → API: tcl_mqmsgque_MqContextC_SendRETURN

Every service-handler have to use this function at the end to return the results or the error. If an error is returned the local MkErrorC is reset. The following behaviour is used:

  • if a shortterm transaction is ongoing this function return the data or the error to the link target
  • if the answer does not return any data no previous MqSendSTART is required.
  • if no transaction is ongoing this function does just return. If an error is available report an asynchronous error to the link target.
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx SendRETURN_SUB

top return Sub-Data-Blocks required by MqSendEND_AND_SUB … → API: tcl_mqmsgque_MqContextC_SendRETURN_SUB

Every service-handler CAN use this function at the end of a data block if the caller used MqSendEND_AND_SUB to initiate the service call. MqSendEND_AND_SUB will block until ithe final $ctx SendRETURN was send.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

MqContextC SERVICE API

NAVI: top, up
ServiceCreate create a link between a service-token and a service-callback
ServiceDelete delete a service. …
ServiceIsTransaction check if the ongoing-service-call belongs to a transaction …
ServiceProxy create a service to link a master-context with a slave-context. …
ServiceProxyCtx same as MqServiceProxy but use an MqContextC as input.
ServiceProxyCtxExists check if service who belongs to token is a proxy-service
ServiceProxyRoundRobin create a proxy-service using Round-Robin as load-balancer …
ServiceStorage setup a service listen on a MqContextC_ServiceApi_Identifer and save all read-data-package into the STORAGE
ServiceTokenCheck in an ongoing-service-call check if the current MqContextC_ServiceApi_Identifer is token
ServiceTokenExists check if the MqContextC_ServiceApi_Identifer token is defined as ctx service …
ServiceTokenGet

in an ongoing-service-call get the current MqContextC_ServiceApi_Identifer

MqContextC SERVICE API DETAILS

C-API: MqContextC_ServiceApi_C_API - MqContextC - create and manage a service …

To provide a service is the main purpose of a server and the main-purpose of a client/server connection is to call a service and to process the result.
A service can be defined on the server or on the client. On the server a service can be initial setup with IServerSetup method and finally cleanup with IServerCleanup.

‍A service is created with the MqServiceCreate and deleted with the MqServiceDelete.

A service can be created and deleted during the entire life-cycle of the server or the client. If the server/client-context is deleted all services of the are deleted also.

‍A MqServiceDelete is not required.

Creating or deleting a service is like granting or revoking the right to access a single feature.

eventloop

To receive a data-package on a service the event-loop have to be active. The event-loop ia always active on an synchronous-service-call . On a server the event-loop is started with MqProcessEvent at startup.
synchronous-service-call
A synchronous-service-call always block and enter the event-loop to wait for an answer
asynchronous-service-call
A asynchronous-service-call always return immediately and the possible result is received on a callback

callback

A callback is the function called by a service and required to receive data from remote.
A callback is created with MqServiceCreate or is part of the service-call.
A callback can be a service-identifer or a service-callback.
service-call with callback
SendEND_AND_CALLBACK, SendEND_AND_SUB, SendEND_AND_TRANSACTION
service-call without callback
SendEND, SendEND_AND_WAIT

Example from MyServer.tcl define the service SRV1 on the server-link-setup

package require tclmsgque::MqMsgque
namespace import tclmsgque::MqMsgque::*
namespace import tclmsgque::MkKernel::*

# package-item
::oo::class create MyServer {
  superclass MqContextC

  # service to serve all incoming requests for token "HLWO"
  method myFirstService {} {
    my SendSTART
    my SendSTR "[my ReadSTR] World"
    my SendRETURN
  }

  # define a service as link between the token "HLWO" and the callback "MyFirstService"
  method serverSetup {} {
    my ServiceCreate "HLWO" myFirstService
  }

  # factory startup (constructor)
  constructor {{tmpl ""}} {
    next $tmpl
    my ConfigSetServerSetup serverSetup
  }
} 

# package-main
tclmsgque::MqMsgque Main {

  # setup commandline arguments for later use
  set args  [MkBufferListC CreateLA {*}$argv]

  # create "MyServer" factory... and make it to the default.
  set fct   [[MqFactoryC Add MyServer] Default]

  # inspect commandline-argument for the "factory" to choose... and create a object
  set fct   [MqFactoryC GetCalledL $args]
  set srv   [$fct New]

  try {
    $srv LinkCreate $args
    $srv ProcessEvent MQ_WAIT_FOREVER
  } on error {} {
    $srv ErrorCatch
  } finally {
    $srv Exit
  }
}

$ctx ServiceCreate token:string[4] callback:callable

top create a link between a service-token and a service-callback … → API: tcl_mqmsgque_MqContextC_ServiceCreate

The servive-token (e.g. MqContextC_ServiceApi_Identifer) have to be unique but the service-callback (e.g. MqServiceCallbackF) not. If a service-callback is not unique than this is called an alias, use string[4] [$ctx ServiceTokenGet] to get the current token for an incoming-service-call.

The service-callback have to be callable by the server and/or by the child and/or the slave context. A static-callback is a good choice to achive this goal.

The filter, a slave-context, is setup with the initial factory using the initial-class (MqContextC) usually different from the server-class (MyServer…). The filter need the service-callback, usually shared with the server, to report a filter-message to the server.
To distinguish the server and the filter the following functions are used
(all function cann be called as either server or filter context):

Example from Filter6.tcl setup the services for server and filter

  method FilterSetup {} {
    set ftr [my SlaveGetFilter]
    my variable FH
    set FH ""
    my ServiceCreate    "LOGF" LOGF
    my ServiceCreate    "EXIT" EXIT
    my ServiceCreate    "SOEX" SOEX
    my ServiceCreate    "ERR1" ERR1
    my ServiceStorage   "PRNT"
    my ServiceStorage   "PRN2"
    my ServiceCreate    "+ALL" FilterIn
    $ftr ServiceCreate  "WRIT" WRIT
    my ServiceCreate    "WRIT" WRIT
    $ftr ServiceProxy   "WRT2" MASTER
  }
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
[in]fCallthe C-function to process the incoming service-request (C-API only)
[in]callbackthe user defined callback as data-argument for the C-function fCall
[in]fFreethe function to free the data-argument after use (C-API only)
[in]fMarkthe function to mark the data-argument during garbage-collection (C-API only)
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
the link-setup (MqLinkCreate or MqLinkCreateChild) have to done before using this function
MqServiceCreate : callback signature
1. The *service-ctx* is the *context* for which the service was defined.
2. If the *callback* is **not** an instance of the calling *context*, the *service-ctx* is added as an argument.
callback-args := service-ctx:MqContextC[in]
[static] proc callback { callback-args ?additional-args...? } ...
[own] ::oo::class create XXX {
superclass MqContextC
method callback { ?additional-args...? } ...
[instance] ::oo::class create YYY {
method callback { callback-args ?additional-args...? } ...
[class] ::oo::class create ZZZ {
self method callback { callback-args ?additional-args...? } ...
read more at: Callback signature

$ctx ServiceDelete token:string[4]

top delete a service. … → API: tcl_mqmsgque_MqContextC_ServiceDelete

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

bool [$ctx ServiceIsTransaction]

top check if the ongoing-service-call belongs to a transaction … → API: tcl_mqmsgque_MqContextC_ServiceIsTransaction

A service-call can be with-transaction (return true if the package was send with MqSendEND_AND_WAIT or MqSendEND_AND_CALLBACK) or can be without-transaction (return false if the package was send with MqSendEND)

Parameters
[in]ctxthe MqContextS instance to work on
Returns
a boolean value, true or false

$ctx ServiceProxy token:string[4] ?id:MqSlaveE|int32=MQ_SLAVE_OTHER?

top create a service to link a master-context with a slave-context. … → API: tcl_mqmsgque_MqContextC_ServiceProxy

This function is used to create a proxy-service to forward the body-data from the read-data-package of the master to the send-data-package of the slave. The data is not changed. This function support the reverse-operation also. If the ctx is a master-context than the data is send to slave identified by id. If the ctx is a slave-context than the data is send to the master of the slave.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
[in]idthe SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal.
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx ServiceProxyCtx token:string[4] target:MqContextC

top same as MqServiceProxy but use an MqContextC as input. → API: tcl_mqmsgque_MqContextC_ServiceProxyCtx

See also
MqServiceProxy

bool [$ctx ServiceProxyCtxExists token:string[4] target:MqContextC]

top check if service who belongs to token is a proxy-service → API: tcl_mqmsgque_MqContextC_ServiceProxyCtxExists

This is used for route (MqRouteDelete) to identify the service-usage

See also
MqServiceProxy

$ctx ServiceProxyRoundRobin token:string[4] ident:string

top create a proxy-service using Round-Robin as load-balancer … → API: tcl_mqmsgque_MqContextC_ServiceProxyRoundRobin

This function is used to create a proxy-service to forward the body-data from the read-data-package of the master-context to the send-data-package of the slave-context. The data is not changed. This function support the reverse-operation also. If the ctx is a master-context than the data is send to one of the slave-context identified by ident. If the ctx is a slave-context than the data is send to the master-context of the slave.

The Round-Robin-Load-Balancer is only used for the direction from the master-context to the slave-context if the name-resolution return multiple target-context for the single ident.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
[in]identthe targetIdent used to select a list slave-Context for the Round-Robin
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx ServiceStorage token:string[4]

top setup a service listen on a MqContextC_ServiceApi_Identifer and save all read-data-package into the STORAGE … → API: tcl_mqmsgque_MqContextC_ServiceStorage

In a shortterm-transaction-synchronous-service-call the service will return an empty data package. In a longterm-transaction-synchronous-service-call the data will return as normal.

Example from Filter6.tcl using MqServiceStorage to store all packages from service PRNT and PRN2 into database

  method FilterSetup {} {
    set ftr [my SlaveGetFilter]
    my variable FH
    set FH ""
    my ServiceCreate    "LOGF" LOGF
    my ServiceCreate    "EXIT" EXIT
    my ServiceCreate    "SOEX" SOEX
    my ServiceCreate    "ERR1" ERR1
    my ServiceStorage   "PRNT"
    my ServiceStorage   "PRN2"
    my ServiceCreate    "+ALL" FilterIn
    $ftr ServiceCreate  "WRIT" WRIT
    my ServiceCreate    "WRIT" WRIT
    $ftr ServiceProxy   "WRT2" MASTER
  }
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

bool [$ctx ServiceTokenCheck token:string[4]]

top in an ongoing-service-call check if the current MqContextC_ServiceApi_Identifer is token … → API: tcl_mqmsgque_MqContextC_ServiceTokenCheck

See also
MqServiceTokenGet
Parameters
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
Returns
a boolean value, true or false

bool [$ctx ServiceTokenExists token:string[4]]

top check if the MqContextC_ServiceApi_Identifer token is defined as ctx service … → API: tcl_mqmsgque_MqContextC_ServiceTokenExists

This code is used to detect if a service with identifer token exists.

See also
MqRouteTraverse
Parameters
[in]ctxthe MqContextS instance to work on
[in]tokenthe MqContextC SERVICE API to identify the service
Returns
a boolean value, true or false

string[4] [$ctx ServiceTokenGet]

top in an ongoing-service-call get the current MqContextC_ServiceApi_Identifer … → API: tcl_mqmsgque_MqContextC_ServiceTokenGet

This function is needed on the server to process a service-request defined as +ALL or as an alias to extract the current MqContextC_ServiceApi_Identifer.

Parameters
[in]ctxthe MqContextS instance to work on
Returns
the MqContextC_ServiceApi_Identifer

MqContextC SLAVE API

NAVI: top, up
SlaveCheck check if slave-id is valid
SlaveCreate create a master/slave link between the master-parent-context and the slave-parent-context …
SlaveDelete Delete a slave object from a master/slave link identified by id. …
SlaveGet get the slave-context from a master-context
SlaveGetFilter get the filter-ctx or the master-ctx
SlaveGetMaster opposite function of MqSlaveGetFilter
SlaveGetProxy on slave return the master and on master return the slave identified by id.
SlaveIs is the context a slave-context ? …
SlaveWorker

create a master/slave link using the image of the ctx object self. …

MqContextC SLAVE API DETAILS

C-API: MqContextC_SlaveApi_C_API - 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:

  • report error messages from the slave-context to the master-context
  • to create a slave-child-context if a master-child-context is created
  • to delete a slave-context if a master-context is deleted

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"

  • the master-context is a parent-context without a child-context available.
  • the master-context is a client-context or a server-context.
  • the link between the master-context and the slave-context is done using MqSlaveWorker or MqSlaveCreate

Definition of the "slave-context"

  • the slave-context is a parent-context without a child-context available.
  • the slave-context is a client-context.
  • the slave-context lifetime is controlled by the master-context.
  • the slave-context report all error-messages to the master-context.
  • the slave-context is identified by a unique-slave-id starting with 0.
  • a special form of a slave-context is a worker-context

Definition of the "worker-context"

  • the worker-context is a slave-context using the image of the master-context self.
  • the master-context can be a server-context or a client-context.
  • the worker-context is created using MqSlaveWorker
  • the worker-context is identified by a unique-slave-id starting with 0.

Definition of the "slave-id"

  • the slave-id is defined at enum MqSlaveE
  • a slave is identified in his master-context by a slave-id
  • the slave-id work like a defined well-known-port-number in /etc/services
  • the slave-id is an integer value with valid values > 0
  • it is a good practice to plan the usage of your slave-id(s)
  • slave
    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
    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 -- #
  • the loopback has always the slave-id = 0 .
  • the loopback has the same class as the parent, if reflection is not available the MqFactoryInitial is used.
  • the loopback is used to call a service on the same process or thread.
  • the loopback is a special filter without an additional process or thread to be started.
  • the loopback is only internal accessible
  • the service called by the loopback need the same attention as the service called by the filter, the context of the service is the loopback-context.
  • the loopback can call MqServiceCreate to create a new link between a service-token and a service-method, by default all services from the master-context (the owner of the loopback) are also accessible by the loopback.
  • in the service use MqSlaveGetMaster to get the master-context from the loopback-context.
  • Example from MyLoopServer.tcl create a new loop-server
    package require tclmsgque::MqMsgque
    namespace import tclmsgque::MqMsgque::*
    
    ::oo::class create MyLoopServer {
      superclass MqContextC
      export variable
    
      # factory startup
      constructor {{tmpl ""}} {
        my variable mydata;
        next $tmpl
        my ConfigSetServerSetup ServerSetup
        # set the "mydata" attribute to the master-context
        set mydata  "Hello World";
      }
    
      # service to serve all EXTERNAL requests for token "HLWO"
      method HLWO_srv {} {
        # get the "loopback" context
        set loop  [my SlaveGet LOOPBACK]
        # call the LOOP service on the SAME server
        $loop Send "W" "LOOP"
        # answer HLWO with string-return from LOOP
        my Send "R" "C" [$loop ReadSTR]
      }
    
      # service to serve all INTERNAL requests for token "LOOP"
      method LOOP_srv {} {
        # get the "master" context
        set master  [my SlaveGetMaster]
        # answer LOOP with data from MASTER->mydata attribute
        $master variable mydata
        my Send "R" "C" $mydata
      }
    
      # setup a server-context - called for every new server-context
      method ServerSetup {} {
        # EXTERNAL: link the "HLWO" service with "HLWO_srv"
        my ServiceCreate "HLWO" HLWO_srv
        # INTERNAL: link the "LOOP" service with "LOOP_srv"
        [my SlaveGet MQ_SLAVE_LOOPBACK] ServiceCreate "LOOP" LOOP_srv
      }
    }
    
    tclmsgque::MqMsgque Main {
    
      # create "MyLoopServer" factory... and the instance
      set srv   [[MqFactoryC Add MyLoopServer] New]
    
      try {
        $srv LinkCreate $argv
        $srv ProcessEvent MQ_WAIT_FOREVER
      } on error {} {
        $srv ErrorCatch
      } finally {
        $srv Exit
      }
    }
    

Performance analyse

The performance-test is created with:
  • pipe
    • Nhi1Exec perfclient.c --parent --wrk ? @ perfserver.c
  • spawn, fork, thread
    • Nhi1Exec -r=uds perfserver.c --spawn|fork|thread
    • Nhi1Exec -r=uds perfclient.c --parent --wrk ?
  • the number of workers are set with the –wrk option
  • the cpu is a xeon with 4/8
  • the performance is calculated as worker-context-created / time-in-sec with a ~2sec (default) measurement period.
performance-test code:
  • The test-setup is done as:
      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 
performance-test results:
  • results generated using the debug environment
    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 -

bool [$ctx SlaveCheck id:MqSlaveE|int32]

top check if slave-id is valid → API: tcl_mqmsgque_MqContextC_SlaveCheck

Parameters
[in]ctxthe master-context as PARENT or CHILD
[in]idthe SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal.
Returns
boolean true = valid or false = invalid

$ctx SlaveCreate id:MqSlaveE|int32 slave:MqContextC

top create a master/slave link between the master-parent-context and the slave-parent-context … → API: tcl_mqmsgque_MqContextC_SlaveCreate

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 :

Client clt = new Client();
clt.LinkCreate(ConfigGetStartAs());
SlaveCreate (id, clt);

Example from server.cc without reflection support... the factory is required :

MqFactoryCT<Client>::Add("client");

and the factory is used to create the object :

Client *clt = MqFactoryCT<Client>::Get("client")->New();
clt->LinkCreate(ConfigGetStartAs());
SlaveCreate (id, clt);
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe master context object as PARENT without a CHILD
[in]idthe SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal.
[in]slavethe slave context object as CLIENT-PARENT without a CHILD
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqSlaveGet

$ctx SlaveDelete id:MqSlaveE|int32

top Delete a slave object from a master/slave link identified by id. … → API: tcl_mqmsgque_MqContextC_SlaveDelete

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.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe master context object as PARENT without a CHILD
[in]idthe SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal.
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
it is still possible to delete a child-slave-context using MqLinkDelete but this will break the internal master/slave order.

MqContextC [$ctx SlaveGet id:MqSlaveE|int32]

top get the slave-context from a master-context … → API: tcl_mqmsgque_MqContextC_SlaveGet

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe master-context as PARENT or CHILD
[in]idthe SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal.
[out]ctx_outthe slave-context or "MK_NULL" on error
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
an error is raised if id is not valid or ctx is not a master-context.

MqContextC [$ctx SlaveGetFilter]

top get the filter-ctx or the master-ctx … → API: tcl_mqmsgque_MqContextC_SlaveGetFilter

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:

  1. return ctx if ctx is the wanted ctx
  2. return master-ctx or filter-ctx
  3. return a "context not available" error
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]ctx_outthe ctx or "MK_NULL" on error
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

MqContextC [$ctx SlaveGetMaster]

top opposite function of MqSlaveGetFilter → API: tcl_mqmsgque_MqContextC_SlaveGetMaster

Attention
if no master is available, a "MK_NULL" is returned

MqContextC [$ctx SlaveGetProxy id:MqSlaveE|int32]

top on slave return the master and on master return the slave identified by id. → API: tcl_mqmsgque_MqContextC_SlaveGetProxy

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe master or slave-context as PARENT or CHILD
[in]idthe SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal.
[out]ctx_outthe other-context or "MK_NULL" on error
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
an error is raised if id is not valid

bool [$ctx SlaveIs]

top is the context a slave-context ? … → API: tcl_mqmsgque_MqContextC_SlaveIs

Parameters
[in]ctxthe MqContextS instance to work on
Returns
a boolean value, true or false

$ctx SlaveWorker id:MqSlaveE|int32 ?fct:string="WORKER"? ?args:MkBufferListC...="MK_NULL"?

top create a master/slave link using the image of the ctx object self. … → API: tcl_mqmsgque_MqContextC_SlaveWorker

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:

  • context-creation in the Factory or the class-constructor
  • link-creation in the IServerSetup method
  • service-call in the client-service-request (starting worker one-the-fly)

Example from server.tcl create a worker in a service-callback reading arguments from the service

# start worker with arguments from the service-call using the current executable
my SlaveWorker $id "WORKER" {*}[my ReadLIST] --name wk-cl-$id @ --name wk-sv-$id
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe master context object as PARENT without a CHILD
[in]idthe SlaveId to unique identify the master/slave link, the id < MQ_SLAVE_USER is internal.
[in]fctthe 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]argscommand-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
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
- A slave-worker can only be created in a parent-context.

MqContextC STORAGE API

NAVI: top, up
StorageClose close the storage. …
StorageCount count the number of storage-rows
StorageDecrRef decrease the internal refCount lock of the database-entry
StorageDelete delete the storage-row identified by the transLIdP_inout
StorageErrCnt increment and return the database row-error-count for the row defined with transLId
StorageExport export the read-data-package into the STORAGE
StorageImport import the storage-package into the read-data-package
StorageIncrRef increase the internal refCount lock of the database-entry
StorageLog log the storage the status of the open transactions
StorageOpen switch to a file-based-transaction-database
StorageResolve

extract the context->link.protect.rmtTransLId entry from the database

MqContextC STORAGE API DETAILS

C-API: MqContextC_StorageApi_C_API - MqContextC - setup and manage a storage used to persist data-packages

The storage is divided into: INTERNAL and EXTERNAL storage. Only the read-data-package can be stored or dumped into the storage.

The read-data-package is saved into the storage using:

ServiceStorage setup a service listen on a MqContextC_ServiceApi_Identifer and save all read-data-package into the STORAGE
StorageExport export the read-data-package into the STORAGE

The read-data-package is restored from the storage using:

StorageImport import the storage-package into the read-data-package
ProxyForward send the entire read-data-package-data to the link-target
All this usually happen in an Event Handler

Some important facts of the storage-feature:

  • The internal-storage depends on SQLite.
  • The package-storage can be used to save all kind of package-data.
  • The longterm-transaction-package-data is allways saved into storage.
  • By default only an in-memory storage is in use, but this can be changed with MqStorageOpen or Storage
  • An entire service-call can be saved with MqServiceStorage

The following internal storages are supported:

default
The default-storage is set with the configuration parameter --storage fileName and defaults to "#memdb#". If a package have to be saved into the storage and the storage is not open the default-storage id used. The open will always be performed. If an explicit storage is required the default can be changed or a storage can explicit be opened with MqStorageOpen. Keep in mind that the default-storage is a per-context configuration but only one storage per process or thread is currently supported.
memdb
This is the default storage and can be set explicitly with MqStorageOpen using the "#memdb#" parameter.
tmpdb
This storage is like an in-memory-storage but export data to the TEMPORARY filesystem if the application run out of memory. This storage can explicit be set with MqStorageOpen with the parameter "#tmpdb#".
filedb
This storage always work on files. Only this storage is persistent and can explicit be set with MqStorageOpen with the storageFile parameter.

Performance analyse:

  • The performance is tested with: Nhi1Exec perfclient.c --all --storage VALUE @ perfserver.c.
  • The parameter VALUE is set to #memdb#, #tmpdb# or a filedb file.
  • If –storage is not set the filedb database is used together with an internal file-name.
database performance host crash application crash info
memdb 30.000 data lost data lost non persistent
tempdb < 30.000 data lost data lost uses memory and/or temporary file
filedb (mem) 10.000 data lost data safe in memory filesystem
filedb (disc) 50 data safe data safe disc-speed is the key factor

$ctx StorageClose

top close the storage. … → API: tcl_mqmsgque_MqContextC_StorageClose

the next storage request will open the storage again with the location from Storage

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

int32 [$ctx StorageCount]

top count the number of storage-rows … → API: tcl_mqmsgque_MqContextC_StorageCount

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]cnt_outnumber of rows, OLL if nothing is available
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

$ctx StorageDecrRef transLId:int32

top decrease the internal refCount lock of the database-entry → API: tcl_mqmsgque_MqContextC_StorageDecrRef

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]transLIdstorage-id … return from MqStorageImport
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqStorageImport, MqStorageIncrRef

int32 [$ctx StorageDelete ?*transLIdP_inout:int32=0?]

top delete the storage-row identified by the transLIdP_inout … → API: tcl_mqmsgque_MqContextC_StorageDelete

The transLIdP_inout is the value returned by a previous MqStorageImport. If transLIdP_inout is "MK_NULL" than OLL is used. MqStorageImport and MqStorageDelete work together link an transaction and every successfull transcation have to delete the transLIdP_inout out of the storage. After sucessfull delete the transLIdP_inout is set to 0LL, on error the initial value is unchanged.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in,out]transLIdP_inoutpointer to storage-id to delete, will be 0LL on success
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

int32 [$ctx StorageErrCnt transLId:int32]

top increment and return the database row-error-count for the row defined with transLId → API: tcl_mqmsgque_MqContextC_StorageErrCnt

The storage is typical used in the following workflow:

<----- AT CALLING CLIENT ----->|<----- AT RECEIVING SERVER ----->
                               |
    *setup transaction         |
    make service-request      -->    *start service-handler
                               |     save request into storage
    wait for confirmation     <--    confirm data receiving
                               |     *stop service-handler

  ====================  enter event loop  =====================

                               |     *start event-handler
                               |     load reqest from storage
                               |     process data
    *start transaction        <--    send result-data
    process result-data        |     *stop event-handler
    *stop transaction          |

Example Filter6 - store incoming packages into storage

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]transLIdstorage-id … return from MqStorageImport
[out]cnt_outthe new value or -1 on error
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

int32 [$ctx StorageExport]

top export the read-data-package into the STORAGE … → API: tcl_mqmsgque_MqContextC_StorageExport

The export include all data required to setup a read-data-package later again. After import with MqStorageImport the read-data-package and the environment will be set as it was on MqStorageExport

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]ltid_outif ltid_out != NULL return the storage-id
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqDumpExport, MqStorageImport

int32 [$ctx StorageImport ?*transLIdP_inout:int32=0?]

top import the storage-package into the read-data-package … → API: tcl_mqmsgque_MqContextC_StorageImport

Select the read-data-package from the database using the transLIdP. Only a package with refCount = 0 will be selected.
After selection the refCount is incremented and the next call to MqStorageImport using the same transLId will fail.
MqStorageImport is used together with MqStorageDelete or MqStorageDecrRef to delete the selected package from database or to undo the select.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in,out]transLIdP_inoutstorage-id or "MK_NULL" or 0 … return from MqStorageExport
*transLIdP > 0 return the read-data-package identified with the storage-id.
*transLIdP == 0 return the top-most (FIFO) read-data-package and set the transLIdP to the storage-id.
*transLIdP < 0 return an error
transLIdP == NULL like transLIdP == 0
*transLIdP invalid like transLIdP < 0
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
Read MqProcessEvent for the dependency with the event-loop.
There is no guarantee that a package will be read FIFO.
In principle, the first free package (refCount=0) with the smallest transLId is read.
However, if the package hangs in subsequent processing and the refCount is not reset or the package is not deleted, then the package remains locked and a subsequent call to MqStorageImport will read the next free package.
  • This approach protects a server or router from blocking after an unpredictable failure.
See also
MqDumpExport, MqStorageExport, MqStorageDelete, MqStorageDecrRef, MqStorageIncrRef

$ctx StorageIncrRef transLId:int32

top increase the internal refCount lock of the database-entry → API: tcl_mqmsgque_MqContextC_StorageIncrRef

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]transLIdstorage-id … return from MqStorageImport
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqStorageImport, MqStorageDecrRef

$ctx StorageLog ?callfunc:string="MK_NULL"?

top log the storage the status of the open transactions → API: tcl_mqmsgque_MqContextC_StorageLog

$ctx StorageOpen storageFile:string

top switch to a file-based-transaction-database … → API: tcl_mqmsgque_MqContextC_StorageOpen

the value can also be set using the --storage commandline option.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[in]storageFilethe file used to create the transaction-database. Allowed values are:
  1. "#memdb#" for a in-memory-database (default)
  2. "#tmpdb#" for a temporary-database-file
  3. filename for a persistent-database-file
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)

{otherCtxP:MqContextC otherLIdP:int32} [$ctx StorageResolve]

top extract the context->link.protect.rmtTransLId entry from the database → API: tcl_mqmsgque_MqContextC_StorageResolve

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe MqContextS instance to work on
[out]otherCtxP_outthe ctx of the resolve
[out]otherLIdP_outthe transLId of the resolve

INSTANCE STORAGE API

SUPER: MqContextC, top

tclmqmsgque is using a class-attribute as instance-storage. …

introduction
The instance-storage is defined using the variable keyword:
package require tclmsgque::MkKernel
namespace import tclmsgque::MkKernel::*
# package-item
::oo::class create MyClass {
superclass MkBufferC
variable my_data
constructor {val} {
set my_data $val
}
}

MqDumpC

SUPER: MkObjectC, top
MqDumpC CLASS

Export MqDumpC - Export class functions …
Introspection MqDumpC - Introspection class functions …
Misc

MqDumpC - Misc class functions …

MqDumpC TOR

Export create a MqDumpC as export of the ctx-read-data-package
BinSet create an MqDumpS object from binary data
Error export the context->error into the dump-package
new create a MqDumpC as export of the ctx-read-data-package
Delete Destructor - delete a MqDumpC instance …
BinGet export the binary data from an MqDumpS object
Import

import the dump-package into the ctx-read-data-package

MqDumpC MISC

Log log the MqDumpC
SizeGet report the binary data size from an MqDumpS object
TokenGet

return the MqContextC_ServiceApi_Identifer

MqDumpC DETAIL

C-API: MqDumpC_C_API - MqDumpC - the class known as dmp or dump is used to export a tclmqmsgque data package as binary

The dump is used to exchange data with external counterparts such as a database or a user-specific infrastructure.

There are 3 different function that deal with a dump:

  1. The MqDumpExport export the read-data-package from the calling context to a dump.
  2. The MqDumpImport imports the dump into the read-data-package of the calling context. All MqContextC READ API functions can be used to read the data from the read-data-package.
  3. The MqProxyForward imports the dump into the send-data-package of the calling context. All MqContextC SEND API functions can be used to write the data into the send-data-package
See also
MqContextC PROXY API

MqDumpC CLASS

NAVI: top, up

MqDumpC CLASS EXPORT

HandleResolve Handle-Resolve-Slot - return a MqDumpC from netHdl or "MK_NULL" if invalid…
HandleGet

Handle-Get-Slot - returns a export-hdl to the MqDumpC useable for external storage

MqDumpC CLASS INTROSPECTION

Instances get head-instance from linked-list of MqDumpS type …
Next get next instance from linked-list of MqDumpS type
Prev

get previous instance from linked-list of MqDumpS type

MqDumpC CLASS MISC

GetNull

Null-Slot - return a MqDumpC typed NULL instance …

MqDumpC CLASS DETAILS

C-API: MqDumpC_Class_C_API - MqDumpC - define the class …

MqDumpC CLASS EXPORT

MqDumpC - Export class functions …

(static) MqDumpC [MqDumpC HandleResolve netHdl:MK_HDL]

top Handle-Resolve-Slot - return a MqDumpC from netHdl or "MK_NULL" if invalid… → API: tcl_mqmsgque_MqDumpC_HandleResolve

The MqDumpHandleResolve undo the MqDumpHandleGet and is intended to export a unique identifer into external code not belonging to the Programming-Language-Micro-Kernel (PLMK).

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]netHdlhandle former exported with MqDumpHandleGet
Returns
the required handle or "MK_NULL" if netHdl is invalid

MK_HDL [$dmp HandleGet]

top Handle-Get-Slot - returns a export-hdl to the MqDumpC useable for external storage → API: tcl_mkkernel_MkObjectC_HandleGet

The export-hdl is a reference to an instance that can be stored in software and converted back into an instance using the MqDumpHandleResolve.

The export-hdl is only valid until the Programming-Language-Micro-Kernel (PLMK) ends.

example: The export-hdl is used in rpc to identify an object across the network.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]dmpthe MqDumpS instance to work on
Returns
the required export-hdl

MqDumpC CLASS INTROSPECTION

MqDumpC - Introspection class functions …

(static) MqDumpC [MqDumpC Instances]

top get head-instance from linked-list of MqDumpS type … → API: tcl_mqmsgque_MqDumpC_Instances

The head-instance is the last instance created.

MqDumpC [$dmp Next]

top get next instance from linked-list of MqDumpS type → API: tcl_mqmsgque_MqDumpC_Next

MqDumpC [$dmp Prev]

top get previous instance from linked-list of MqDumpS type → API: tcl_mqmsgque_MqDumpC_Prev

MqDumpC CLASS MISC

MqDumpC - Misc class functions …

(static) MqDumpC [MqDumpC GetNull]

top Null-Slot - return a MqDumpC typed NULL instance … → API: tcl_mqmsgque_MqDumpC_GetNull

MqDumpC TOR

C-API: MqDumpC_TOR_C_API - MqDumpC - various functions to create, initialize and destroy a dump

(constructor,static) MqDumpC [MqDumpC Export ctx:MqContextC ?dumpP_inout:MqDumpC="MK_NULL"?]

top create a MqDumpC as export of the ctx-read-data-package … → API: tcl_mqmsgque_MqDumpC_Export

The new instance belongs to the caller and may have to be released if necessary. A manual release using DumpDelete is always possible, but the instance can no longer be used afterwards.

The export include all data required to setup a read-data-package again later. After import with MqDumpImport the read-data-package and the environment will be set as it was on MqDumpExport The export can be saved into an external storage or be used in a network-tunnel (example: the aguard tool).

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe context to be exported into the dump-package-data
[in,out]dumpP_inoutreturns
Returns
The newly created MqDumpC instance, the instance is owned by the caller
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqStorageExport, MqDumpImport, MqDumpError
Attention
1. The goal of this function is to create a dump to be loaded in the context later. If the context is not the original context… propably additional work is necessary.
2. The MqDumpExport is using realloc to allocate space. The value of *value should be initialized with either "MK_NULL" or a result of a previous MqDumpExport or MqDumpError.
3. Garbage is detected using MqDumpC_SIGNATURE… there is a MINIMAL chance (1 to 4.294.967.295) that the gargabe is NOT detected… to be save… always initialize the dump.
4. If the dump was initialized with "MK_NULL" or garbage … new memory will be allocated… If the dump memory will NOT be reused… free the memory with (6.)
5. If the dump was initialized with an previous dump … the memory will be reused… and extended with realloc if required.
6. Free the memory with MqDumpDelete.
7. On error… the dump is unchanged.
8. In case of TLS memory returned read more at MkKernel_Storage_C_API.

(constructor,static) MqDumpC [MqDumpC BinSet data:binary]

top create an MqDumpS object from binary data → API: tcl_mqmsgque_MqDumpC_BinSet

Check the MqDumpC_SIGNATURE and set the refCount to 0

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]datathe binary data
[out]dmp_outthe new MqDumpC
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
The MqDumpS object is an pointer object… this mean the original data is still required and must NOT be freed.
MkBinaryR bin,
MQ_DMP *dmp_out
) {
assert(dmp_out!=NULL);
MQ_DMP dump = (MQ_DMP) bin.data;
if (!__MkCheckX(MqDumpC,dump)) {
return MkErrorDbV_2_M(MK_ERROR_PRINT,MK_ERROR_VALUE_INVALID, "signature", "MqDumpS");
} else {
MkOBJ_R(dump).refCount = 0;
}
*dmp_out = dump;
return MK_OK;
}

(constructor,static) MqDumpC [MqDumpC Error error:MqContextC ?dumpP_inout:MqDumpC="MK_NULL"?]

top export the context->error into the dump-package … → API: tcl_mqmsgque_MqDumpC_Error

The export include all data required to setup a read-data-package later again. After import with MqDumpImport the read-data-package and the environment will be set as it was on MqDumpExport The export can be saved into an external storage or be used in a network-tunnel (example: the agurad tool).

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]errorthe error-context to be exported into the dump-package-data
[in,out]dumpP_inoutthe dump-error-package-data to save
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
1. use remarks from MqDumpExport
2. MqDumpError using the send-data-package to create the dump-package.. to use the send-data-package afterwords a MqSendSTART is required
See also
MqStorageExport, MqDumpImport, MqDumpExport

(constructor,static) MqDumpC [MqDumpC new ctx:MqContextC ?dumpP_inout:MqDumpC="MK_NULL"?]

top create a MqDumpC as export of the ctx-read-data-package … → API: tcl_mqmsgque_MqDumpC_new

The new instance belongs to the caller and may have to be released if necessary. A manual release using DumpDelete is always possible, but the instance can no longer be used afterwards.

The export include all data required to setup a read-data-package again later. After import with MqDumpImport the read-data-package and the environment will be set as it was on MqDumpExport The export can be saved into an external storage or be used in a network-tunnel (example: the aguard tool).

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]ctxthe context to be exported into the dump-package-data
[in,out]dumpP_inoutreturns
Returns
The newly created MqDumpC instance, the instance is owned by the caller
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
See also
MqStorageExport, MqDumpImport, MqDumpError
Attention
1. The goal of this function is to create a dump to be loaded in the context later. If the context is not the original context… propably additional work is necessary.
2. The MqDumpExport is using realloc to allocate space. The value of *value should be initialized with either "MK_NULL" or a result of a previous MqDumpExport or MqDumpError.
3. Garbage is detected using MqDumpC_SIGNATURE… there is a MINIMAL chance (1 to 4.294.967.295) that the gargabe is NOT detected… to be save… always initialize the dump.
4. If the dump was initialized with "MK_NULL" or garbage … new memory will be allocated… If the dump memory will NOT be reused… free the memory with (6.)
5. If the dump was initialized with an previous dump … the memory will be reused… and extended with realloc if required.
6. Free the memory with MqDumpDelete.
7. On error… the dump is unchanged.
8. In case of TLS memory returned read more at MkKernel_Storage_C_API.

(destructor) $dmp Delete

top Destructor - delete a MqDumpC instance … → API: MqDumpDelete_RT

See also
MqDumpExport MqDumpError MkObjectDelete

binary [$dump BinGet]

top export the binary data from an MqDumpS object → API: tcl_mqmsgque_MqDumpC_BinGet

Parameters
[in]dumpthe source object
Returns
The required MkBinaryR
Attention
The data still belongs to the MqDumpS object… do NOT free.
MQ_DMPN const dump
) {
MK_ATTR_HDL_CHECK(dump);
return (MkBinaryR) {dump->size, (MK_BIN)dump};
}

$dump Import ctx:MqContextC

top import the dump-package into the ctx-read-data-package … → API: tcl_mqmsgque_MqDumpC_Import

The dump is the result of a previous MqDumpExport function call. After the load an package is suitable for all kind of MqContextC READ API function. To just forward the package use the MqProxyForward function.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]dumpthe dump-package to be imported
[in]ctxthe context in wich the dump-package is imported
Exceptions
MkExceptionC→ The default-exception from the Programming-Language-Micro-Kernel (PLMK)
Attention
- The memory is dynamic-allocated and can be reused for the next MqDumpExport.
  • (do not free) The memory of the out/return value belongs to the called TclMqMsgque function and therefore never becomes "MK_NULL" for a non-error result.
    For details on the out/return value, see: MkKernel_Storage_C_API.
See also
MqStorageExport, MqDumpExport, MqDumpError

MqDumpC MISC

C-API: MqDumpC_Misc_C_API - MqDumpC - various functions to work on a dump

$dmp Log ?fmtobj:MkObjectC="MK_NULL"? ?debug:int32=0? ?callfunc:string="MK_NULL"? ?lvl:int32=0?

top log the MqDumpC … → API: tcl_mqmsgque_MqDumpC_Log

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]dmpthe MqDumpS instance to work on
[in]fmtobjmanaged object used to format the log-message (default="MK_NULL" → use default-format)
[in]debugthe debug level from MkRuntimeS::debug, use 0 <= debug <= 9 (default=0)
[in]callfunca user-defined postfix to identify the calling function or the environment (default=name-of-function)
[in]lvla user-defined prefix starting with "" for lvl=0 and increase with " " for lvl+1 (default=0)

long [$dump SizeGet]

top report the binary data size from an MqDumpS object → API: tcl_mqmsgque_MqDumpC_SizeGet

Parameters
[in]dumpthe source object
Returns
the size of the dump
MQ_DMPN const dump
) {
MK_ATTR_HDL_CHECK(dump);
return dump->size;
}

string [$dump TokenGet]

top return the MqContextC_ServiceApi_Identifer … → API: tcl_mqmsgque_MqDumpC_TokenGet

MQ_DMPN const dump
) {
MK_ATTR_HDL_CHECK(dump);
return dump->hdr.tok;
}

MqFactoryC

SUPER: MkObjectC, top
MqFactoryC CLASS

Export MqFactoryC - Export class functions …
Introspection MqFactoryC - Introspection class functions …
Misc

MqFactoryC - Misc class functions …

MqFactoryC TOR

Add add a new MqFactoryC identified by factory-identifier and defined by factory-constructor
new add a new MqFactoryC identified by factory-identifier and defined by factory-constructor
Delete Destructor - delete a MqFactoryC instance …
Dup2

create a duplicate of the singleton object MqFactoryC using a new factory-identifer

MqFactoryC GET

Get return the MqFactoryC
GetCalled returns the MqFactoryC identified by ident
GetCalledL returns the MqFactoryC identified as first argument in the largs MkBufferListC
GetOriginalIdent

helper function to return MqFactoryS::originalIdent

MqFactoryC MISC

DefaultIdent return the factory-identifier of the default MqFactoryC
InitialIdent return the factory-identifier of the initial MqFactoryC
LogAll log all "factories" to stderr
Default set the default-attribute to the factory
Initial set the initial-attribut to fct
Log log the MqFactoryC
New

create a new MqContextC from a MqFactoryC

MqFactoryC DETAIL

C-API: MqFactoryC_C_API - MqFactoryC - the class known as fct or factory is used to provide an interface to create one or more new MqContextC

The factory is an important part of the object management and has the following basic features:

  1. create/delete a MqContextC defined by a MqFactoryC
  2. infrastructure to host multiple MqFactoryC in a single executable
  3. provide an identifier used for factory-lookup and as an unique-application-name
  4. identification of a client and a server in an application-link

Without a factory only the pipe-feature without the child-feature is guaranteed to work. Other features may work, this depends of the "flexibility" of the programming-language.

The link between the MqFactoryS-identifier and the MqFactoryC is important for the future development of tclmqmsgque. Message-Routing, Service-Location and Persistent-Transactions depend on this feature.

The relationship between the MqFactoryC and the MqContextC is the same as the relationship between a type (MqFactoryS) and an object (MqContextS) of a regular programming language. The MqFactoryC define the type of the server and the MqContextC define a single object of the server process or thread.

                                     Application
|-------------------------------------------------------------------------------------|
|--------------- physical host 1 -----------------------|------ physical host 2 ------|
|-------- process-1 --------|-------- process-2 --------|-- process-3 --|---- … ------|
 thread-1     thread-2…      thread-1…     thread-2…      thread-1…       thread-…
  factory-A     factory-X     factory-Y…    factory-Z…
   object-1     object-1   object-…    …
   object-2     object-2   …
   object-3     object-3
   …              …

A server has a single MqFactoryC object per thread or process but multiple MqFactoryC objects per application. Decreasing the size and the complexity of a MqContextC object will improve the server performance. In future more fields, defined in the MqSetupS attribute of the the MqContextC object, will move into MqFactoryC object.

Thread Support and 'tclmsgque Main'

Description: a tclmsgque SERVER listen on a port and start for every incoming connetion a NEW sub-server. If a thread sub-server was choosen... with the --thread commandline-option... a new thread is created. To setup a new thread the INITIAL tcl-file is READ again and PROCS and VARIABLES are initialized. The NEW thread has it's own MqMain-Loop and so... the original MqMain-Loop is skipped. If a Factory command is used OUTSIDE of the MqMain-Loop... the initial MqFactoryS would be created TWICE. The creation of multiple MqFactoryS objects... with the SAME name... is an ERROR.

MqFactoryC CLASS

NAVI: top, up

MqFactoryC CLASS EXPORT

HandleResolve Handle-Resolve-Slot - return a MqFactoryC from netHdl or "MK_NULL" if invalid…
HandleGet

Handle-Get-Slot - returns a export-hdl to the MqFactoryC useable for external storage

MqFactoryC CLASS INTROSPECTION

Instances get head-instance from linked-list of MqFactoryS type …
Next get next instance from linked-list of MqFactoryS type
Prev

get previous instance from linked-list of MqFactoryS type

MqFactoryC CLASS MISC

GetNull

Null-Slot - return a MqFactoryC typed NULL instance …

MqFactoryC CLASS DETAILS

C-API: MqFactoryC_Class_C_API - MqFactoryC - define the class …

MqFactoryC CLASS EXPORT

MqFactoryC - Export class functions …

(static) MqFactoryC [MqFactoryC HandleResolve netHdl:MK_HDL]

top Handle-Resolve-Slot - return a MqFactoryC from netHdl or "MK_NULL" if invalid… → API: tcl_mqmsgque_MqFactoryC_HandleResolve

The MqFactoryHandleResolve undo the MqFactoryHandleGet and is intended to export a unique identifer into external code not belonging to the Programming-Language-Micro-Kernel (PLMK).

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]netHdlhandle former exported with MqFactoryHandleGet
Returns
the required handle or "MK_NULL" if netHdl is invalid

MK_HDL [$fct HandleGet]

top Handle-Get-Slot - returns a export-hdl to the MqFactoryC useable for external storage → API: tcl_mkkernel_MkObjectC_HandleGet

The export-hdl is a reference to an instance that can be stored in software and converted back into an instance using the MqFactoryHandleResolve.

The export-hdl is only valid until the Programming-Language-Micro-Kernel (PLMK) ends.

example: The export-hdl is used in rpc to identify an object across the network.

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]fctthe MqFactoryS instance to work on
Returns
the required export-hdl

MqFactoryC CLASS INTROSPECTION

MqFactoryC - Introspection class functions …

(static) MqFactoryC [MqFactoryC Instances]

top get head-instance from linked-list of MqFactoryS type … → API: tcl_mqmsgque_MqFactoryC_Instances

The head-instance is the last instance created.

MqFactoryC [$fct Next]

top get next instance from linked-list of MqFactoryS type → API: tcl_mqmsgque_MqFactoryC_Next

MqFactoryC [$fct Prev]

top get previous instance from linked-list of MqFactoryS type → API: tcl_mqmsgque_MqFactoryC_Prev

MqFactoryC CLASS MISC

MqFactoryC - Misc class functions …

(static) MqFactoryC [MqFactoryC GetNull]

top Null-Slot - return a MqFactoryC typed NULL instance … → API: tcl_mqmsgque_MqFactoryC_GetNull

MqFactoryC TOR

C-API: MqFactoryC_TOR_C_API - MqFactoryC - various functions to create, initialize and destroy a factory

(constructor,static) MqFactoryC [MqFactoryC Add constructor:class ?ident:string="MK_NULL"?]

top add a new MqFactoryC identified by factory-identifier and defined by factory-constructor … → API: tcl_mqmsgque_MqFactoryC_Add

The factory is required to get all tclmqmsgque features.

The context is a instance from a subclass of MqContextC

The constructor require a tmpl argument with default "MK_NULL"

Example from example_code.tcl setup a server called MyServer with one service MYTO

::oo::class create MyServer {
  superclass MqContextC
  ...
  <constructor> {{tmpl ""}} {
    next $tmpl
    my ConfigSetServerSetup serverSetup
    ...
  }
  method serverSetup {} {
    my ServiceCreate "MYTO" myService
    ...
  }
  ...
}

# package-main
tclmsgque::MqMsgque Main {
  ...
  # create "MyServer" factory... and make it to the default.
  set fct   [[MqFactoryC Add MyServer] Default]
  ...
}

Example from Filter5.tcl create a new context using factory F1; F2 or F3 read from the commandline

tclmsgque::MqMsgque Main {

  # create buffer-list of the application arguments
  set largs [MkBufferListC CreateLA {*}$argv]

  # add factories
  MqFactoryC Add F1
  MqFactoryC Add F2
  MqFactoryC Add F3

  # call factory using the !first! application argument
  set srv [[MqFactoryC GetCalledL $largs] New]
  try {
    # configure and start the server
    $srv LinkCreate $largs

    # start event-loop and wait forever
    $srv ProcessEvent MQ_WAIT_FOREVER
  } on error {} {

    # set the libmqmsgque error from the tcl error
    $srv ErrorCatch
  } finally {
    $srv Exit
  }
}
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]error(C-API) flag to signal how to report an error. valid values are: MK_ERROR_PANIC, MK_ERROR_PRINT, MK_ERROR_IGNORE or an other MqContextC
[in]identthe factory-identifier, if "MK_NULL" or EMPTY the class-name is used. The ident is the public identifier (name) of the factory and is used in logging-output (MqLog...) , name-resolution (MqFactoryGet...) and an first parameter in the executable-call: myserver ident ....
[in]createCallF(C-API) object constructor function
[in]constructorobject (class) constructor data
[in]createDataFreeF(C-API) object constructor data free function
[in]createDataCopyF(C-API) object copy-constructor data free function
[in]deleteCallF(C-API) object destructor function
[in]destructorobject (class) destructor data
[in]deleteDataFreeF(C-API) object destructor data free function
[in]deleteDataCopyF(C-API) object copy-constructor data free function
Returns
the new MqFactoryC or "MK_NULL" on error
See also
MqFactoryTypeAdd

(constructor,static) MqFactoryC [MqFactoryC new constructor:class ?ident:string="MK_NULL"?]

top add a new MqFactoryC identified by factory-identifier and defined by factory-constructor … → API: tcl_mqmsgque_MqFactoryC_new

The factory is required to get all tclmqmsgque features.

The context is a instance from a subclass of MqContextC

The constructor require a tmpl argument with default "MK_NULL"

Example from example_code.tcl setup a server called MyServer with one service MYTO

::oo::class create MyServer {
  superclass MqContextC
  ...
  <constructor> {{tmpl ""}} {
    next $tmpl
    my ConfigSetServerSetup serverSetup
    ...
  }
  method serverSetup {} {
    my ServiceCreate "MYTO" myService
    ...
  }
  ...
}

# package-main
tclmsgque::MqMsgque Main {
  ...
  # create "MyServer" factory... and make it to the default.
  set fct   [[MqFactoryC Add MyServer] Default]
  ...
}

Example from Filter5.tcl create a new context using factory F1; F2 or F3 read from the commandline

tclmsgque::MqMsgque Main {

  # create buffer-list of the application arguments
  set largs [MkBufferListC CreateLA {*}$argv]

  # add factories
  MqFactoryC Add F1
  MqFactoryC Add F2
  MqFactoryC Add F3

  # call factory using the !first! application argument
  set srv [[MqFactoryC GetCalledL $largs] New]
  try {
    # configure and start the server
    $srv LinkCreate $largs

    # start event-loop and wait forever
    $srv ProcessEvent MQ_WAIT_FOREVER
  } on error {} {

    # set the libmqmsgque error from the tcl error
    $srv ErrorCatch
  } finally {
    $srv Exit
  }
}
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]error(C-API) flag to signal how to report an error. valid values are: MK_ERROR_PANIC, MK_ERROR_PRINT, MK_ERROR_IGNORE or an other MqContextC
[in]identthe factory-identifier, if "MK_NULL" or EMPTY the class-name is used. The ident is the public identifier (name) of the factory and is used in logging-output (MqLog...) , name-resolution (MqFactoryGet...) and an first parameter in the executable-call: myserver ident ....
[in]createCallF(C-API) object constructor function
[in]constructorobject (class) constructor data
[in]createDataFreeF(C-API) object constructor data free function
[in]createDataCopyF(C-API) object copy-constructor data free function
[in]deleteCallF(C-API) object destructor function
[in]destructorobject (class) destructor data
[in]deleteDataFreeF(C-API) object destructor data free function
[in]deleteDataCopyF(C-API) object copy-constructor data free function
Returns
the new MqFactoryC or "MK_NULL" on error
See also
MqFactoryTypeAdd

(destructor) $fct Delete

top Destructor - delete a MqFactoryC instance … → API: MqFactoryDelete_RT

The factory-delete is more a pseudo-delete because a factory is always in-duty:

  1. The context has a link to a factory (MqSetupS::factory) → this link is not protected by the refCount.
    1. The factory-delete will modify the environment of an existing context.
  2. The factory is a singelton (like a type) → there are very "few" factories at all.
  3. The factory is shared between threads → a modification would risk a race-condition.
    1. the factory can not be modify after creation
See also
MkRefDecr MqFactoryFree

(constructor) MqFactoryC [$fct Dup2 ident:string]

top create a duplicate of the singleton object MqFactoryC using a new factory-identifer → API: tcl_mqmsgque_MqFactoryC_Dup2

MqFactoryC GET

C-API: MqFactoryC_Get_C_API - MqFactoryC - various functions to 'get' data out of a factory

(static) MqFactoryC [MqFactoryC Get ?ident:string=""?]

top return the MqFactoryC → API: tcl_mqmsgque_MqFactoryC_Get

The ident is the factory-name used with MqFactoryAdd - usually the class-name.

The following ident are also supported:

"initial"belongs to the factory with MqFactoryInitial
"default" or ""belongs to the factory with MqFactoryDefault
Parameters
[in]identthe factory-identifier to search for
Returns
the MqFactoryC or "MK_NULL" if ident was not found

(static) MqFactoryC [MqFactoryC GetCalled ?ident:string=""?]

top returns the MqFactoryC identified by ident … → API: tcl_mqmsgque_MqFactoryC_GetCalled

If multiple factories (MqFactoryAdd) are available the startup code have to choose which factory to use.
The selection is done by the factory-identifer and is taken from the ident or from the first argument of the commandline-arguments-list.

Parameters
[in]identthe factory-identifier or "" for the default MqFactoryC
Returns
the MqFactoryC or "MK_NULL" if nothing was found
See also
MqFactoryGetCalledL

(static) MqFactoryC [MqFactoryC GetCalledL largs:MkBufferListC]

top returns the MqFactoryC identified as first argument in the largs MkBufferListC … → API: tcl_mqmsgque_MqFactoryC_GetCalledL

Like MqFactoryGetCalled but the ident is taken from the MkBufferListC object that was created from the commandline-arguments-list.

Command-Line-Arguments-List
The Commandline-Argumentis-List begins with the first argument after the executable and/or the script file.
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]largsthe command-line-args or "" for the default MqFactoryC
Returns
the MqFactoryC or "MK_NULL" if nothing was found
See also
MqFactoryGetCalled

string [$fct GetOriginalIdent]

top helper function to return MqFactoryS::originalIdent → API: tcl_mqmsgque_MqFactoryC_GetOriginalIdent

Attention
The MK_STRN returned belongs to tclmqmsgque… do not free the data.

MqFactoryC MISC

C-API: MqFactoryC_Misc_C_API - MqFactoryC - various functions to work on a factory

(static) string [MqFactoryC DefaultIdent]

top return the factory-identifier of the default MqFactoryC → API: tcl_mqmsgque_MqFactoryC_DefaultIdent

(static) string [MqFactoryC InitialIdent]

top return the factory-identifier of the initial MqFactoryC → API: tcl_mqmsgque_MqFactoryC_InitialIdent

(static) MqFactoryC LogAll ?callfunc:string="MK_NULL"?

top log all "factories" to stderr → API: tcl_mqmsgque_MqFactoryC_LogAll

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]callfunca user-defined postfix to identify the calling function or the environment (default=name-of-function)

MqFactoryC [$fct Default]

top set the default-attribute to the factory … → API: tcl_mqmsgque_MqFactoryC_Default

The default-factory is used to create an MqFactoryC if MqFactoryGetCalled was not able to find a specific factory object. This is designed for a scenario with multiple factories included into a single binary and the first commandline parameter after the executable name… (position 0=executable, position 1=factory-selector)… is not related to a factory-ident… added with MqFactoryAdd.

Parameters
[in]fctthe new default MqFactoryC
Returns
the input fct

Example: from example/tcl/server.cs

static void Main(string[] argv) {
var largv = new MkBufferListC(argv);
MqFactoryCT<Server>.Add("server").Default();
MqFactoryCT<Client>.Add("client");
// "ctx" get the "Default" factory "server" ... or ... the factory "client" ...
// if string "client" is on the FIRST position in "argv"
MqContextC ctx = MqFactoryCT<MqContextC>.GetCalled(largv).New();
try {
ctx.LinkCreate(largv);
ctx.LogC("this is the log test\n",1,"test");
ctx.ProcessEvent(MqWaitOnEventE.FOREVER);
} catch (Exception ex) {
ctx.ErrorCatch (ex);
} finally {
ctx.Exit();
}
}

MqFactoryC [$fct Initial]

top set the initial-attribut to fct … → API: tcl_mqmsgque_MqFactoryC_Initial

The factory with "Initial"-attribute is always used for an object that should only be created with the MqContextC base class, but for which no other factory has been specified.
Use this attribute with care because you are firmly linking a factory. In a programming language with class-support, such as C++ or C#, this class is used for every new MqContextC object.
Where "Reflection" is available, this attribute has less meaning since the class is primarily determined from the parent object by means of "Reflection".
The "Initial" attribute is otherwise used for the "Loopback" and the "Filter" capability.

Example from Filter4.tcl set Initial attribute to a Factory

tclmsgque::MqMsgque Main {
  # !!ATTENTION!! if you put the "MqFactoryC Add" outsite of "tclmsgque::MqMsgque Main"
  # you get a error like: "...factory identifer already in use..."
  # because in a "thread" startup... you try to create a factory with SAME NAME again.
  [MqFactoryC Add Filter4 ] Initial
  set srv [Filter4 new]

  try {
    $srv LinkCreate {*}$argv
    $srv ProcessEvent MQ_WAIT_FOREVER
  } on error {} {
    $srv ErrorCatch
  } finally {
    $srv Exit
  }
}
Parameters
[in]fctthe new initial MqFactoryC
Returns
the input fct

$fct Log ?fmtobj:MkObjectC="MK_NULL"? ?debug:int32=0? ?callfunc:string="MK_NULL"? ?lvl:int32=0?

top log the MqFactoryC … → API: tcl_mqmsgque_MqFactoryC_Log

Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]fctthe MqFactoryS instance to work on
[in]fmtobjmanaged object used to format the log-message (default="MK_NULL" → use default-format)
[in]debugthe debug level from MkRuntimeS::debug, use 0 <= debug <= 9 (default=0)
[in]callfunca user-defined postfix to identify the calling function or the environment (default=name-of-function)
[in]lvla user-defined prefix starting with "" for lvl=0 and increase with " " for lvl+1 (default=0)
See also
MqFactoryC

MqContextC [$fct New]

top create a new MqContextC from a MqFactoryC … → API: tcl_mqmsgque_MqFactoryC_New

this create only the initial-server-object… all other server-objects will be created on behalf of the client-request.

Example from MyServer.tcl create a new server context

package require tclmsgque::MqMsgque
namespace import tclmsgque::MqMsgque::*
namespace import tclmsgque::MkKernel::*

# package-item
::oo::class create MyServer {
  superclass MqContextC

  # service to serve all incoming requests for token "HLWO"
  method myFirstService {} {
    my SendSTART
    my SendSTR "[my ReadSTR] World"
    my SendRETURN
  }

  # define a service as link between the token "HLWO" and the callback "MyFirstService"
  method serverSetup {} {
    my ServiceCreate "HLWO" myFirstService
  }

  # factory startup (constructor)
  constructor {{tmpl ""}} {
    next $tmpl
    my ConfigSetServerSetup serverSetup
  }
} 

# package-main
tclmsgque::MqMsgque Main {

  # setup commandline arguments for later use
  set args  [MkBufferListC CreateLA {*}$argv]

  # create "MyServer" factory... and make it to the default.
  set fct   [[MqFactoryC Add MyServer] Default]

  # inspect commandline-argument for the "factory" to choose... and create a object
  set fct   [MqFactoryC GetCalledL $args]
  set srv   [$fct New]

  try {
    $srv LinkCreate $args
    $srv ProcessEvent MQ_WAIT_FOREVER
  } on error {} {
    $srv ErrorCatch
  } finally {
    $srv Exit
  }
}
Parameters
[in]mkrtthe MkRuntimeS instance to work on - the runtime argument, used by MK_RT_CALL (C-only)
[in]fcta MqFactoryC used to create a MqContextC
[in]tmpl(C-API only) template for context intialization
[out]val_outthe new context object as return or "MK_NULL" on error
Returns
the new MqContextC or NULL on error
Attention
(C-API only)
the programmer have-to check the return value on "MK_NULL" pointer
(non C-API only)
this is no hard constructor because the factory create the object and the self pointer is already available. ObjNew is used to extract the self pointer from the object

FILTER MODE

C-API: MqContextC_FilterApi_C_API - MqContextC - modify the data using the filter-technology

The filter mode is related to a special usage of the tclmqmsgque software called a command pipeline. To define a filter create a server with:

Every filter has two context one belongs to the left command and one belongs to the right command:

 <-- left cmd --> <------- filter -------> <-- right cmd -->

                  <-- left --><- right -->
                  <- server -><- client ->
                  <- master -><- slave -->
                  <-context1-><-context2->

  ... command1   @         filter         @   command2 ...

The left context is created on application startup and the right context is created as slave of the left context.

  • if the @ argument is followed by an normal command (server) a local pipeline is created:
    client @ filter @ server
    
  • if the @ argument is followed by an option a non-local pipeline is created:
    <------------ host-1 -------------> <-- network --> <---------- host-2 ----------->
           <---- client arguments ---->                       <--- server arguments -->
                    <-- filter arg. -->
                      <--- options --->
    
    client @ filter @ --tcp --port 7777   ...........   server --tcp --port 7777 --fork
    

BI-DIRECTIONAL FILTER

A bi-directional filter allow a data-flow in both directions and is used in a classical client/server application:

    client ... <--> ... server

as a feature enhancement like a protocol-tunnelling:

    client @ mq2tunnel ... <--> ... tunnel2mq @ server

or to convert the protocol into an other protocol:

    client @ mq2soap ... <--> ... soap-server

To define a bi-directional filter a couple of commands provide support:

  • MqServiceCreate
    • use the token +ALL to add a listener for all services. This feature is used for a tunnel to modify the body at all. (example: aguard)
  • MqServiceProxy
    • use this function to link the left context with the right context identified with the slave-identifier id (default: 0). No data manipulation is performed.
  • MqSlaveGetFilter, MqSlaveGetMaster, MqSlaveGetProxy
    • in a filter service the current context is used to read the data. To send the data an other context, belonging to the other site of the communication, have to be used. This function return the context of the other site.
  • MqServiceTokenGet
    • if the token +ALL is used in ServiceCreate to add a generic service handler the current token is not known. This function return the current token.
  • MqServiceIsTransaction
    • if the token +ALL is used in ServiceCreate to add a generic service handler the current transaction-status is not known. This function return the transaction-status as boolean with true (with-transaction) or false (without-transaction).
    • with-transaction: the package was send with MqSendEND_AND_WAIT or MqSendEND_AND_CALLBACK
    • without-transaction: the package was send with MqSendEND
  • MqDumpExport
    • read and return the read-data-package as MqDumpC. Use this dump to apply a transformation to the data, like encryption (example: aguard), or to save the body in a persistent storage for later use MqDumpImport.
  • MqDumpImport
    • load the MqDumpC into the read-data-package
  • MqProxyForward

ONE-DIRECTIONAL FILTER

A one-directional filter is a special form of a bi-directional filter and allow a data-flow from the left to the right.
This filter is well known from the unix shell to link different commands together:

    command1 | command2 | command3

A tclmqmsgque command pipeline is created with the special character "@" instead of "|" :

    msgcmd1 @ msgcmd2 @ msgcmd3

To define a tclmqmsgque filter... create a service handle with MqServiceCreate or MqServiceProxy ... using the token +FTR and +EOF

token description
+FTR required to act on filter data rows. Every filter input data is a list of filter data
rows and every row is a list of filter data columns. Every row is send to the following
filter-command as +FTR service request
+EOF required to act on End-Of-Filter data and is called after all +FTR data was send.
Sometimes the filter data can not be served as +FTR data (example: sorting of the
input rows need to read all rows before the data can be send to the next filter command)
and the+EOF token is used to continue send +FTR data rows.

and send every data item with MqSendEND_AND_WAIT .

PORTABILITY ISSUES

This library is actively developed and tested on x86_64 Linux (opensuse), older versions have also been successful tested on FreeBSD, WindowsXP/7, MacOSX and Solaris using x86_64, i686, ppc and sparc processor.


EXAMPLES

1. simple client/server application

  • The simple client/server application to provide the external "MMUL" service to multiplicate 2 double values
  • The client and the server application is using the low-level MqContextC SEND API and MqContextC READ API.

a) server to provide the "MMUL" service

Example from mulserver.tcl
package require tclmsgque::MqMsgque
namespace import tclmsgque::MqMsgque::*

::oo::class create MulServer {
  superclass MqContextC
  constructor {{tmpl ""}} {
    next $tmpl
    my ConfigSetServerSetup ServerSetup
  }
  method MMUL {} {
    my SendSTART
    my SendDBL [expr {[my ReadDBL] * [my ReadDBL]}]
    my SendRETURN
  }
  method ServerSetup {} {
    my ServiceCreate "MMUL" MMUL
  }
}

tclmsgque::MqMsgque Main {
  set srv [[MqFactoryC Add MulServer "mulserver"] New]
  try {
    $srv LinkCreate {*}$argv
    $srv ProcessEvent MQ_WAIT_FOREVER
  } on error {} {
    $srv ErrorCatch
  } finally {
    $srv Exit
  }
}
Start mulserver.tcl using TCP port 7777 and spawn a new session for every incoming connection
> tclsh mulserver.tcl --tcp --port 7777 --spawn

b) client to call the "MMUL" service

Example from mulclient.tcl
package require tclmsgque::MqMsgque
tclmsgque::MqMsgque::MqContextC create ctx
ctx LinkCreate --name "MyMul" {*}$argv
ctx SendSTART
ctx SendDBL 3.67 
ctx SendDBL 22.3 
ctx SendEND_AND_WAIT "MMUL" 
puts [ctx ReadDBL]
ctx Exit
Use mulclient.tcl to connect to mulserver.tcl using TCP port 7777:
> tclsh mulclient.tcl --tcp --port 7777

2. advanced client/server application

  • The advanced client/server application to provide the external "HLWO" and the internal "LOOP" service.
  • The external "HLWO" service is calling the internal "LOOP" service.
  • The internal "LOOP" service is using a instance-attribute to return data.
  • The server is using the MqContextC HIGH API to simplify service-usage.

a) server to provide the "HLWO" service

Example from MyLoopServer.tcl
package require tclmsgque::MqMsgque
namespace import tclmsgque::MqMsgque::*

::oo::class create MyLoopServer {
  superclass MqContextC
  export variable

  # factory startup
  constructor {{tmpl ""}} {
    my variable mydata;
    next $tmpl
    my ConfigSetServerSetup ServerSetup
    # set the "mydata" attribute to the master-context
    set mydata  "Hello World";
  }

  # service to serve all EXTERNAL requests for token "HLWO"
  method HLWO_srv {} {
    # get the "loopback" context
    set loop  [my SlaveGet LOOPBACK]
    # call the LOOP service on the SAME server
    $loop Send "W" "LOOP"
    # answer HLWO with string-return from LOOP
    my Send "R" "C" [$loop ReadSTR]
  }

  # service to serve all INTERNAL requests for token "LOOP"
  method LOOP_srv {} {
    # get the "master" context
    set master  [my SlaveGetMaster]
    # answer LOOP with data from MASTER->mydata attribute
    $master variable mydata
    my Send "R" "C" $mydata
  }

  # setup a server-context - called for every new server-context
  method ServerSetup {} {
    # EXTERNAL: link the "HLWO" service with "HLWO_srv"
    my ServiceCreate "HLWO" HLWO_srv
    # INTERNAL: link the "LOOP" service with "LOOP_srv"
    [my SlaveGet MQ_SLAVE_LOOPBACK] ServiceCreate "LOOP" LOOP_srv
  }
}

tclmsgque::MqMsgque Main {

  # create "MyLoopServer" factory... and the instance
  set srv   [[MqFactoryC Add MyLoopServer] New]

  try {
    $srv LinkCreate $argv
    $srv ProcessEvent MQ_WAIT_FOREVER
  } on error {} {
    $srv ErrorCatch
  } finally {
    $srv Exit
  }
}
Start MyLoopServer.tcl using UDS file /var/loop-server.uds and thread a new session for every incoming connection
> tclsh MyLoopServer.tcl --uds --file /var/loop-server.uds --thread

b) client to call the "HLWO" service

Example from MyClient.tcl
package require tclmsgque::MqMsgque

# create a context using the static tclmsgque CTOR method "Create"
set ctx [tclmsgque::MqMsgque::MqContextC Create]
try {
  $ctx ConfigSetName "MyClient"
  $ctx LinkCreate {*}$argv
  $ctx SendSTART
  $ctx SendSTR "Hello"
  $ctx SendEND_AND_WAIT "HLWO" 
  puts [$ctx ReadSTR]
} on error {} {
  $ctx ErrorCatch
} finally {
  # delete the context using the tclmsgque APPLICATION-DTOR method "Exit"
  $ctx Exit
}
Use MyClient.tcl to connect to mulserver.tcl using UDS file /var/loop-server.uds:
> tclsh MyClient.tcl --uds --file /var/loop-server.uds

3. create a filter to wrap every column in a '<>' pair

Example from manfilter.tcl

package require tclmsgque::MqMsgque

proc FTRcmd {ctx} {
  set ftr [$ctx SlaveGetFilter]
  $ftr SendSTART
  while {[$ctx ReadItemExists]} {
    $ftr SendSTR "<[$ctx ReadSTR]>"
  }
  $ftr SendEND_AND_WAIT "+FTR"
  $ctx SendRETURN
}

tclmsgque::MqMsgque Main {
  tclmsgque::MqMsgque::MqContextC create srv
  srv ConfigSetIsServer yes
  srv ConfigSetName "filter"

  try {
    srv LinkCreate {*}$argv
    srv ServiceCreate "+FTR" FTRcmd
    srv ServiceProxy  "+EOF"
    srv ProcessEvent MQ_WAIT_FOREVER
  } on error {} {
    srv ErrorCatch
  } finally {
    srv Exit
  }
}

Use manfilter.tcl in a tclmqmsgque command pipeline:

> echo -e "1:2:3\na:b:c" | atool split -d : @ tclsh manfilter.tcl @ atool join -d :

SEE ALSO

libmqmsgque, ccmqmsgque, csmqmsgque, javamqmsgque, gomqmsgque, pymqmsgque, rbmqmsgque, tclmqmsgque, perlmqmsgque, phpmqmsgque

KEYWORDS

Tcl, unix, socket, message, msgque