Conversion Utilities

The conversion utilities are:

%DH: Decimal to hexadecimal conversion.

%DO: Decimal to octal conversion.

%HD: Hexadecimal to decimal conversion.

%HO: Hexadecimal to octal conversion.

%LCASE: Converts a string to all lower case.

%OD: Octal to decimal conversion.

%OH: Octal to hexadecimal conversion.

%UCASE: Converts a string to all upper case.

The conversion utilities can be invoked as extrinsic functions.

While the radix conversions work for very long values, the performance degrades with length and may be impractical beyond some point. If your application limits the input(s) and performance is important, you can get some speed improvement by eliminating behavior on which your code does not rely.

%DH

The %DH utility converts numeric values from decimal to hexadecimal. %DH defaults the length of its output to eight digits. However the input variable %DL overrides the default and controls the length of the output. The routine has entry points for interactive or non-interactive use.

Utility Labels

INT: Converts interactively entered decimal number to hexadecimal number with the number of digits specified.

FUNC(d[,l]): Invokes %DH as an extrinsic function returning the hexadecimal equivalent of the argument.

Input Variables

%DH: As input, contains input decimal number.

%DL: Specifies how many digits appear in the output, defaults to eight.

Prompts

Decimal: Requests a decimal number for conversion to hexadecimal.

Digits: Requests the length of the output in digits; eight by default.

Output Variables

%DH: As output, contains the converted number in hexadecimal.

Examples of %DH

Example:

GTM>DO INT^%DH 
Decimal: 12
Digits: 1
GTM>ZWRITE 
%DH="C" 

This example invokes %DH interactively with INT^%DH. %DH prompts for a decimal number and output length, then returns the result in the variable %DH. ZWRITE displays the contents of the variables.

Example:

GTM>SET %DH=12
GTM>DO ^%DH
GTM>ZWRITE
%DH="0000000C"
%DL=8 

This example sets the read-write variable %DH to 12 and invokes %DH to convert the number to a hexadecimal number. Because the number of digits was not specified, %DH used the default of 8 digits. Set %DL to specify the number of output digits.

Example:

GTM>WRITE $$FUNC^%DH(12,4)
000C

This example invokes %DH as an extrinsic function using the FUNC label. The first argument specifies the input decimal number and the optional, second argument specifies the number of output digits. If the extrinsic does not have a second argument, the length of the output defaults to eight characters.

%DO

The %DO utility converts numeric values from decimal to octal. The default length of its output is 12 digits. The value assigned to the input variable %DL overrides the default and controls the length of the output. The routine has entry points for interactive or non-interactive use.

Utility Labels

INT: Converts the specified decimal number to an octal number with the specified number of digits, interactively.

FUNC(d[,ln]): Invokes %DO as an extrinsic function, returning the octal equivalent of the argument.

Prompts

Decimal: Requests a decimal number for conversion to octal.

Digits: Requests the length of the output in digits; 12 by default.

Input Variables

%DO: As input, contains input decimal number.

%DL: Specifies the number of digits in the output, defaults to 12.

Output Variables

%DO: As output, contains the converted number in octal.

Examples of %DO

Example:

GTM>DO INT^%DO 
Decimal: 12
Digits: 4
GTM>ZWRITE
%DO="0014"

This example invokes %DO interactively with INT^%DO. %DO prompts for a decimal number and an output length. If the output value of %DO has leading zeros, the value is a string. ZWRITE displays the contents of the variables.

Example:

GTM>SET %DO=12 
GTM>DO ^%DO
GTM>ZWRITE
%DO="000000000014"

This example sets the read-write variable %DO to 12 and invokes %DO to convert the number non-interactively. Because the number of digits was not specified, %DO used the default of 12 digits. Set %DL to specify the number of output digits. ZWRITE displays the contents of the variables.

Example:

GTM>WRITE $$FUNC^%DO(12,7)
0000014 

This example invokes %DO as an extrinsic function with the label FUNC. The first argument specifies the number to be converted and the optional, second argument specifies the number of output digits. If the second argument is not specified, %DO uses the default of 12 digits.

%HD

The %HD utility converts numeric values from hexadecimal to decimal. %HD returns the decimal number in the read-write variable %HD. %HD rejects input numbers beginning with a minus (-) sign and returns null (""). The routine has entry points for interactive or non-interactive use.

Utility Labels

INT: Converts hexadecimal number entered interactively to decimal number.

FUNC(h): Invokes %HD as an extrinsic function returning the decimal equivalent of the argument.

Prompts

Hexadecimal: Requests a hexadecimal number for conversion to decimal.

Input Variables

%HD: As input, contains input hexadecimal number.

Output Variables

%HD: As output, contains the converted number in decimal.

Examples of %HD

Example:

GTM>DO INT^%HD
Hexadecimal:E
GTM>ZWRITE
%HD=14

This example invokes %HD in interactive mode with INT^%HD. %HD prompts for a hexadecimal number, then returns the converted number in the variable %HD. ZWRITE displays the contents of the variable.

Example:

GTM>SET %HD="E" 
GTM>DO ^%HD
GTM>ZWRITE
%HD=14

This example sets the read-write variable %HD to "E" and invokes %HD to convert non-interactively the value of %HD to a decimal number. %HD places the converted value into the read-write variable %HD.

Example:

GTM>WRITE $$FUNC^%HD("E")
14

This example invokes %HD as an extrinsic function with the label FUNC and writes the results.

%HO

The %HO utility converts numeric values from hexadecimal to octal. %HO returns the octal number in the read-write variable %HO. %HO rejects input numbers beginning with a minus (-) sign and returns null (""). The routine has entry points for interactive or non-interactive use.

Utility Labels

INT: Converts hexadecimal number entered interactively to octal number.

FUNC(h): Invokes %HO as an extrinsic function returning the octal equivalent of the argument.

Prompts

Hexadecimal: Requests a hexadecimal number for conversion to octal.

Input Variables

%HO: As input, contains input hexadecimal number.

Output Variables

%HO: As output, contains the converted number in octal.

Examples of %HO

Example:

GTM>DO INT^%HO
Hexadecimal:C3
GTM>ZWRITE
%HO=303

This example invokes %HO in interactive mode using INT^%HO. %HO prompts for a hexadecimal number that it converts to an octal number. ZWRITE displays the contents of the variable.

Example:

GTM>SET %HO="C3"
GTM>DO ^%HO
GTM>ZWRITE
%HO=303 

This example sets the read-write variable %HO to "C3" and invokes %HO to convert the value of %HO non-interactively. ZWRITE displays the contents of the variable.

Example:

GTM>WRITE $$FUNC^%HO("C3")
303

This example invokes %HO as an extrinsic function with the FUNC label.

%JSWRITE

The ^%JSWRITE utility routine converts a glvn structure or a series of SET @ arguments to a string of JS objects. The format of the ^%JSWRITE utility is:

^%JSWRITE(glvnode,[expr1,expr2])
  • glvnode specifies the string containing the subscripted/unsubscripted global or local variable name. When glvnode evaluates to an empty string ("") or there are no arguments, %JSWRITE considers all subscripted local variables in scope for conversion.

  • If expr1 specifies "#", ^%JSWRITE displays JS objects of the entire tree starting from the glvnode till the end of the glvn.

  • If expr1 specifies "*", ^%JSWRITE displays JS objects for all nodes descending from the specified glvn node.

  • Specifying "*" and "#" together produces an ILLEGALEXPR2 error.

  • Specifying [expr1], that is, with a leading "["and trailing "]", ^%JSWRITE displays the JSON objects in an array collection. Without [], you need to transform the object strings to the desired destination object format.

  • If expr2 specifies "noglvname", ^%JSWRITE excludes the first key containing the name of the glvn root from the JS object output.

  • The default $ETRAP for %JSWRITE is if (""=$etrap) new $etrap set $etrap="do errorobj"_"^"_$text(+0),$zstatus="". To override the default error handler, set $ETRAP to any non-empty value.

  • GT.M is not a JavaScript runtime environment. Therefore, we recommend parsing all output of ^%JSWRITE either using a JSON parser such as JSON.parse() in an appropriate JavaScript run-time environment, a web server via setting its response header to 'Content-Type:application/json', or an application where JSON parsing is available.

  • When appropriate, enclose invocations of ^%JSWRITE in a TSTART/COMMIT boundary to prevent any blurred copy of data that is actively updated.

  • When appropriate, use GT.M alias containers to take appropriate local variables temporarily out of scope and then run the argumentless form of ^%JSWRITE.

Examples:

# Demo lv
GTM>zwrite demodevtest
demodevtest("Developer1","Token1","testSetup")="runtest holt maintest cpipe"
demodevtest("Developer1","Token1","testSetup","65401,11987")=1
demodevtest("Developer1","Token1","testSetup","holt","t")="mtest"
demodevtest("Developer1","Token1","testSetup","holt","t","SendReport",65401,12073)=1
demodevtest("Developer1","Token1","testSetup","holt","t","cpipe",65401,12025)=0
demodevtest("Developer1","Token2","testSetup")="runtest holt maintest tconv"
demodevtest("Developer1","Token2","testSetup","holt","65401,21987")=1
demodevtest("Developer1","Token2","testSetup","holt","t")="mtest"
demodevtest("Developer1","Token2","testSetup","holt","t","SendReport",65401,22073)=1
demodevtest("Developer1","Token2","testSetup","holt","t","tconv",65401,22025)=0
demodevtest("Developer2","Token3","testSetup")="runtest holt maintest tconv"
demodevtest("Developer2","Token3","testSetup","holt","65401,21987")=1
demodevtest("Developer2","Token3","testSetup","holt","t")="mtest"
demodevtest("Developer2","Token3","testSetup","holt","t","SendReport",65401,22073)=1
demodevtest("Developer2","Token3","testSetup","holt","t","tconv",65401,22025)=0
demodevtest("Developer3","Token4","testSetup")="runtest holt maintest tconv"
demodevtest("Developer3","Token4","testSetup","holt","65401,31987")=1
demodevtest("Developer3","Token4","testSetup","holt","t")="mtest"
demodevtest("Developer3","Token4","testSetup","holt","t","SendReport",65401,32073)=1
demodevtest("Developer3","Token4","testSetup","holt","t","tconv",65401,32025)=0
    
GTM>set glvn="demodevtest(""Developer2"")" 
    
GTM>do ^%JSWRITE(glvn,"*") ; JS Object Strings: All descendants of demodevtest("Developer2") 
{"demodevtest":{"Developer2":{"Token3":{"testSetup":"runtest holt maintest tconv"}}}}
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"65401,21987":1}}}}}}
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":"mtest"}}}}}}
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":{"SendReport":{"65401":{"22073":1}}}}}}}}}
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":{"tconv":{"65401":{"22025":0}}}}}}}}}
    
GTM>do ^%JSWRITE(glvn,"[*]") ; Array: All descendants of demodevtest("Developer2") 
[{"demodevtest":{"Developer2":{"Token3":{"testSetup":"runtest holt maintest tconv"}}}},
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"65401,21987":1}}}}}},
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":"mtest"}}}}}},
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":{"SendReport":{"65401":{"22073":1}}}}}}}}},
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":{"tconv":{"65401":{"22025":0}}}}}}}}}]
    
GTM> do ^%JSWRITE(glvn,"#") ; JS Object Strings: All descendants of demodevtest starting from demodevtest("Developer2") 
{"demodevtest":{"Developer2":{"Token3":{"testSetup":"runtest holt maintest tconv"}}}}
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"65401,21987":1}}}}}}
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":"mtest"}}}}}}
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":{"SendReport":{"65401":{"22073":1}}}}}}}}}
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":{"tconv":{"65401":{"22025":0}}}}}}}}}
{"demodevtest":{"Developer3":{"Token4":{"testSetup":"runtest holt maintest tconv"}}}}
{"demodevtest":{"Developer3":{"Token4":{"testSetup":{"holt":{"65401,31987":1}}}}}}
{"demodevtest":{"Developer3":{"Token4":{"testSetup":{"holt":{"t":"mtest"}}}}}}
{"demodevtest":{"Developer3":{"Token4":{"testSetup":{"holt":{"t":{"SendReport":{"65401":{"32073":1}}}}}}}}}
{"demodevtest":{"Developer3":{"Token4":{"testSetup":{"holt":{"t":{"tconv":{"65401":{"32025":0}}}}}}}}}
    
GTM>do ^%JSWRITE(glvn,"[#]") ; Array: All descendants of demodevtest starting from demodevtest("Developer2") 
[{"demodevtest":{"Developer2":{"Token3":{"testSetup":"runtest holt maintest tconv"}}}},
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"65401,21987":1}}}}}},
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":"mtest"}}}}}},
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":{"SendReport":{"65401":{"22073":1}}}}}}}}},
{"demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":{"tconv":{"65401":{"22025":0}}}}}}}}},
{"demodevtest":{"Developer3":{"Token4":{"testSetup":"runtest holt maintest tconv"}}}},
{"demodevtest":{"Developer3":{"Token4":{"testSetup":{"holt":{"65401,31987":1}}}}}},
{"demodevtest":{"Developer3":{"Token4":{"testSetup":{"holt":{"t":"mtest"}}}}}},
{"demodevtest":{"Developer3":{"Token4":{"testSetup":{"holt":{"t":{"SendReport":{"65401":{"32073":1}}}}}}}}},
{"demodevtest":{"Developer3":{"Token4":{"testSetup":{"holt":{"t":{"tconv":{"65401":{"32025":0}}}}}}}}}]
    
$ $gtm_dist/mumps -r %XCMD 'ZWRITE ^demodevtest' | $gtm_dist/mumps -r STDIN^%JSWRITE
[{"^demodevtest":{"Developer1":{"Token1":{"testSetup":"runtest holt maintest cpipe"}}}},
{"^demodevtest":{"Developer1":{"Token1":{"testSetup":{"65401,11987":1}}}}},
{"^demodevtest":{"Developer1":{"Token1":{"testSetup":{"holt":{"t":"mtest"}}}}}},
{"^demodevtest":{"Developer1":{"Token1":{"testSetup":{"holt":{"t":{"SendReport":{"65401":{"12073":1}}}}}}}}},
{"^demodevtest":{"Developer1":{"Token1":{"testSetup":{"holt":{"t":{"cpipe":{"65401":{"12025":0}}}}}}}}},
{"^demodevtest":{"Developer1":{"Token2":{"testSetup":"runtest holt maintest tconv"}}}},
{"^demodevtest":{"Developer1":{"Token2":{"testSetup":{"holt":{"65401,21987":1}}}}}},
{"^demodevtest":{"Developer1":{"Token2":{"testSetup":{"holt":{"t":"mtest"}}}}}},
{"^demodevtest":{"Developer1":{"Token2":{"testSetup":{"holt":{"t":{"SendReport":{"65401":{"22073":1}}}}}}}}},
{"^demodevtest":{"Developer1":{"Token2":{"testSetup":{"holt":{"t":{"tconv":{"65401":{"22025":0}}}}}}}}},
{"^demodevtest":{"Developer2":{"Token3":{"testSetup":"runtest holt maintest tconv"}}}},
{"^demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"65401,21987":1}}}}}},
{"^demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":"mtest"}}}}}},
{"^demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":{"SendReport":{"65401":{"22073":1}}}}}}}}},
{"^demodevtest":{"Developer2":{"Token3":{"testSetup":{"holt":{"t":{"tconv":{"65401":{"22025":0}}}}}}}}},
{"^demodevtest":{"Developer3":{"Token4":{"testSetup":"runtest holt maintest tconv"}}}},
{"^demodevtest":{"Developer3":{"Token4":{"testSetup":{"holt":{"65401,31987":1}}}}}},
{"^demodevtest":{"Developer3":{"Token4":{"testSetup":{"holt":{"t":"mtest"}}}}}},
{"^demodevtest":{"Developer3":{"Token4":{"testSetup":{"holt":{"t":{"SendReport":{"65401":{"32073":1}}}}}}}}},
{"^demodevtest":{"Developer3":{"Token4":{"testSetup":{"holt":{"t":{"tconv":{"65401":{"32025":0}}}}}}}}}]

Utility Label:

STDIN^%JSWRITE [singlesub]

With the STDIN, the %JSWRITE utility routine expects a valid SET @ argument (like the one from the ZWRITE command) as its standard input over a named/unnamed pipe device and returns an array of objects. This construct ensures that $ZUSEDSTOR remains consistently low even for processing large data for conversion. STDIN^%JSWRITE automatically terminates the process with a non-zero exit status when it does not receive a READ terminator for 120 seconds from standard input.

When "singlesub" is specified as an argument, ^%JSWRITE expects ZWRITE lines for single subscript glvns. Here ^%JSWRITE implicitly removes the unsubscripted glvn name and returns an array collection of objects in the form of [{"key1":value,"key2":value,...},{"key1":value,"key2":value,...}] where:

  • key1 is the subscript

  • value is the right side of the =.

The subscript first received by STDIN^%JSWRITE singlesub denotes the start of the object. When ^%JSWRITE finds the same subscript, it ends the current object boundary and starts the boundary of a new object.

Example:

$ $gtm_dist/mumps -r ^RTN
abc("firstname")="John"
abc("lastname")="Doe"
abc("firstname")="Jane"
abc("lastname")="Doe"
  
$ $gtm_dist/mumps -r ^RTN | $gtm_dist/mumps -r STDIN^%JSWRITE singlesub
[{"firstname":"John","lastname":"Doe"},
{"firstname":"Jane","lastname":"Doe"}]

The fis-gtm-jswrite.tar.gz npm package

Overview

fis-gtm-jswrite.tar.gz is an npm package containing four ^%JSWRITE reference implementations and three examples for the ^%JSWRITE utility routine. It also includes a utility class called JSWRITE.js to help process the output of the ^%JSWRITE utility routine for use in a JavaScript runtime environment and convert JavaScript objects to SET @ arguments.

The fis-gtm-jswrite.tar.gz package is available only for supported GT.M customers from the FIS Client Portal (https://my.fisglobal.com/products/gtm). Being a supported GT.M customer entitles you to receive package patches and upgrades under the terms of your support agreement. Note that the license for the fis-gtm-jswrite.tar.gz does not permit redistribution. You may use the fis-gtm-jswrite.tar.gz package as-is or modify as appropriate to suit your needs. In both the cases, you must adequately test the reference implementations and the utility class before using them in a production environment. Please contact gtmsupport@fisglobal.com or your support channel for more information on obtaining this package.

The ^%JSWRITE reference implementations are:

  1. Dynamic Journal File Progress Bar: GTMJSJNLCHAIN.m/gtmjsjnlchain.js

  2. Global Buffers Dashboard: GTMJSACCESSBG.m/gtmjsaccessbg.js

  3. Journal File Chain Report: GTMJSJNLCHAIN.m/gtmjsdbjnl.js

  4. %YGBLSTATS Sparkline Chart and %YGBLSTATS to JSON: GTMJSGVSTATS.m/gtmjsgvstats.js

The examples are:

  1. gtmjstree.js (renders ^sampletree in the form of a tree)

  2. gtmjs-sql1.js (a simple example)

  3. gtmjs-sql2.js (a simple example)

  4. gtmjs-to-gtm.js (example of JSWRITE.js helper class)

Installation

Step 1: Install node.js and npm

curl -sL https://deb.nodesource.com/setup_13.x | sudo -E bash -
sudo apt-get install -y nodejs
curl -L https://www.npmjs.com/install.sh | sh

Step 2: Install the fis-gtm-jswrite npm package

cd $project_dir
npm install /path/to/fis-gtm-jswrite.tar.gz # This command installs the @fis-gtm/jswrite package and the relevant %JSWRITE reference implementation dependencies. 
npm audit --fix

Step 3: Run the %JSWRITE reference implementations

# The following reference implementations use the "STDIN^%JSWRITE singlesub" entry point and require the gtmposix plugin.
export gtmroutines="node_modules/@fis-gtm/jswrite/reference_implementations $gtmroutines"      # include the reference_implementations directory in the search list
node node_modules/@fis-gtm/jswrite/reference_implementations/gtmjsjnlchain.js  # journal file chain status sheet  
node node_modules/@fis-gtm/jswrite/reference_implementations/gtmjsaccessbg.js  # %dirty buffer dashboard 
node node_modules/@fis-gtm/jswrite/reference_implementations/gtmjsdbjnl.js     # displays the size of the database and journal files 
# Set the environment variable LC_ALL to a UTF8 locale (needed for the %JSWRITE Sparkline Chart (GTMJSGVSTATS.m/gtmjsgvstats.js) reference implementation)
node node_modules/@fis-gtm/jswrite/reference_implementations/gtmjsgvstats.js   # By default, this reference implementation displays a sparkline chart for SETs and GETs. For monitoring other statistics, open gtmjsgvstats.js and update the STAT array to include the list of statistics which require sparkline chart style monitoring.  

Step 4: Run the examples

Create a sandbox environment for GT.M and run the following commands:

$gtm_dist/mupip set -key_size=1019 -region "*"
$gtm_dist/mupip load node_modules/@fis-gtm/jswrite/examples/sample.zwr
$gtm_dist/mupip load node_modules/@fis-gtm/jswrite/examples/sampletree.zwr
export "gtmroutines=node_modules/@fis-gtm/jswrite/examples/ $gtmroutines"
 
# The following example uses the do ^%JSWRITE("^sample","[*]") entry point. This uses the lodash library to merge the nodes coming from %JSWRITE. 
npm install lodash@latest
node node_modules/@fis-gtm/jswrite/examples/gtmjstree.js     # loads sample.zwr in the tree format
# The following two examples use the STDIN^%JSWRITE entry point of the %JSWRITE utility routine and then use the getter methods of the JSWRITE.js helper class to create the SQL queries. 
npm install alasql@latest
node node_modules/@fis-gtm/jswrite/examples/gtmjs-sql1.js
npm install sqlite3@latest
node node_modules/@fis-gtm/jswrite/examples/gtmjs-sql2.js
# The following example uses the @fis-gtm/jswrite helper class (JSWRITE.js) to send data back to GT.M in SET @ argument form using shelljs.
npm install shelljs@latest
node node_modules/@fis-gtm/jswrite/examples/gtmjs-to-gtm.js
Dynamic Journal File Progress Bar

The dynamic journal file progress bar displays the size progress of a journal file till it reaches the autoswitch limit. It also displays an estimation of time and speed at which a journal file reaches its autoswitch limit. This can be use for benchmarking purposes or as a tool for GT.M performance tuning.

This %JSWRITE reference implementation uses the STDIN^%JSWRITE singlesub entrypoint of the %JSWRITE utility routine.

Example:

$ node node_modules/@fis-gtm/jswrite/reference_implementations/gtmjsjnlprogress.js
Press <Ctrl> + c to terminate. refreshInterval is 3 seconds
DEFAULT [===-------------------------------------] 7% | Size: 303.7 MiB | Autoswitch: 4095 MiB | ETA: 5m40s | Speed: 15.233 MiB/s
REGIONA [=========-------------------------------] 21% | Size: 876 MiB | Autoswitch: 4095 MiB | ETA: 5m15s | Speed: 14 MiB/s
REGIONB [=========-------------------------------] 23% | Size: 962 MiB | Autoswitch: 4095 MiB | ETA: 4m40s | Speed: 15 MiB/s
REGIONC [=========-------------------------------] 21% | Size: 876.12 MiB | Autoswitch: 4095 MiB | ETA: 5m15s | Speed: 14.04 MiB/s

This %JSWRITE reference implementation monitors the size of the journal files and displays an estimate of time and speed for reaching the autoswitch limit.

Journal File Chain Report

The journal file chain report display the journal file chain starting from the current journal file for reach region. This reference implementation also displays the "out-of-chain" journal files, that is, those journal files which are broken and do not participate in journal recovery in normal circumstances. These out-of-chain journal files can be removed at the discretion of the GT.M database administrator to make space available.

This %JSWRITE reference implementation uses the STDIN^%JSWRITE singlesub entrypoint of the %JSWRITE utility routine.

Example:

$ node node_modules/@fis-gtm/jswrite/reference_implementations/gtmjsjnlchain.js
# Journal File Chain Report
| Region     | Journal File                          | Size (MiB) | Switch Date          | Back link                    | Chain status |
| :--------- | :------------------------------------ | ---------: | :------------------- | :--------------------------- | ------------ |
| GTMWIZARDS | /path/to/gtmwizards.mjl               |       0.07 | current              | gtmwizards.mjl_2020063121042 | In chain     |
| GTMWIZARDS | /path/to/gtmwizards.mjl_2020063121042 |       0.07 | 03-MAR-2020 12:10:42 | gtmwizards.mjl_2020063121035 | In chain     |
| GTMWIZARDS | /path/to/gtmwizards.mjl_2020063121035 |       0.07 | 03-MAR-2020 12:10:35 | -                            | In chain     |
| REGIONA    | /path/to/regiona.mjl                  |       0.07 | current              | regiona.mjl_2020063121042    | In chain     |
| REGIONA    | /path/to/regiona.mjl_2020063121042    |       0.07 | 03-MAR-2020 12:10:42 | regiona.mjl_2020063121035    | In chain     |
| REGIONA    | /path/to/regiona.mjl_2020063121035    |       0.07 | 03-MAR-2020 12:10:35 | -                            | In chain     |
| REGIONB    | /path/to/regionb.mjl                  |       0.07 | current              | regionb.mjl_2020063121042    | In chain     |
| REGIONB    | /path/to/regionb.mjl_2020063121042    |       0.07 | 03-MAR-2020 12:10:42 | regionb.mjl_2020063121035    | In chain     |
| REGIONB    | /path/to/regionb.mjl_2020063121035    |       0.07 | 03-MAR-2020 12:10:35 | -                            | In chain     |
| REGIONC    | /path/to/regionc.mjl                  |       0.07 | current              | regionc.mjl_2020063121042    | In chain     |
| REGIONC    | /path/to/regionc.mjl_2020063121042    |       0.07 | 03-MAR-2020 12:10:42 | regionc.mjl_2020063121035    | In chain     |
| REGIONC    | /path/to/regionc.mjl_2020063121035    |       0.07 | 03-MAR-2020 12:10:35 | -                            | In chain     |
| N/A        | /path/to/gtmwizards.mjl_2020063120753 |       0.07 | 03-MAR-2020 12:07:53 | -                            | Out of chain |
| N/A        | /path/to/gtmwizards.mjl_2020063120800 |       0.07 | 03-MAR-2020 12:08:00 | -                            | Out of chain |
| N/A        | /path/to/gtmwizards.mjl_2020063120801 |       0.07 | 03-MAR-2020 12:08:01 | gtmwizards.mjl_2020063120800 | Out of chain |
| N/A        | /path/to/gtmwizards.mjl_2020063120812 |       0.07 | 03-MAR-2020 12:08:12 | gtmwizards.mjl_2020063120801 | Out of chain |
| N/A        | /path/to/gtmwizards.mjl_2020063120822 |       0.07 | 03-MAR-2020 12:08:22 | gtmwizards.mjl_2020063120812 | Out of chain |
| N/A        | /path/to/gtmwizards.mjl_2020063121026 |       0.07 | 03-MAR-2020 12:10:26 | gtmwizards.mjl_2020063120822 | Out of chain |
| N/A        | /path/to/regiona.mjl_2020063120753    |       0.07 | 03-MAR-2020 12:07:53 | -                            | Out of chain |
| N/A        | /path/to/regiona.mjl_2020063120800    |       0.07 | 03-MAR-2020 12:08:00 | -                            | Out of chain |
| N/A        | /path/to/regiona.mjl_2020063120801    |       0.07 | 03-MAR-2020 12:08:01 | regiona.mjl_2020063120800    | Out of chain |
| N/A        | /path/to/regiona.mjl_2020063120812    |       0.07 | 03-MAR-2020 12:08:12 | regiona.mjl_2020063120801    | Out of chain |
| N/A        | /path/to/regiona.mjl_2020063120822    |       0.07 | 03-MAR-2020 12:08:22 | regiona.mjl_2020063120812    | Out of chain |
| N/A        | /path/to/regiona.mjl_2020063121026    |       0.07 | 03-MAR-2020 12:10:26 | regiona.mjl_2020063120822    | Out of chain |
| N/A        | /path/to/regionb.mjl_2020063120753    |       0.07 | 03-MAR-2020 12:07:53 | -                            | Out of chain |
| N/A        | /path/to/regionb.mjl_2020063120800    |       0.07 | 03-MAR-2020 12:08:00 | -                            | Out of chain |
| N/A        | /path/to/regionb.mjl_2020063120801    |       0.07 | 03-MAR-2020 12:08:01 | regionb.mjl_2020063120800    | Out of chain |
| N/A        | /path/to/regionb.mjl_2020063120812    |       0.07 | 03-MAR-2020 12:08:12 | regionb.mjl_2020063120801    | Out of chain |
| N/A        | /path/to/regionb.mjl_2020063120822    |       0.07 | 03-MAR-2020 12:08:22 | regionb.mjl_2020063120812    | Out of chain |
| N/A        | /path/to/regionb.mjl_2020063121026    |       0.07 | 03-MAR-2020 12:10:26 | regionb.mjl_2020063120822    | Out of chain |
| N/A        | /path/to/regionc.mjl_2020063120753    |       0.07 | 03-MAR-2020 12:07:53 | -                            | Out of chain |
| N/A        | /path/to/regionc.mjl_2020063120800    |       0.07 | 03-MAR-2020 12:08:00 | -                            | Out of chain |
| N/A        | /path/to/regionc.mjl_2020063120801    |       0.07 | 03-MAR-2020 12:08:01 | regionc.mjl_2020063120800    | Out of chain |
| N/A        | /path/to/regionc.mjl_2020063120812    |       0.07 | 03-MAR-2020 12:08:12 | regionc.mjl_2020063120801    | Out of chain |
| N/A        | /path/to/regionc.mjl_2020063120822    |       0.07 | 03-MAR-2020 12:08:22 | regionc.mjl_2020063120812    | Out of chain |
| N/A        | /path/to/regionc.mjl_2020063121026    |       0.07 | 03-MAR-2020 12:10:26 | regionc.mjl_2020063120822    | Out of chain |
# Out of chain journal files:
 /path/to/gtmwizards.mjl_2020063120753 /path/to/gtmwizards.mjl_2020063120800 /path/to/gtmwizards.mjl_2020063120801 /path/to/gtmwizards.mjl_2020063120812 /path/to/gtmwizards.mjl_2020063120822 /path/to/gtmwizards.mjl_2020063121026 /path/to/regiona.mjl_2020063120753 /path/to/regiona.mjl_2020063120800 /path/to/regiona.mjl_2020063120801 /path/to/regiona.mjl_2020063120812 /path/to/regiona.mjl_2020063120822 /path/to/regiona.mjl_2020063121026 /path/to/regionb.mjl_2020063120753 /path/to/regionb.mjl_2020063120800 /path/to/regionb.mjl_2020063120801 /path/to/regionb.mjl_2020063120812 /path/to/regionb.mjl_2020063120822 /path/to/regionb.mjl_2020063121026 /path/to/regionc.mjl_2020063120753 /path/to/regionc.mjl_2020063120800 /path/to/regionc.mjl_2020063120801 /path/to/regionc.mjl_2020063120812 /path/to/regionc.mjl_2020063120822 /path/to/regionc.mjl_2020063121026
# Out of chain total        : 1.68 MiB
# Summary
| Region     | Size Total (MiB) | Recoverability up to |
| ---------- | ---------------- | -------------------- |
| GTMWIZARDS | 0.21             | 03-MAR-2020 12:10:35 |
| REGIONA    | 0.21             | 03-MAR-2020 12:10:35 |
| REGIONB    | 0.21             | 03-MAR-2020 12:10:35 |
| REGIONC    | 0.21             | 03-MAR-2020 12:10:35 |
Global Buffer Dashboard

The %dirty global buffer dashboard displays the region-wise percentage of global buffers vs dirty global buffers in a bar graph and the number of global buffers in a table. A large number of global buffers implies a large number of dirty global buffers to be flushed at an epoch. This dashboard along with the dynamic journal file chain can be used to determine an appropriate epoch interval / tapering settings for the application and help troubleshoot I/O spikes and process hangs during high loads.

This %JSWRITE reference implementation uses the STDIN^%JSWRITE singlesub entrypoint of the %JSWRITE utility routine.

Example:

$ node node_modules/@fis-gtm/jswrite/reference_implementations/gtmjsaccessbg.js
^%YGBLSTAT Sparkline Charts

%YGBLSTAT Sparkline shows region-wise sparkline charts for the specified collection of statistics. Typically, you would group statistics by their relevance, for example, TR0,TR1,TR2,TR3, and TR4 can be grouped together to visualize variations for TP Restarts in a condensed form.

This %JSWRITE reference implementation uses the STDIN^%JSWRITE singlesub entrypoint of the %JSWRITE utility routine.

Example:

# Set the environment variable LC_ALL to a UTF8 locale (needed for the %JSWRITE Sparkline Chart (GTMJSGVSTATS.m/gtmjsgvstats.js) reference implementation)
node node_modules/@fis-gtm/jswrite/reference_implementations/gtmjsgvstats.js   # By default, this reference implementation displays a sparkline chart for SETs and GETs. For monitoring other statistics, open gtmjsgvstats.js and update the STAT array to include the list of statistics which require sparkline chart style monitoring. 
^%YGBLSTAT to JSON

GTMJSGVSTATS.m is routine used in the %YGBLSTAT sparkline chart reference implementation. You can use the same routine to create a JSON file which can be imported to spreadsheet software such as Excel. The following command creates gvstats.json which includes all statistics produced with the %YGBLSTAT utility for all regions which have opted for statistics sharing.

$gtm_dist/mumps -r ^GTMJSGVSTATS | $gtm_dist/mumps -r STDIN^%JSWRITE singlesub > /src/toExcel/gvstats.json

You can also choose the statistics that you want in the JSON file with the following:

$gtm_dist/mumps -r ^GTMJSGVSTATS TR0,TR1,TR2,TR3,TR4 | $gtm_dist/mumps -r STDIN^%JSWRITE singlesub > /src/toExcel/gvstats.json

You can import gvstats.json in Excel using the "Data->Get Data->From File->From JSON" option of Excel.

This %JSWRITE reference implementation uses the STDIN^%JSWRITE singlesub entrypoint of the %JSWRITE utility routine.

JSWRITE Utility Class

JSWRITE.js is a utility class for managing objects created with the ^%JSWRITE utility routine of GT.M. It helps with object mutation and cases when you need to round-trip data back to GT.M. The use of JSWRITE.js is optional and is provided as a convenience to JavaScript developers working on ^%JSWRITE utility routine.

The constructor of JSWRITE.js takes one argument which can be an array collection object from %JSWRITE(glvn,[#]|[*]), one object string %JSWRITE(glvn,#|*), or an empty object. After instantiation, the object has the following getter function.

Getter Method

getSubs

Returns an array containing the unsubscripted GT.M glvname and their subscripts. The first element of the array is always the glvname.

getValue

Returns the value of the GT.M glvname.

getZWRLines

Contains an array of ZWR lines with each element represents one valid argument for use with SET @ in GT.M.

For example, for following GT.M lv structure:

GTM>zwrite
A("One","Two","Three","Four")="Demo"
GTM>do ^%JSWRITE("A","*")
{"A":{"One":{"Two":{"Three":{"Four":"Demo"}}}}}

..instantiate an object as follows:

> var JSWRITE=require("@fis-gtm/jswrite")
> JSObj=new JSWRITE({"A":{"One":{"Two":{"Three":{"Four":"Demo"}}}}})

The getter functions return the following values:

JSObj.getSubs

[ 'A', 'One', 'Two', 'Three', 'Four' ]

JSObj.getValue

'Demo'

JSObj.getZWRLines

[ 'A("One","Two","Three","Four")="Demo"' ]

Other Methods

toZWR(JSONobj)

Attempts to traverse and convert the JSON paths and their values of JSONObj to a form that can be used with SET @. The argument must be an object. Specifying an array produces an error. Invoking the .toZWR(JSONObj) method appends the getZWRLines array.

customZWR(glvName, [subscripts], glvValue)

Returns an array containing the unsubscripted GT.M glvname and their subscripts. The first element of the array is always the glvname.

validateJSON(str)

Checks whether the string argument is a valid JSON object. If str is a valid JSON string, it returns the result of JSON.parse(str).

Examples:

.toZWR()

>var JSWRITE=require("@fis-gtm/jswrite")
undefined
> JSObj=new JSWRITE({})
undefined
> JSObj.toZWR({"A":{"A1":[1,2,{"C":"C3"},4]}})
undefined
> JSObj.getZWRLines
[
  'A("A1","0")="1"',
  'A("A1","1")="2"',
  'A("A1","2","C")="C3"',
  'A("A1","3")="4"'
]
>

.customZWR()

> JSObj.customZWR("A",[1,2,3,4,5],"ABCD\n")
undefined
> JSObj.getZWRLines
[ 'A(1,2,3,4,5)="ABCD"_$C(10)_""' ]

%LCASE

The %LCASE utility converts a string to all lower-case letters. If a routine uses this function repetitively, put the utility code directly into the M program.

Utility Labels

INT: Converts interactively a string to lower-case.

FUNC(s): Invokes %LCASE as an extrinsic function returning the lower-case form of the argument.

Prompts

String: Requests a string for conversion to lower case.

Input Variables

%S: As input, contains string to be converted to lower case.

Output Variables

%S: As output, contains the converted string in lower case.

Examples of %LCASE

Example:

GTM>DO INT^%LCASE
String: LABEL
Lower: label

This example invokes %LCASE in interactive mode using INT^%LCASE. %LCASE prompts for a string that it converts to all lower case.

Example:

GTM>SET %S="Hello"
GTM>do ^%LCASE
GTM>zwrite
%S="hello" 

This example sets the variable %S to the string "Hello" and invokes %LCASE non-interactively to convert the string.

Example:

GTM>SET ^X="Hello"
GTM>WRITE $$FUNC^%LCASE(^X)
hello 

This example sets the variable ^X to the string "Hello" and invokes %LCASE as an extrinsic function that returns "hello" in lower case.

%OD

The %OD utility converts numeric values from octal to decimal. %OD returns the decimal number in the read-write variable %OD. %OD rejects input numbers beginning with a minus (-) sign and returns null (""). The routine has entry points for interactive or non-interactive use.

Utility Labels

INT: Converts octal number entered interactively to decimal number.

FUNC(oct): Invokes %OD as an extrinsic function returning the decimal equivalent of the argument.

Prompts

Octal: Requests an octal number for conversion to decimal.

Input Variables

%OD: As input, contains input octal number.

Output Variables

%OD: As output, contains the converted number in decimal.

Examples of %OD

Example:

GTM>DO INT^%OD
Octal:14
GTM>ZWRITE
%OD=12

This example invokes INT^%OD to interactively convert the octal number entered. %OD prompts for an octal number that it converts to a decimal. %OD returns the converted value in the variable %OD.

Example:

GTM>SET %OD=14
GTM>DO ^%OD
GTM>ZWRITE
%OD=12

This example sets the read-write variable %OD to 14 and invokes %OD to convert the number non-interactively. ZWRITE displays the contents of the variables.

Example:

GTM>WRITE $$FUNC^%OD(14)
12

This example invokes %OD as an extrinsic function with the FUNC label. The argument specifies the number to be converted.

%OH

The %OH utility converts numeric values from octal to hexadecimal. %OH returns the hexadecimal number in the read-write variable %OH. %OH rejects input numbers beginning with a minus (-) sign. The routine has entry points for interactive or non-interactive use. In interactive mode, %OH rejects non-octal numbers with the following message, "Input must be an octal number". In non-interactive mode, %OH returns a null string ("") upon encountering a non-octal number.

Utility Labels

INT: Converts interactively octal number entered to hexadecimal number.

FUNC(oct): Invokes %OH as an extrinsic function returning the hexadecimal equivalent of the argument.

Prompts

Octal:Requests an octal number for conversion to hexadecimal.

Input Variables

%OH: As input, contains input octal number.

Output Variables

%OH: As output, contains the converted number in hexadecimal.

Examples of %OH

Example:

GTM>DO INT^%OH
Octal:16
GTM>ZWRITE
%OH="E"

This example invokes %OH in interactive mode using INT^%OH. %OH prompts for an octal number that it converts to a hexadecimal number. ZWRITE displays the contents of the variable.

Example:

GTM>SET %OH=16
GTM>DO ^%OH
GTM>ZWRITE
%OH="E" 

This example sets the read-write variable %OH to 16 and invokes %OH to convert the value of %OH non-interactively. ZWRITE displays the contents of the variable.

Example:

GTM>WRITE $$FUNC^%OH(16)
E

This example invokes %OH as an extrinsic function with the FUNC label.

%UCASE

The %UCASE utility converts a string to all upper-case letters. If a routine uses this function repetitively, put the utility code directly into the M program.

Utility Labels

INT: Converts a string to upper case interactively.

FUNC(s): Invokes %UCASE as an extrinsic function, returning the upper-case form of the argument.

Prompts

String: Requests a string for conversion to upper case.

Input Variables

%S: As input, contains string to be converted to upper case.

Output Variables

%S: As output, contains the converted string in upper case.

Examples of %UCASE

Example:

GTM>DO INT^%UCASE
String: test
Upper: TEST

This example invokes %UCASE in interactive mode using INT^%UCASE. %UCASE prompts for a string that it converts to all upper case.

Example:

GTM>SET ^X="hello"
GTM>WRITE $$FUNC^%UCASE(^X)
HELLO

This example sets the variable X to the string "hello" and invokes %UCASE as an extrinsic function that returns "HELLO" in upper case.