|
Introduction
Eloquence B.08.30 eloqcore introduces DLG protocol version 2,
intended to improve DLG protocol performance especially for wide-area
(Internet) network connections.
To make better use of available network bandwidth, the size of a single
DLG transaction has been significantly reduced, and data compression is
selectively applied.
To lower network latency, multiple DLG transactions are batched into
a single network transmission. This requires that bulk
mode is active.
To further reduce network traffic, eloqcore maintains a cache which
holds recent attribute values. When a program invokes DLG GET, and the
addressed attribute value is stored in the cache, it can be returned
to the program without performing a network transmission.
Furthermore, the maximum string length limitation of the first DLG
protocol (8075 bytes) has been removed.
Please note:
The DLG v2 protocol is enabled when a compatible DLG server connects.
This is currently JDLG 2.0.
Bulk mode
The DLG v2 bulk protocol is enabled by default.
The eloq.config (or .eloqrc) config option OPTION DLGBULK
may be used to modify the default:
OPTION DLGBULK {0|1|2}
0 - bulk mode is not enabled by default
1 - bulk mode is enabled by default with JDLG 2.0
2 - same as (1) but DLG SET .async is ignored (force bulk mode)
The default is 1.
If bulk mode is enabled, DLG transactions are batched into a single
network transmission, which is transmitted as soon as a synchronous
DLG call is issued. Synchronous DLG calls, such as DLG GET or DLG DO,
require immediate execution.
Also, a DLG call becomes synchronous when a status return variable is
assigned. For example, DLG SET Path$,Value$;Stat requires
immediate execution to return the resulting DLG status in Stat.
The first DLG protocol supports the .async mode to reduce call
latency. If .async mode is enabled, certain DLG calls such as
DLG NEW and DLG SET are transmitted without expecting a response, thus
lowering network latency but at the same time losing status about
failed DLG calls.
The DLG v2 protocol still supports .async mode but combines it
with bulk mode (i.e., when async mode is active, bulk mode is implicitly
activated as well). This allows for enhanced diagnostics
to obtain details about failed DLG calls along with the originating location
(segment/file/line).
Furthermore, the DLG LOAD call temporarily activates bulk mode if inactive.
As a result, DLG LOAD can be executed in a single network transmission
(depending on the size of the loaded DLG file). Programs no longer need
to explicitly activate .async mode to optimize DLG LOAD performance.
When bulk mode is active and a DLG instruction issues a runtime error,
it is possible that this error is related to an earlier DLG call which
was batched previously and now turns out to have failed after the bulk
response has been received. Enhanced diagnostics
may then be used to find out about which particular DLG instruction has
failed.
While bulk mode and .async mode appear to have similar effects,
in .async mode any DLG error is ignored by default, while in
bulk mode a runtime error is triggered, but probably later when a
synchronous DLG call is executed.
Summary:
OPTION DLGBULK 1 is the default. It provides all bulk mode performance
enhancements while maintaining backward compatibility. It is recommended to
modify ON ERROR handlers to use enhanced diagnostics.
OPTION DLGBULK 2 can be used if programs don't use .async mode,
or when it is expected that all DLG calls are successful while .async
mode is active. Programs which rely on the fact that failed DLG calls are
ignored while .async mode is active may no longer work as before,
in which case OPTION DLGBULK 1 must be configured.
OPTION DLGBULK 0 might be useful when single-stepping a program while
expecting that DLG calls are executed immediately.
Related attributes:
- .bulk : integer, get/set
-
Allows to programmatically set or query the
OPTION DLGBULK configuration.
On DLG SET, the OPTION DLGBULK configuration is modified.
In addition, if the program is connected to JDLG 2.0, bulk mode is
activated or deactivated.
- .async : integer, get/set
-
Allows to programmatically activate/deactivate or query async mode.
Nonzero: async mode is active. On DLG SET, async mode is activated
and .async_status is reset.
Zero: async mode is inactive. On DLG SET, async mode is deactivated
and .async_status is updated to the status code of the first
DLG call which failed since async
mode was activated.
Note: Before Eloquence B.08.30 RC4 the value was bit-coded
(bit 0: async mode, bit 1: bulk mode). This has been changed for
full backward compatibility.
- .async_status : integer, get
-
Returns the status code of the first DLG call which failed since async
mode was activated.
Zero is returned if no DLG call failure was recorded.
Notes:
- Must be invoked after async mode was deactivated.
- Can only be queried once, i.e., DLG GET internally sets it to zero.
- If DLG protocol v2 is active, enhanced diagnostics
can be used to obtain details about which DLG call failed when
.async_status is nonzero.
Example:
DLG SET ".async",1
...
...
DLG SET ".async",0
DLG GET ".async_status",Stat
! Stat is the status of the first failed asynchronous
! DLG call since async mode was activated
! or zero if no DLG call failure was recorded
Enhanced diagnostics
When bulk mode is active and a DLG instruction issues a runtime error,
it is possible that this error is related to an earlier DLG call which
was batched previously and only now turns out to have failed after the
bulk response has been received.
When .async mode is active, failed DLG calls are ignored.
When async mode is deactivated again, .async_status is set.
In both cases, if failed DLG calls are detected which have been batched
and therefore are not related to the DLG call currently executed by
the program, detailed diagnostic information can be obtained by
configuring a log file (eloqcore -log) and setting the G1 log level
(-dG1). The calls including their arguments, the status code, and the
originating location (segment/file/line) are logged.
Example: DLG SET "main.foo",0 returning status 657 (649+8)
G1: req = DMDRV_SET
G1: obj.path = main.foo
G1: data.type = INT
G1: data.value= 0
G1: res = DMDRV_STATUS
G1: status.iv = 8
G1: DLG STATUS 657 IN SUB Setup FILE /prog/FOOBAR LINE 30
In addition, a program may use the attributes below to obtain enhanced
diagnostics if a DLG runtime error is triggered:
- .status : integer, get
-
Returns the status code of the last failed DLG call,
or returns async_status if set.
Zero is returned if no DLG call failure was recorded.
Note: Unlike .async_status, this can be queried multiple times.
Example:
DLG GET ".status",Stat;Rc
IF NOT Rc THEN
! DLG v2 extended diagnostics available
! Stat contains last DLG status or async_status
! or zero if no DLG call failure was recorded
END IF
- .status_msg : string, get
-
Returns a status message related to the last failed DLG call, or related
to the first failed DLG call since async mode was activated.
The message is formatted like below:
"DLG STATUS 657 IN SUB Setup FILE /prog/FOOBAR LINE 30"
An empty string is returned if no DLG call failure was recorded.
Example:
DLG GET ".status_msg",Msg$;Rc
IF NOT Rc THEN
! DLG v2 extended diagnostics available
! Msg$ contains DLG status message like:
! "DLG STATUS 657 IN SUB Setup FILE /prog/FOOBAR LINE 30"
! or is empty if no DLG call failure was recorded
END IF
- .status_seg : string, get
-
Returns the name of the program segment (main or SUB or FN) related
to the last failed DLG call, or related to the first failed DLG call
since async mode was activated.
An empty string is returned if no DLG call failure was recorded.
Example:
DLG GET ".status_seg",Seg$;Rc
IF NOT Rc THEN
! DLG v2 extended diagnostics available
! Seg$ contains the segment name (main or SUB or FN)
! or is empty if no DLG call failure was recorded
END IF
- .status_file : string, get
-
Returns the file name related to the last failed DLG call, or related
to the first failed DLG call since async mode was activated.
An empty string is returned if no DLG call failure was recorded.
Example:
DLG GET ".status_file",File$;Rc
IF NOT Rc THEN
! DLG v2 extended diagnostics available
! File$ contains the file name
! or is empty if no DLG call failure was recorded
END IF
- .status_line : integer, get
-
Returns the line number related to the last failed DLG call, or related
to the first failed DLG call since async mode was activated.
Zero is returned if no DLG call failure was recorded.
Example:
DLG GET ".status_line",Line;Rc
IF NOT Rc THEN
! DLG v2 extended diagnostics available
! Line contains the line number
! or zero if no DLG call failure was recorded
END IF
Error handler examples
Programs can now integrate enhanced DLG error diagnostics
in their ON ERROR handler. The example below checks whether a DLG status
message is available, the error handler could then for example output it
to a log file:
DLG GET ".status_msg",Msg$;Rc
IF NOT Rc AND LEN(Msg$) THEN
! DLG v2 status message available
! Msg$ contains DLG status message like:
! "DLG STATUS 657 IN SUB Setup FILE /prog/FOOBAR LINE 30"
...
END IF
Alternatively, the components of a DLG status message can be obtained
as separate elements:
DLG GET ".status",Stat;Rc
IF NOT Rc AND Stat THEN
! DLG v2 status available
! Stat contains last DLG status or async_status
DLG GET ".status_seg",Seg$
! Seg$ contains the segment name (main or SUB or FN)
DLG GET ".status_file",File$
! File$ contains the file name
DLG GET ".status_line",Line
! Line contains the line number
...
END IF
When .async mode is used, .async_status may be
queried after .async mode has been deactivated.
The example below demonstrates how a nonzero .async_status
is turned into a DLG runtime error so that the ON ERROR handler is
invoked:
DLG SET ".async",1
...
...
DLG SET ".async",0
DLG GET ".async_status",Stat
IF Stat THEN FORCE ERROR Stat
Statistics
If DLG protocol v2 is active and JDLG 2.0 disconnects, typically at the end
of a program, DLG statistics can be obtained by configuring a log file
(eloqcore -log) and setting the G1 log level (-dG1).
DLG SET ".reset_statistics",0 may be called to log intermediate
statistics (see below).
Example:
G1: --- DLG Statistics
G1: DLG calls : 103573
G1: Client/server : 3723 (3.59457%)
G1: GET calls : 96147
G1: GET cached : 92450 (96.1548%)
G1: Values cached : 3699
G1: Values bytes : 136915
Lines having a zero value are not logged.
- DLG calls: The total number of DLG calls the program has issued.
- Client/server: The number of network transmissions.
- GET calls: The total number of DLG GET calls.
- GET cached: The number of DLG GET calls which did not require
a network transmission because the value was returned from the cache.
- Values cached: The maximum number of cached values.
- Values bytes: The maximum number of bytes used for cached values.
The ratio between DLG calls and client/server transmissions indicates how
efficiently bulk mode has reduced the number of network transmissions. In the
above example, 103573 DLG calls resulted in 3723 network transmissions, which
is a ratio of ~3.6%. The previous DLG protocol would have used 100% (103573
network transmissions).
The ratio of GET calls and GET cached indicates how efficiently a program uses
the cache. In the above example, the efficiency is ~96%, which means that only
~4% of all DLG GET calls required a network transmission.
In addition, a program may use the attributes below to programmatically
obtain or reset the statistics:
- .statistics : string, get
-
Returns the current statistics, as shown in the above example. Lines are
separated by LF (ASCII 10).
Lines having a zero value are not returned. An empty string is returned if
no statistics have been collected so far.
- .statistics[] : integer or string, get
-
May be used to obtain a specific statistics entry, for example the number of
DLG GET calls, which is 96147 in the above example.
When used with a positive index (starting with 1), the statistics value of
the corresponding line is returned as integer. For example, line 3 contains
the number of DLG GET calls, so DLG GET ".statistics[3]",St would
set St to 96147 in the above example. Zero is returned if the index
is out of range.
When used with a negative index (starting with -1), the statistics title of
the corresponding line is returned as string. For example, line 3 contains
the number of DLG GET calls, so DLG GET ".statistics[-3]",St_title$
sets St_title$ to "GET calls". An empty string is returned if the
index is out of range.
- .reset_statistics : integer, set
-
Resets the statistics. The value is ignored.
The current statistics are logged if the G1 log level is set and any
statistics have been collected so far.
|
|