GT.M Acculturation Live CD

From VistApedia
Revision as of 15:03, 3 February 2010 by Ivaldes1 (talk | contribs)
Jump to: navigation, search

The GT.M Acculturation live CD is a Linux live CD aimed at those who would like to learn about GT.M. It is a tutorial with examples and exercises focusing on the differences between GT.M and other implementations of M. In view of the fact that these differences are mostly in the area of administration and operations, reflecting GT.M's emphasis as a platform for secure, mission critical, production applications, that is the focus.

It has been used as the basis for several of the GT.M workshops at VistA Community Meetings.

It is available for download from the WorldVistA Sourceforge Project Page and the document re-created here:

<html> </head><body dir="ltr" lang="en-US">

Contents

<img src="index_files/FNFIS_logo.jpg" name="graphics7" align="right" border="0" height="77" width="156"><img src="index_files/powered_by_gtm_wo.jpg" name="graphics9" align="left" border="0" height="58" width="95">Welcome to the GT.M Acculturation Live CD!



Although you can read this document in your current environment, you will need to boot this CD in order to get the most benefit from it. When you boot it, please either:

  • connect a 512MB USB flash drive (also known as a jump drive or thumb drive), or

  • ensure

    that the hard disk has a partition with at least 300MB in size with

    either

    • a FAT file system,

    • a Linux file system, or

    • a

      partition which can be over-written with a Linux file system – tools to partition the disk drive and create a Linux file system

      are included on the CD).

<img src="index_files/penguin12.gif" name="graphics8" align="right" border="0" height="76" width="90">Note: there is no “Start” button. Clicking on the screen background with the right mouse button pops up the menu.

Table of Contents

  • <a href="#2.Overview%7Coutline">Overview</a>

    • <a href="#GT.M%7Coutline">GT.M</a>

    • <a href="#Acculturation%20Workshop%7Coutline">Acculturation Workshop</a>

    • <a href="#VistA%7Coutline">VistA</a>

    • <a href="#Linux%20Live%20CD%7Coutline">Linux Live CD</a>

    • <a href="#Hardware%20Requirements%7Coutline">Hardware Requirements</a>

    • <a href="#Conventions%7Coutline">Conventions</a>

    • <a href="#Legal%20Stuff%7Coutline">Legal Stuff</a>

  • <a href="#3.Getting%20Started%7Coutline">Getting Started</a>

    • <a href="#FAT%20File%20System%7Coutline">FAT File System</a>

      • <a href="#Mounting%20a%20read/write%20partition%7Coutline">Mounting a Read/Write Partition</a>

        • <a href="#Graphical%20Mounting%20Tool%7Coutline">Graphical Mounting Tool</a>

        • <a href="#Mounting%20With%20Shell%20Commands%7Coutline">Mounting with Shell Commands</a>

      • <a href="#First%20usage%7Coutline">First Usage</a>

      • <a href="#First%20and%20subsequent%20usage%7Coutline">First and Subsequent Usage</a>

    • <a href="#Linux%20file%20system%7Coutline">Linux File System</a>

      • <a href="#First%20usage%7Coutline">First Usage</a>

      • <a href="#Subsequent%20usage%7Coutline">Subsequent Usage</a>

  • <a href="#4.Start+GT.M+%3F+ready+to+run+VistA%7Coutline">Start GT.M – Ready to Run VistA</a>

  • <a href="#5.Excellent%20Documentation%7Coutline">Excellent Documentation</a>

    • <a href="#Manuals%7Coutline">Manuals</a>

    • <a href="#Technical%20Bulletins%7Coutline">Technical Bulletins</a>

  • <a href="#6.GT.M+%3F+a+MUMPS+unlike+any+other%7Coutline">GT.M – a MUMPS Unlike Any Other</a>

    • <a href="#GT.M%20is%20just%20like%20any%20other%20M%20implementation%7Coutline">GT.M is Just Like Any Other M Implementation</a>

    • <a href="#Routines%20are%20in%20the%20file%20system%7Coutline">Routines are in the File System</a>

      • <a href="#Exercise%7Coutline">Exercise – Compiling & Linking</a>

    • <a href="#Global%20directories%20point%20to%20global%20variables%7Coutline">Global Directories Point to Global Variables</a>

    • <a href="#$ZROUTINES%20and%20$ZGBLDIR%20vs.%20UCI%20&%20Volume%20set%7Coutline">$ZROUTINES and $ZGBLDIR vs. UCI & Volume set</a>

    • <a href="#Example:%20Development%20environments%7Coutline">Example: Development Environments</a>

    • <a href="#Example:%20Application%20Service%20Provider%7Coutline">Example: Application Service Provider</a>

      • <a href="#Exercise+%3F+GDE+commands+for+ASP%7Coutline">Exercise – GDE Commands for ASP</a>

    • <a href="#GT.M%20leverages%20the%20operating%20system%7Coutline">GT.M Leverages the Operating System</a>

    • <a href="#Security%7Coutline">Security</a>

      • <a href="#Security%7Coutline">Exercise – Security</a>

    • <a href="#No%20special%20startup%20or%20shutdown%7Coutline">No Special Startup or Shutdown</a>

    • <a href="#Journaling+%3F+the+key+to+database+integrity%7Coutline">Journaling – the Key to Database Integrity</a>

    • <a href="#Exercise%20-%20journaling%7Coutline">Exercise – Journaling</a>

    • <a href="#Database%20replication%7Coutline">Database Replication</a>

    • <a href="#Replication%20and%20Backlogs%7Coutline">Replication and Backlogs</a>

      • <a href="#Exercise+%3F+replication+backlogs%7Coutline">Exercise – Replication Backlogs</a>

    • <a href="#Backup%7Coutline">Backup</a>

      • <a href="#Exercise%20-%20backup%7Coutline">Exercise – Backup</a>

    • <a href="#Potential%20surprises%7Coutline">Potential Surprises</a>

    • <a href="#Exploit%20integration%20with%20underlying%20operating%20system%7Coutline">Exploit Integration with Underlying Operating System</a>

  • <a href="#7.In%20conclusion%7Coutline">In Conclusion</a>

<a name="2.Overview|outline"></a>Overview

<a name="GT.M|outline"></a>GT.M

<a href="http://www.sanchez-gtm.com/">GT.M™</a> is an implementation of the ISO standard scripting & application development language M, commonly known as MUMPS from <a href="http://fidelityinfoservices.com/">Fidelity Information Services, Inc.</a> As the platform for the <a href="http://www.fidelityinfoservices.com/fnfis/markets/midtierlgbanking/corebanking/profile">Fidelity Profile</a> application, GT.M is the most widely used M implementation in banking and finance, including the <a href="http://www.sanchez-gtm.com/news/news.htm">largest real time core processing system that is live at any bank anywhere in the world</a>. GT.M is increasingly used in healthcare, and is likely the most widely used M on Linux. The implementation of GT.M on the GNU/Linux operating system on industry standard x86 architecture hardware is available under the GNU General Public License, and is the M implementation used for the FOSS stack for VistA.

GT.M is architected with the following objectives:

  • Without compromise, the robustness, security and integrity of the information entrusted to it.

  • Open

    architecture, with easy, standards based access to the information

    in the database.

  • Continuity

    of business – GT.M has unique functionality for the deployment of mission-critical applications that must be available 24 hours a

    day, 365 days a year, with no down time even for planned events.

  • Throughput,

    performance and scalability to meet the needs of the largest

    institutions in the world.

Free support for GT.M is provided by the community on <a href="http://sourceforge.net/forum/?group_id=11026">various mailing lists and electronic forums</a>, and 24x365 support is available from Fidelity on a commercial basis.

GT.M provides:

  • full ACID (Atomic, Consistent, Isolated, Durable) transaction semantics,

  • throughput that scales to the needs of enterprise wide applications, and

  • unique

    functionality for creating logical dual site configurations for mission critical applications that must always be available; including during upgrades, and even upgrades involving changes to

    the database schema.

This CD includes GT.M V5.0-000C.

<a name="Acculturation Workshop|outline"></a>Acculturation Workshop

The GT.M acculturation workshop is a hands-on GT.M “boot camp” for M professionals who are not familiar with GT.M, as well as for those interested in GT.M configuration, administration and operations. This file is the script, or workbook, for the workshop, and consists of the exercises below. The exercises are designed to be carried out by booting the GT.M Acculturation live CD. To do so, you should be reading this in a browser window on your PC desktop after boot-up. If that is not the route that brought you to your perusal of this document, then please boot the GT.M Acculturation live CD and continue.

The workshop is not a course in M programming – familiarity with another M implementation (or with GT.M for those using these exercises to refine their skills) is assumed. Familiarity with Linux® (or at least UNIX®) is highly desirable, but not absolutely required.

As the differences between GT.M and other M implementations are more in the area of configuration and systems administration rather than M language features, the former topics are the major thrust of the workshop.

<a name="VistA|outline"></a>VistA

The <a href="http://www.va.gov/">US Department of Veterans Affairs</a> is one of the largest integrated healthcare networks in the world. Delivering legally mandated high quality care to veterans of the US armed forces, it has repeatedly been recognized not only for the quality, but also for the cost-effectiveness, of the care that it provides.

VistA is an HIS developed and maintained by the VA, based on the systems software architecture and implementation methodology developed by the US Public Health Service jointly with the National Bureau of Standards. VistA is used throughout the VA system, and variants are used by the US Department of Defense, the Indian Health Service (an agency of the US Department of Health and Human Services), as well as at numerous institutions around the world. VistA has a proven track record of supporting a large variety of settings and medical delivery systems. The software is in the public domain and freely available. Many providers support VistA on a commercial basis, and there is an <a href="http://lists.sourceforge.net/lists/listinfo/hardhats-members">active online VistA community</a>.

For all healthcare organizations, VistA can provide a cost-effective enterprise resource planning (ERP) system. It is written in the ANSI/ISO standard programming language M (also known as MUMPS), With origins in the field of healthcare informatics, M is the de facto standard for healthcare software.

The GT.M Acculturation live CD uses the US Department of Veterans Affairs' acclaimed VistA healthcare information system as a sample GT.M application, and is itself a repackaged VistA live CD that can be downloaded from the <a href="http://sourceforge.net/projects/worldvista">WorldVistA project at Source Forge</a>.

No knowledge of VistA is assumed or required for the Acculturation Workshop.

<a name="Linux Live CD|outline"></a>Linux Live CD

Linux is the common name for the GNU/Linux operating system, consisting of the GNU utilities and libraries on the Linux kernel, available across the broadest range of hardware of any operating system. It is most widely used on industry standard architecture x86 hardware (i.e., based on popular CPUs from Intel, AMD and others), and is increasingly popular around the world for applications that include embedded computing (appliances); personal desktops; file, print & web servers; supercomputing; and to deploy mission critical software. Linux is the operating system for the VistA FOSS stack.

Free support for Linux is available on numerous mailing lists and electronic forums. Commercial support is widely available from multiple vendors.

A <a href="http://en.wikipedia.org/wiki/Live_cd">live CD</a> (or DVD – the terms are interchangeable as far as this document is concerned) is a CD that boots a PC and runs the GNU/Linux operating system – more commonly referred to as just Linux – from the CD, no matter what operating system is installed on the hard drive. Indeed, there need not even be a hard drive on the PC.

Content on the CD is compressed, and uncompressed on the fly as needed. This means that there is a lot more on the CD than its nominal capacity. Note that booting and running an operating system off a CD will be slower than running the same operating system off a hard drive because (a) CD-ROM drives are typically slower than hard drives and (b) content must be uncompressed each time it is read from the CD.

This GT.M Acculturation live CD is based on the <a href="http://damnsmalllinux.org/">Damn Small Linux (DSL)</a> distribution version 2.1b.

<a name="Hardware Requirements|outline"></a>Hardware Requirements

This CD will boot on an industry standard x86 architecture PC that can boot from a CD-ROM. 500MHz or better CPU and 128MB or more RAM are recommended.

GT.M is a database application development platform. Although a snapshot of a database can be placed on a CD, it is not possible for an operational database to reside on a read-only medium such as a CD. Ergo, the exercises require read/write storage, which can be provided by one of the following:

  • A 512MB USB flash drive (also referred to as a thumb drive or jump drive; a USB 2.x drive and a USB 2.x port on the host PC will be much faster than a USB 1.x drive and port). A USB hard drive would also work, as would a memory card or stick (e.g., from a digital camera) mounted in a suitable reader. Such a device will probably have a name such as /dev/sda1 or /dev/sdb1.

  • A

    partition on an IDE or SCSI hard drive that contains a Linux file system (e.g., ext3, reiserfs) or a FAT file system (Windows 95/98/ME file system), but not an NTFS file system (Windows NT/2000/XP file system). A partition on an IDE drive will probably have a name such as /dev/hda2 or /dev/hdb3; a partition on a SCSI drive will have a name such as /dev/sda1 or /dev/sda2

    (i.e., similar to a USB drive). If a partition with a FAT or Linux file system does not exist, and the contents of an existing partition can be over-written, you can create such a file system in

    an existing partition with this CD.

A minimum of 350MB of available space is required. More (400MB) is strongly recommended. For the purpose of the examples in this document, a read/write partition with a FAT file system is assumed to reside at /dev/sda1 (which corresponds to the first partition of the first USB flash drive found); a read/write partition with a Linux file system is assumed to reside at /dev/hda2 (which corresponds to the second partition of the first IDE hard drive). Adjust your commands as needed for partitions in other locations.

<a name="Conventions|outline"></a>Conventions

In the following, text in a blue bold monospace font is intended to be typed in at a GT.M prompt (including the main GTM> prompt as well as utility programs such as GDE>). Text in a red bold monospace font is intended to be typed in at a bash shell prompt (or otherwise provided as input to a bash shell), or elsewhere in Linux but not to GT.M.

<a name="Legal Stuff|outline"></a>Legal Stuff

GT.M is owned and copyrighted by <a href="http://fidelityinfoservices.com/">Fidelity National Information Services, Inc.</a>, and is available for the x86 GNU/Linux platform under the terms of the <a href="http://www.fsf.org/licensing/licenses/gpl.txt">GNU General Public License (GPL)</a>. Source and binary can be downloaded from the <a href="http://sourceforge.net/projects/sanchez-gtm">GT.M project page at Source Forge</a>.

VistA is in the public domain through the <a href="http://en.wikipedia.org/wiki/Freedom_of_information_act">US Freedom of Information Act</a>. Source and object code are available on the CD. As noted above, no understanding of VistA itself is required or assumed for the workshop.

The Linux kernel, GNU utilities, XFCE, and all other software on the CD are open source free software, available under their respective open source licenses.

Copyrights and trademarks of all content on the CD are hereby acknowledged as being held by their owners.

This document itself is placed in the public domain by the author with no warranty of any kind, explicit or implicit. Follow any instructions herein at your own risk.

<a name="3.Getting Started|outline"></a>Getting Started

As discussed above, a read/write partition is required for the database. Choose one of the following, depending on your hardware configuration:

  • <a href="#FAT%20File%20System%7Coutline">FAT file system</a>, (USB drive, or a partition on an IDE or SCSI drive with a FAT file system), or

  • <a href="#Linux%20file%20system%7Coutline">Linux

    file system</a> (partition on an IDE or SCSI hard drive with a Linux file system, or a partition that can be formatted with a Linux file

    system)

In either case, first:

  • Start a bash shell: right click on the screen background, choose Xshells and then your choice of background for the terminal window (Transparent, Light or Dark). The initial directory for the shell is /home/dsl.

  • All

    exercises will be carried out in /home/dsl/myVistA and its subdirectories. Create a mount point myVistA in /home/dsl, the home directory of the default user, dsl: mkdir

    -p myVistA

<a name="FAT File System|outline"></a><a name="FAT File System|outline"></a><a name="FAT File System|outline"></a> FAT File System

The exercises require a GT.M database in a Linux file system. Although a GT.M database can reside in a FAT file system (at least for demonstration purposes – databases on FAT file systems are neither recommended nor supported for production use), the exercises require functionality that is not available with a FAT file system. Ergo a Linux file system is required for the GT.M Acculturation Workshop. So, the FAT file system must first be mounted, and the Linux file system within mounted separately (i.e., there are two mount operations performed).

<a name="Mounting a read/write partition|outline"></a>Mounting a read/write partition

When you are asked to mount an existing file system with a read/write partition using the <a href="#Graphical%20Mounting%20Tool%7Coutline">graphical mounting tool</a>, or <a href="#Mounting%20With%20Shell%20Commands%7Coutline">with shell commands</a> and then choose either <a href="#FAT%20File%20System%7Coutline">FAT file system</a> or <a href="#Linux%20file%20system%7Coutline">Linux file system</a>. depending on the file system on the device partition.

<a name="Graphical Mounting Tool|outline"></a><a name="Graphical Mounting Tool|outline"></a> Graphical Mounting Tool

<img src="index_files/dsl_automounter_umounted.jpg" name="graphics1" align="left" border="0" height="86" hspace="16" width="77"><img src="index_files/dsl_automounter_mounted.jpg" name="graphics2" align="right" border="0" height="85" hspace="12" width="76">In the lower right corner is a graphical mounting tool. Click on the button that says “fd0” till till it has the name of the device you wish to mount, e.g., “sda1” for a USB flash drive or “hda2” for a hard drive partition. Then click the red button labelled “umounted” to mount it. On a successful mount, the red button will turn green and say “mounted”. The device will be mounted under /mnt (e.g., /dev/hda2 will be mounted as /mnt/hda2).

<a name="Mounting With Shell Commands|outline"></a><a name="Mounting With Shell Commands|outline"></a> Mounting With Shell Commands

To mount a USB flash drive which is at /dev/sda1 at /mnt/sda1, type: mount /mnt/sda1 – if it is something else, such as a hard drive partition, or a SCSI drive partition, e.g., /dev/sdb3 or /dev/hda2, alter the command accordingly.

<a name="First usage|outline"></a><a name="First usage|outline"></a> First usage

It is possible to create a Linux file system within a FAT file system with a two stage process. We will use a Linux feature that treats an ordinary file as a device (a so called “loop” file system). Within the FAT file system, we will create a single large file called LinuxFileSystem (the name does not really matter). By treating this file as a disk drive, we will create a Linux file system within it, and mount this file system as a loop file system.

If this is the first time that you are using that FAT file system, execute the following commands (with a USB 1.x interface, each command could take many minutes to tens of minutes; USB 2.x will be much faster):

Create a 350MB file called LinuxFileSystem on the FAT file system, adjust count as needed for a smaller or larger file: dd if=/dev/zero of=/mnt/sda1/LinuxFileSystem count=716800

Create a Linux ext3 file system within LinuxFileSystem: mkfs -t ext3 -F /mnt/sda1/LinuxFileSystem

<a name="First and subsequent usage|outline"></a>First and subsequent usage

Mount the Linux file system within /mnt/sda1/LinuxFileSystem as /home/dsl/myVistA: sudo mount -o loop /mnt/sda1/LinuxFileSystem myVistA

<a name="Linux file system|outline"></a><a name="Linux file system|outline"></a><a name="Linux file system|outline"></a> Linux file system

First usage

If a file system does not exist in the read/write partition and one needs to be created first (this will over-write any existing contents on the partition): sudo mkfs -t ext3 /dev/hda2

Mount the partition: sudo mount /dev/hda2 myVistA

Change the ownership of the mounted file system so that it is owned by user dsl: sudo chown -R dsl.staff myVistA

<a name="Subsequent usage|outline"></a>Subsequent usage

Simply mount the partition: sudo mount /dev/hda2 myVistA

<a name="4.Start GT.M – ready to run VistA|outline"></a>Start GT.M – ready to run VistA

You have reached the real starting point of the GT.M Acculturation Workshop – getting to the GT.M direct (i.e., interactive or immediate) mode prompt (GTM> in a terminal window) with the environment configured to run VistA. At this point, you should have a Linux filesystem mounted as /home/dsl/myVistA, ready for a database to be loaded into it. The filesystem could be a Linux filesystem on a a device, or residing in a file which itself resides in a file on a FAT filesystem.

The first time that you run with the live CD, you will need create a VistA environment. The underlying principles are on the <a href="http://openforum.worldvista.org/%7Eforum/index.php?title=Software_Development_%28WG1%29_Version_Control_%28T3%29">Setting up a VistA Development page</a> of the <a href="http://openforum.worldvista.org/%7Eforum">WorldVistA Wiki</a>. In case of limited internet access, a copy of relevant material from which is cached locally <a href="file:///home/ivaldes/.gvfs/GT.MAcculturation0.4.iso/20060321WorldVistAWikiSWConfiguration.html">here</a>. To create a VistA environment:

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~$ <font color="#ff0000">/usr/local/FOIAVistA/install myVistA/FOIAVistA</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Creating environment in  myVistA/FOIAVistA  as child of environment in  /usr/local/FOIAVistA</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Unzipping from parent to create initial database</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-JNLCREATE, Journal file /ramdisk/home/dsl/myVistA/FOIAVistA/g/mumps.mjl created for database file /ramdisk/home/dsl/myVistA/FOIAVistA/g/mumps.dat with BEFORE_IMAGES</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-JNLSTATE, Journaling state for database file /ramdisk/home/dsl/myVistA/FOIAVistA/g/mumps.dat is now ON</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Default permission for development environment is for all to read and group to write - please alter as needed</b></font></font>

The above creates an environment for GT.M, and uncompresses the database from the copy on the CD. This can take from a few seconds to many minutes, depending on the type of device (USB 2.x is slower than IDE / SCSI; USB 1.x is slower than USB

2.x), PC speed, etc.

On subsequent occasions, once the database is uncompressed and copied, to run the application, execute myVistA/FOIAVistA/run and get to the GTM> prompt:

<font face="Nimbus Mono L"><font size="2"><b>dsl@box:~$ <font color="#ff0000">myVistA/FOIAVistA/run</font></b></font></font>

<font face="Nimbus Mono L"><font size="2"><b>GTM></b></font></font>

At this point,

you have a full character mode VistA, e.g.:

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">set DUZ=1 do P^DI</font></b></font></font>


<font face="Nimbus Mono L, monospace"><font size="2"><b>VA FileMan 22.0</b></font></font>


<font face="Nimbus Mono L, monospace"><font size="2"><b>Select OPTION: <font color="#0000ff">?</font></b></font></font>

    <b><font face="Nimbus Mono L, monospace">Answer with OPTION NUMBER, or NAME</font></b>
   <b><font face="Nimbus Mono L, monospace">Choose from:</font></b>
   <b><font face="Nimbus Mono L, monospace">1            ENTER OR EDIT FILE ENTRIES</font></b>
   <b><font face="Nimbus Mono L, monospace">2            PRINT FILE ENTRIES</font></b>
   <b><font face="Nimbus Mono L, monospace">3            SEARCH FILE ENTRIES</font></b>
   <b><font face="Nimbus Mono L, monospace">4            MODIFY FILE ATTRIBUTES</font></b>

   <b><font face="Nimbus Mono L, monospace">5            INQUIRE TO FILE ENTRIES</font></b>
   <b><font face="Nimbus Mono L, monospace">6            UTILITY FUNCTIONS</font></b>
   <b><font face="Nimbus Mono L, monospace">7            OTHER OPTIONS</font></b>
   <b><font face="Nimbus Mono L, monospace">8            DATA DICTIONARY UTILITIES</font></b>
   <b><font face="Nimbus Mono L, monospace">9            TRANSFER ENTRIES</font></b>
    
<font face="Nimbus Mono L, monospace"><font size="2"><b>Select OPTION: <font color="#0000ff">← <i><font size="3"><font face="Nimbus Roman No9 L, serif">press Enter here</font></font></i></font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM></b></font></font>

Once you can

access the application, we can start to work with GT.M.

<a name="5.Excellent Documentation|outline"></a>Excellent Documentation

GT.M user documentation consists of manuals and technical bulletins. Manuals are updated periodically, and technical bulletins serve as user documentation updates that are available in a more timely manner. Current GT.M documentation is available online at the <a href="http://www.sanchez-gtm.com/user_documentation/user_doc.htm">GT.M documentation site</a> as well as a <a href="file:///usr/share/doc/gtm/index.html" target="_blank">local copy</a> on this CD.

<a name="Manuals|outline"></a>Manuals

  • Programmers Guide

  • Administration

    and Operations Guide (caution: as of this writing, this is a draft version of the Administration and Operations Guide in the new HTML

    format generated from DocBook XML, and has a few rough edges).

  • Messages and Recovery Procedures

<a name="Technical Bulletins|outline"></a>Technical Bulletins

Sample technical bulletins:

  • V5.0-000C Release Notes

  • MUPIP Set Journal

  • Long names

  • Null subscripts

  • Supplementary information

Onward to the real GT.M acculturation workshop!

<a name="6.GT.M – a MUMPS unlike any other|outline"></a>GT.M – a MUMPS unlike any other

<a name="GT.M is just like any other M implementation|outline"></a> GT.M is just like any other M implementation

You can type lines of code and have them execute interactively, just like on any other M implementation, e.g.:

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Set ^X=1</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>1</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Kill ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Set S="S ^X=1 W ^X K ^X" Xecute S</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>1</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Halt</font></b></font></font>

You can edit routines from the GTM> prompt: ZEDit "XUP". This starts the vi editor editing the source routine for ^XUP, /home/dsl/myVistA/FOIAVistA/r/XUP.m. Use the five key sequence Escape

q ! Enter

to exit vi

without changing the file.

With the exception of Structured System Variable Names (SSVNs), GT.M mostly implements ISO standard M (ISO 11756–1999), including a full implementation of transaction processing (TP) that provides ACID (Atomic, Consistent, Isolated, Durable) transactions. As with any M implementation, there are extensions, IO parameters are implementation specific, as are the VIEW command, and commands & variables starting with the letter Z.

Despite the fact that the dialect of M implemented by GT.M shares so much in common with other M implementations, operationally, GT.M is unlike any other M implementation!

<a name="Routines are in the file system|outline"></a>Routines are in the file system

Routines in GT.M are simply files in the file system; they do not reside in databases. To see the routines that make up VistA, try ls -l /usr/local/FOIAVistA/r (this can take several minutes the first time you try it, depending on the speed of your PC). To count how many routines make up VistA, type ls -l /usr/local/FOIAVistA/r | wc to get the answer. The philosophy of GT.M is to focus on what it does well, providing a robust, scalable, transaction processing database and a compiler for the M language, and to leverage tools and capabilities of the underlying operating system for the rest. This is powerful because whenever there are enhancements to the underlying operating environment, GT.M can benefit from them. This can also be a little uncomfortable for the typical M programmer, because traditional M implementations carry their environments with them, not unlike the shell on a snail's back.

GT.M is a true compiler that compiles source code routines into object code routines. Source code is in files with a .m extension and object code is in routines with a .o extension. On the GT.M acculturation workshop live CD, the VistA routines have been pre-compiled. For example, to see the source code routines on the CD for managing Diagnostic Related Groups (DRG), type ls /usr/local/FOIAVistA/r/ICD* and to see the corresponding object code routines, type ls /usr/local/FOIAVistA/o/ICD*.

As you saw when executing M commands interactively, the fact that GT.M is a true compiler does not keep it from providing an interactive direct mode – GT.M simply compiles and executes each line.

<a name="Exercise|outline"></a>Exercise

The purpose of this exercise is to understand compiling and linking routines. Since not everyone is comfortable with the terse character-oriented commands of vi, you can optionally use a mouse-and-menu based editor called beaver before you enter GT.M:

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~$ <font color="#ff0000">export EDITOR=`which beaver`</font></b></font></font>
<font color="#ff0000"><font face="Nimbus Mono L, monospace"><font size="2"><b><font color="#000000">dsl@box:~$ </font>myVistA/FOIAVistA/run</b></font></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM></b></font></font>

Tell GT.M to run the routine ^XYZ, and note that it reports an error that it cannot find the routine:

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Do ^XYZ</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-E-ZLINKFILE, Error while zlinking "XYZ"</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-E-FILENOTFND, File XYZ not found</b></font></font>

Note that the directories /home/dsl/myVistA/FOIAVistA/r and /home/dsl/myVistA/FOIAVistA/o

are empty:

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">ZSYstem "ls -lR $vista_home"</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>/home/dsl/myVistA/FOIAVistA:</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-r-xr-xr-x    1 dsl      staff         278 Mar 22 03:18 cprs_direct</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-r--r--r--    1 dsl      staff         583 Mar 22 03:18 env</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>drwxrwxr-x    2 dsl      staff        4096 Mar 22 03:19 g</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>lrwxrwxrwx    1 dsl      staff          24 Mar 22 03:18 gtm -> /usr/local/FOIAVistA/gtm</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-r-xr-xr-x    1 dsl      staff        2977 Mar 22 03:18 install</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>drwxrwxr-x    2 dsl      staff        4096 Mar 22 03:18 o</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>drwxrwxr-x    2 dsl      staff        4096 Mar 22 03:18 p</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>lrwxrwxrwx    1 dsl      staff          20 Mar 22 03:18 parent -> /usr/local/FOIAVistA</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>drwxrwxr-x    2 dsl      staff        4096 Mar 22 03:18 r</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-r-xr-xr-x    1 dsl      staff         252 Mar 22 03:18 run</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>drwxrwxr-x    2 dsl      staff        4096 Mar 22 03:18 tmp</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-r-xr-xr-x    1 dsl      staff        4405 Mar 22 03:18 vista</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-r-xr-xr-x    1 dsl      staff         884 Mar 22 03:18 vista_cprs</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>/home/dsl/myVistA/FOIAVistA/g:</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-r--    1 dsl      staff   348910080 Mar 22 04:53 mumps.dat</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-r--r--r--    1 dsl      staff        1024 Mar 22 03:18 mumps.gld</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-r--    1 dsl      staff        7456 Mar 22 04:53 mumps.mjl</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>/home/dsl/myVistA/FOIAVistA/o:</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>/home/dsl/myVistA/FOIAVistA/p:</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>/home/dsl/myVistA/FOIAVistA/r:</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>/home/dsl/myVistA/FOIAVistA/tmp:</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM></b></font></font>

Type ZEDit "XYZ" then edit, create and save XYZ.m as a small M program, e.g., something that prints “Hello, World!”. Remember to put a newline after the last line in your routine. Save the file and exit the editor.

Execute Do ^XYZ (you can simply hit the up-arrow key three times to recall the command) and note that your program runs as expected. Now execute ZSYstem "ls -lR $vista_home" again and note that the directories /home/dsl/myVistA/FOIAVistA/r and /home/dsl/myVistA/FOIAVistA/o are no longer empty. There are two files, /home/dsl/myVistA/FOIAVistA/r/XYZ.m and /home/dsl/myVistA/FOIAVistA/r/XYZ.o. The former is the source program that you just edited, and the latter is the object code. GT.M dynamically, and automatically, recompiled the source program into the object program when you typed Do ^XYZ.

Since GT.M is a compiler, it can generate error messages at compile time as well as at run time, and indeed when compiling VistA, there are hundreds of lines of error messages triggered by lines of code that are legal for other M implementations but not for GT.M. (These lines are protected in VistA and are inside conditional statements that are executed only on the appropriate M implementation, so they are nothing to be concerned about.)

Again edit the program with ZEDit "XYZ" then change it, e.g., make it print “Aloha, World!” instead, save it.

Again execute Do ^XYZ and note that GT.M still prints “Hello, World!” This is because GT.M already has an XYZ module linked in its address space, and does not go out every time to check if there is a new version. This is “clobber protection” and a GT.M feature.

Now execute ZLink "XYZ" which tells GT.M to re-link XYZ even if it already has one linked in its address space, followed by Do ^XYZ and note that it now prints “Aloha, World!” A ZSYstem "ls -lR $vista_home" shows that GT.M has recompiled the module to create a new object file (since when it attempted the re-link, the source file was found to be newer than the object file).

The intrinsic special variable $ZROutines tells GT.M where to find routines:

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write $ZROutines</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>/home/dsl/myVistA/FOIAVistA/p /home/dsl/myVistA/FOIAVistA/o(/home/dsl/myVistA/FOIAVistA/r) /home/dsl/myVistA/FOIAVistA/parent/p /home/dsl/myVistA/FOIAVistA/parent/o(/</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>home/dsl/myVistA/FOIAVistA/parent/r) /usr/local/gtm_V5.0-000C</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM></b></font></font>

The Programmers Guide explains in detail how $ZROutines is used. $ZROutines is initialized from the shell environment variable $gtmroutines

at:

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write $ZTRNLNM("gtmroutines")</font> </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>/home/dsl/myVistA/FOIAVistA/p /home/dsl/myVistA/FOIAVistA/o(/home/dsl/myVistA/FOIAVistA/r) /home/dsl/myVistA/FOIAVistA/parent/p /home/dsl/myVistA/FOIAVistA/parent/o(/</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>home/dsl/myVistA/FOIAVistA/parent/r) /usr/local/gtm_V5.0-000C</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM></b></font></font>

The example uses GT.M's $ZTRNLNM()

function, which is used to get the value of environment variables.

<a name="Global directories point to global variables|outline"></a> Global directories point to global variables

Since routines in GT.M reside in the file system rather than in the database, whereas global variables reside in databases, routines are completely independent of global variables. In this respect, GT.M is different from other M implementations.

Given a person's name, a telephone directory helps you find the person by giving you the phone number and (usually) the address. Analogously, given an M global variable name, a global directory helps a GT.M process find the variable by giving it the database file where that variable resides, as well as other pertinent information.

The global directory is a binary file pointed to by the intrinsic special variable $ZGbldir. The GDE utility program (invoked with Do ^GDE inside GT.M or mumps -run ^GDE from the shell) is used to manage global directories. [Note that the input to GDE can be a text file. In a production environment, Fidelity recommends that text files be used to define database configurations, and that these text files be put under version control.]

In GT.M, sets of M global variables (Names or Name spaces) are mapped to Regions that define properties relating to the M global. Each Region is mapped to a Segment that defines properties relating to the file system. Consider the example in the figure below:

<img src="index_files/041014-2GlobalDirectory.gif" name="graphics3" align="left" border="0" height="552" width="828">


In this example, there are four M global variables that we would like to separate from the rest (e.g, for purposes of sharing globals between applications, or for reasons of protection – perhaps they contain special information, so that only herpetologists are to have access to globals ^Gharial and ^Jacare, and only ornithologists are to have access to globals ^Hoopoe and ^Trogon). This is accomplished by creating five name spaces (note that a name space can contain a single variable, as in this example, or a range of global variables, e.g., everything starting with ^A through ^Gharial). There is always a default (*) name space.

One or more name spaces are mapped to a Region. All global variables in a region share a common set of M global variable properties, such as the maximum record length, whether null subscripts are permitted, etc. In this case ^Gharial and ^Jacare are mapped to the region REPTILES, whereas ^Hoopoe and ^Trogon are mapped to the region BIRDS. The default name space * is mapped to a region called DEFAULT.

Each region is mapped to a Segment. Just as a region defines properties pertaining to M global variables, the segment defines properties pertaining to the database file for that region, such as the file name, the initial allocation, number of global buffers, etc. The database file is just an ordinary file in the file system of the underlying operating system.

Each database file can have a single active journal file. A journal file can be linked to a previous journal files to form a chain of journal files.

The intrinsic special variable $ZGbldir points a GT.M process to the global directory. $ZGbldir is initialized from $gtmgbldir at process startup:

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write $ZGbldir</font> </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>/home/dsl/myVistA/FOIAVistA/g/mumps.gld</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write $ZTRNLNM("gtmgbldir")</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>/home/dsl/myVistA/FOIAVistA/g/mumps.gld</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM></b></font></font>

Global directories can have environment variables in database file names, which is how one global directory can point to different database files.

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~$ <font color="#ff0000">myVistA/FOIAVistA/run ^GDE</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GDE-I-LOADGD, Loading Global Directory file </b></font></font>
        <b><font face="Nimbus Mono L, monospace">/home/dsl/myVistA/FOIAVistA/g/mumps.gld</font></b>

<font face="Nimbus Mono L, monospace"><font size="2"><b>%GDE-I-VERIFY, Verification OK</b></font></font>


<font face="Nimbus Mono L, monospace"><font size="2"><b>GDE> <font color="#0000ff">show name</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GDE-E-VALUEBAD, name is not a valid Global qualifier</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GDE> <font color="#0000ff">show -name</font></b></font></font>

         <b><font face="Nimbus Mono L, monospace">*** NAMES ***</font></b>

 <b><font face="Nimbus Mono L, monospace">Global                             Region</font></b>
 <b><font face="Nimbus Mono L, monospace">------------------------------------------------------------------------------</font></b>
 <b><font face="Nimbus Mono L, monospace">*                                  DEFAULT</font></b>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GDE> <font color="#0000ff">show -region</font></b></font></font>

                                <b><font face="Nimbus Mono L, monospace">*** REGIONS ***</font></b>

                                 <b><font face="Nimbus Mono L, monospace">Dynamic                          Def    Rec   Key Null       Standard</font></b>
 <b><font face="Nimbus Mono L, monospace">Region                          Segment                         Coll   Size  Size Subs       NullColl  Journaling</font></b>
 <b><font face="Nimbus Mono L, monospace">------------------------------------------------------------------------------------------------------------------</font></b>
 <b><font face="Nimbus Mono L, monospace">DEFAULT                         DEFAULT                            0   4080   255 NEVER      N         N</font></b>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GDE> <font color="#0000ff">show -segment</font></b></font></font>

                                <b><font face="Nimbus Mono L, monospace">*** SEGMENTS ***</font></b>
 <b><font face="Nimbus Mono L, monospace">Segment                         File (def ext: .dat)Acc Typ Block      Alloc Exten Options</font></b>
 <b><font face="Nimbus Mono L, monospace">-------------------------------------------------------------------------------------------</font></b>
 <b><font face="Nimbus Mono L, monospace">DEFAULT                         $vista_home/g/mumps.dat</font></b>
                                                     <b><font face="Nimbus Mono L, monospace">BG  DYN  4096      75000  2000 GLOB=2048</font></b>
                                                                                    <b><font face="Nimbus Mono L, monospace">LOCK=  40</font></b>

                                                                                    <b><font face="Nimbus Mono L, monospace">RES =   0</font></b>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GDE> <font color="#0000ff">show -map</font></b></font></font>

                                  <b><font face="Nimbus Mono L, monospace">*** MAP ***</font></b>
   <b><font face="Nimbus Mono L, monospace">-  -  -  -  -  -  -  -  -  - Names -  -  - -  -  -  -  -  -  -</font></b>
 <b><font face="Nimbus Mono L, monospace">From                            Up to                            Region / Segment / File(def ext: .dat)</font></b>

 <b><font face="Nimbus Mono L, monospace">-----------------------------------------------------------------------------------------------------------------------------------</font></b>
 <b><font face="Nimbus Mono L, monospace">%                               ...                              REG = DEFAULT</font></b>
                                                                  <b><font face="Nimbus Mono L, monospace">SEG = DEFAULT</font></b>
                                                                  <b><font face="Nimbus Mono L, monospace">FILE = $vista_home/g/mumps.dat</font></b>
 <b><font face="Nimbus Mono L, monospace">LOCAL LOCKS                                                      REG = DEFAULT</font></b>
                                                                  <b><font face="Nimbus Mono L, monospace">SEG = DEFAULT</font></b>

                                                                  <b><font face="Nimbus Mono L, monospace">FILE = $vista_home/g/mumps.dat</font></b>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GDE> <font color="#0000ff">quit</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GDE-I-NOACTION, Not updating Global Directory /home/dsl/myVistA/FOIAVistA/g/mumps.gld</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~$ </b></font></font>

In the example above, notice how the database file is defined in terrms of the environment variable $vista_home. This means that, as long as the environment variable $vista_home is defined, a global directory on the CD-ROM can serve to point to a database file wherever it happens to be on the system. This can allow two processes to share a global directory, but to have different database files.

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write $ZTRNLNM(<font face="Nimbus Mono L">"vista_home")</font></font></b></font></font>

<font face="Nimbus Mono L"><font size="2"><b>/home/dsl/myVistA/FOIAVistA</b></font></font>
<font face="Nimbus Mono L"><font size="2"><b>GTM></b></font></font>

<a name="$ZROUTINES and $ZGBLDIR vs. UCI & Volume set|outline"></a>

$ZROUTINES and

$ZGBLDIR vs. UCI & Volume set

The GT.M environment is defined by $ZROutines and $ZGbldir. Concepts from other M implementations such as UCI and volume set do not exist on GT.M.

The GT.M separation between routines and the database is very powerful, especially in real-world environments. Apart from the flexibility this offers, it enables the practice of “defensive programming”, not unlike defensive driving. We are human beings who are prone to err, and defensive practices reduce the probability of errors.

<a name="Example: Development environments|outline"></a>Example: Development environments

The example below is adapted from a post I made on the <a href="http://lists.sourceforge.net/lists/listinfo/hardhats-members">Hardhats mailing list</a>.

Fil is <a href="http://hardhats.org/history/beza.html">Fil Beza</a>, a key contributor to VistA for two decades who passed away on February 3, 2005 (click on his name for tributes from those who knew him). He gave me permission to use his name in the GT.M Acculturation live CD, after I first developed this example in response to one of his posts on the mailing list.

If Fil and I are developers and Fil's project is involves work on certain Lab modules, he can create a /home/fil/lab subdirectory for his work and if my project is in Oncology, I can create a /home/bhaskar/onc subdirectory for my work. If the reference (or production) routines are in the directory /opt/vista_23.98/o for the object files and /opt/vista_23.98/r for the source files, I can copy the files I wish to work on from /opt/vista_23.98/r to /home/bhaskar/onc – I do not need to copy all 20,000+ routines to create my private environment – and work on them in /home/bhaskar/onc. I can set $ZROUtines to "/home/bhaskar/onc /opt/vista_23.98/o(/opt/vista_23.98/r)". As long as I have read access to /opt/vista_23.98/ and its subdirectories (e.g., by making them world read-only or setting up ownership and permissions so that I do not have write access), I can continue to use all routines there except those for which I have a private copy, and I cannot possibly either deliberately or inadvertently change the reference / production routines. Note that while I technically do not need access to /opt/vista_23.98/r, I nevertheless still include it in my $ZROUtines so that I can read the source code of any routine that need to examine.

Similarly, Fil can set his $ZROUtines to "/home/fil/lab /opt/vista_23.98/o(/opt/vista_23.98/r)". All he needs to do is copy that set of routines that he wants to work on from /opt/vista_23.98/r to /home/fil/lab and change them. He doesn't need to copy all 20,000+ routines into his private environment. We can also ensure that Fil cannot deliberately or inadvertently change anything in the reference / production environment, while continuing to use the routines therein. This is shown in the diagram below (the link to /opt/vista_23.98/o to find object code modules also includes a parenthetic reference to /opt/vista_23.98/r for the corresponding source code modules so that they can be examined):

<img src="index_files/041210-1EnvironmentExample1.jpg" name="graphics4" align="left" border="0" height="610" width="687">
Now consider when Fil and I are done with our work. Since he and I have been working in parallel, we will want to test our work for mutual (in)compatibility. I can set my $ZROUtines to "/home/bhaskar/onc /home/fil/lab /opt/vista_23.98/o(/opt/vista_23.98/r)" and Fil can set his $ZROUtines to "/home/fil/lab /home/bhaskar/onc /opt/vista_23.98/o(/opt/vista_23.98/r)". This allows us to use each other's routines in our own unit test environments to see whether we have stepped on each other's toes. We can find and address conflicts that go beyond both of us changing the same code module. This is shown below.

<img src="index_files/041210-1EnvironmentExample2.gif" name="graphics5" align="left" border="0" height="523" width="588">
GT.M also simplifies version control, because it means that when I am ready to check in my work, the only files we need to look at are in /home/bhaskar/lab, since I could not possibly have changed anything in reference / production, even inadvertently.

We can take this example further. Suppose that Fil and I are doing our work with a new GT.M version and part of what we are doing is to enhance the application software to take advantage of a new feature in the new release, say a $ZMAgic() function. He and I can set up a shared directory, say /var/newobj to which we both have read/write access. I can set up $ZROUtines to be "/home/bhaskar/onc /var/newobj(/opt/vista_23.98/r)" and Fil can set up his $ZROUtines to be "/home/fil/lab /var/newobj(/opt/vista_23.98/r)". Now, whenever he or I reference a routine from the reference / production environment, a new object module compiled by the new GT.M version will be dynamically compiled and placed in /var/newobj, but the source routines in /opt/vista_23.98/r are unaltered.

There are similar things we can do with M globals using a global directory pointed to by $ZGBLdir. For example, if the data dictionary is defined in ^DIC, Fil and I can create global directories that refer to ^DIC in the production / reference database. If we have read-only access to that database file, we cannot possibly change it during the course of our development, not even inadvertently, and we are assured that our software is compatible with the production data dictionary. Taking this one step further, if I know that my oncology work is only supposed to affect globals ^ABC and ^DEF, I can set up a global directory and a sandbox database file that allows me read/write access only to those two globals, and read-only access to everything else. [Note, this slicing and dicing of globals is done at the level of the global variable, and not at the level of a subscript.]

GT.M also simplifies version control, because it means that when I am ready to check in my work, the only files we need to look at are in /home/bhaskar/lab, since I could not possibly have changed anything in reference / production, even inadvertently.

We can take this example further. Suppose that Fil and I are doing our work with a new GT.M version and part of what we are doing is to enhance the application software to take advantage of a new feature in the new release, say a $ZMAgic() function. He and I can set up a shared directory, say /var/newobj to which we both have read/write access. I can set up $ZROUtines to be "/home/bhaskar/onc /var/newobj(/opt/vista_23.98/r)" and Fil can set up his $ZROUtines to be "/home/fil/lab /var/newobj(/opt/vista_23.98/r)". Now, whenever he or I reference a routine from the reference / production environment, a new object module compiled by the new GT.M version will be dynamically compiled and placed in /var/newobj, but the source routines in /opt/vista_23.98/r are unaltered.

There are similar things we can do with M globals using a global directory pointed to by $ZGBLdir. For example, if the data dictionary is defined in ^DIC, Fil and I can create global directories that refer to ^DIC in the production / reference database. If we have read-only access to that database file, we cannot possibly change it during the course of our development, not even inadvertently, and we are assured that our software is compatible with the production data dictionary. Taking this one step further, if I know that my oncology work is only supposed to affect globals ^ABC and ^DEF, I can set up a global directory and a sandbox database file that allows me read/write access only to those two globals, and read-only access to everything else. [Note, this slicing and dicing of globals can be done at the level of the global variable, and not at the level of a subscript.]

<a name="Example: Application Service Provider|outline"></a>Example: Application Service Provider

In an Application Service Provider (ASP) environment, the same application code can be used for a number of customers, but each customer has its own database. Sometimes parts of the database may also be common and used on a read-only basis for normal operation, such as a data dictionary, an approved drug formulary, or a table of sales tax rates for each county or municipality. Each customer may also have a small set of custom routines. In a “Harry Potter meets the magic of VistA” example, let us consider an ASP serving St. Mungo's Hospital as well as Azkaban Infirmary:

  • The majority of routines are shared with object files in /opt/vista_23.98/o and source files in /opt/vista_23.98/r.

  • Custom

    routines for St. Mungo's in /var/stmungos/o & /var/stmungos/r for object & source respectively.

  • Similarly,

    custom routines for Azkaban are in /var/azkaban/o

    & /var/azkaban/r.

  • The

    National Drug File as approved by the Ministry of Magic in ^PSNDF is shared by both institutions, but all other data is institution specific. ^PSNDF

    is in /opt/vista_23.98/g/ndf.dat.

  • All other globals for St. Mungo's are in /var/stmungos/g/mumps.dat.

  • All other globals for Azkaban are in /var/azkaban/g/mumps.dat.

One way to accomplish this is as follows:

  • There will be two Linux groups, stmungos and azkaban. All St. Mungo's users will belong to the former, and all Azkaban users will belong to the latter.

  • /var/stmungos

    will have subdirectory o

    for object files of M routines that are used only by St. Mungo's; subdirectory r for source files of M routines specific to St. Mungo's; subdirectory g for the database file /var/stmungos/g/mumps.dat; and subdirectory j for the journal files. Note that /var/stmungos/j

    will actually be a file system mounted on a different disk and a different controller, either mounted at /var/stmungos/j or pointed to as a symbolic link by /var/stmungos/j – in a production environment, for reasons of recoverability from a hardware failure, it is desirable for a database file and its journal file to reside on different hard drives with different controllers. /var/stmungos/g/mumps.dat, /var/stmungos/j and /var/stmungos/j/mumps.mjl

    will be read-writable only by members of the group stmungos. No one else will even have read-only access. /var/stmungos/o and /var/stmungos/r will be read-only directories, since the only time to change a routine (or its object code) will be when the application is being updated. At all other times, we will use Linux file permissions to ensure that routines cannot even inadvertently be altered.

  • /var/azkaban

    will be similarly configured to be accessible by Azkaban users and no one else.

  • /opt/vista_23.98

    and all subdirectories and files are available to all users but on a read-only basis. The subdirectories will be o for object files, r for routines, and g

    for a global directory, /opt/vista_23.98/g/mumps.gld as well as for the national drug database file /opt/vista_23.98/g/ndf.dat. Note that ndf.dat

    is used read-only, and static files do not need to be journaled.

  • The

    global directory /opt/vista_23.98/g/mumps.gld

    will have two name spaces, NDF, to which will be directed, and which will point to the database file /opt/vista_23.98/g/ndf.dat and DEFAULT which will point to /var/$GROUP/g/mumps.dat. The environment variable $GROUP will be set in the Linux shell when a user logs in, and used by the sole global directory /opt/vista_23.98/g/mumps.gld

    to point GT.M processes from each hospital to their appropriate database.

  • The

    commands below in the file /etc/profile.local are used to set the environment variables for all users on the system. Note the use of the environment variable $GROUP to again set the correct value of $gtmroutines

    appropriately for each user.

<font face="Nimbus Mono L, monospace"><font size="2"><b>export GROUP=${GROUP:=`id -gn`}</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>export gtm_dist=/usr/local/gtm ; source $gtm_dist/gtmprofile</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>export gtmgbldir=/opt/vista_23.98/g/mumps.gld</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>export gtmroutines="/var/$GROUP/o(/var/$GROUP/r) /opt/vista_23.98/o(/opt/vista_23.98/r) $gtm_dist"</b></font></font>

It is worth taking the time to review the above example, to see how with maximum commonality and minimal customization, each user is directed to the correct database and routines for his/her institution. Note that even if a user were to manually change his environment variables and attempt to access the database and routines of another institution, the Linux file system permissions would prevent such unauthorized

access.

<a name="Exercise – GDE commands for ASP|outline"></a>Exercise – GDE commands for ASP

Write the commands to be used by GDE to create the global directory /opt/vista_23.98/g/mumps.gld. Assume that maximum key size is 255 bytes, the maximum record size is 2000 bytes, the desired block size is 4096 bytes, and the number of global buffers is 4000 for each institution's main database, and 1000 for the National Drug File database.

<a name="GT.M leverages the operating system|outline"></a>GT.M leverages the operating system

Wherever possible, the GT.M philosophy is to leverage what is already there in the underlying computer system, rather than reinventing it. For example, you use the editor of your choice when editing M routines. You used the beaver editor earlier; now try another, e.g., nano.

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~$ <font color="#ff0000">export EDITOR=`which nano`</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~$ <font color="#ff0000">myVistA/FOIAVistA/run</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">ZEDit "XYZ"</font></b></font></font>

<a name="Security|outline"></a><a name="Security|outline"></a>Security

In order to meet the needs of financial applications, GT.M was designed from the very beginning to be secure. [Caveat: absolute security does not exist in this universe. For a discussion that bridges philosophy and technology, I highly recommend Bruce Schneier's Secrets and Lies, ISBN 0-471-25311-1.]

A GT.M process can access a database file only if the file ownership and permissions allow that access. Under normal operation, there is no component of GT.M that operates as the super user (root). The GT.M security model is simple, well understood and documented.

It is extremely straightforward to create a user id that can only login, run VistA and log out.

<a name="Exercise – Security|outline"></a>Exercise – Security

In the following, notice how Linux file permissions are used to allow user dsl full access to the database, and preventing another user from updating a database, while allowing that user to read from it. Notice how the commands source /usr/local/gtm/gtmprofile, mumps -run ^GDE and mupip create are used to set up the GT.M environment, create a global directory and create the database file(s). In subsequent exercises, you will have to remember to do that yourself without being told!

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~$ <font color="#ff0000">mkdir myVistA/tmp ; cd myVistA/tmp</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">source /usr/local/gtm/gtmprofile</font> </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mumps -run ^GDE</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GDE-I-GDUSEDEFS, Using defaults for Global Directory </b></font></font>
        <b><font face="Nimbus Mono L, monospace">/ramdisk/home/dsl/myVistA/tmp/mumps.gld</font></b>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GDE> <font color="#0000ff">change -segment DEFAULT -file=/home/dsl/myVistA/tmp/mumps.dat</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GDE> <font color="#0000ff">exit</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GDE-I-VERIFY, Verification OK</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>%GDE-I-GDCREATE, Creating Global Directory file </b></font></font>
        <b><font face="Nimbus Mono L, monospace">/ramdisk/home/dsl/myVistA/tmp/mumps.gld</font></b>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mupip create</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Created file /home/dsl/myVistA/tmp/mumps.dat</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">chmod o-w mumps.dat</font> </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">ls -l mumps.dat</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-r--    1 dsl      staff      169472 Mar 22 21:41 mumps.dat</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Set ^X=1</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>1</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Halt</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">sudo su - lp</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>lp@ttyp0[lpd]$ <font color="#ff0000">cd /home/dsl/myVistA/tmp</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>lp@ttyp0[tmp]$ <font color="#ff0000">source /usr/local/gtm/gtmprofile</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>lp@ttyp0[tmp]$ <font color="#0000ff">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>1</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Kill ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-E-DBPRIVERR, No privilege for attempted update operation for file: /home/dsl/myVistA/tmp/mumps.dat</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Halt</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>lp@ttyp0[tmp]$ <font color="#ff0000">exit</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>logout</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">cd ../..</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~$ <font color="#ff0000">rm -rf myVistA/tmp</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~$ </b></font></font>

<a name="No special startup or shutdown|outline"></a>No special startup or shutdown

The first process to open a database file sets up all the shared memory control structures needed. The last one out tears it down. There is no daemon that must run as root that can be a single point of failure, a performance bottleneck, or a potential security vulnerability.

Upon bringing the system back up, if the system crashes, or is forcibly brought down: if journaling is in use, mupip journal -recover (or mupip journal -rollback if replication is in use) will recover the database. If journaling is not in use, mupip rundown -region "*" will clean up the database, but cannot fix any integrity errors caused, for example, but shutting down a computer without cleanly terminating GT.M processes. [Note: do not use mupip rundown if journaling is in use and you plan to recover the database after a crash with a mupip journal operation.]

<a name="Journaling – the key to database integrity|outline"></a> Journaling – the key to database integrity

GT.M, like virtually all high performance databases, uses journaling (called “logging” by some databases) to restore data integrity and provide continuity of business after an unplanned event such as a system crash.

There are two switches to turn on journaling – ENable / DISable and ON/OFF. Enabling or disabling journaling requires stand alone access to the database. Turning journaling on and off can be done when the database is in use.

<a name="Exercise - journaling|outline"></a><a name="Exercise - journaling|outline"></a> Exercise - journaling

Here, we will set up journaling for a database, simulate a crash, and recover the database from the journal file. Since GT.M database administration commands are normally issued from the Linux shell, outside GT.M, we will manually set up the environment GT.M expects (which thus far has been done in shell scripts). Also, note that the Linux command ipcs -m is used twice: first to report on shared memory segments that exist before any database access; and again after the database has been accessed – the additional shared memory segment reported the second time is used by GT.M for the database file. A system crash is simulated by deleting the shared memory segment used for the database and terminating the GT.M process (do not ever attempt the following on a real system except for testing purposes; because of the possibility of human error, do not ever do this on a machine where production applications are operating, even for testing).

Note that the numbers in fuchsia (light magenta) are process ids, and shared memory keys tht we will manipulate as part of the exercise. They will vary from machine to machine and run to run. You should use the values from your machine for your run. Create a directory ~/myVistA/tmp, set up the GT.M environment, create a global directory and an initial database (see <a href="#Exercise+%3F+Security%7Coutline">above</a>, if you don't remember how to). We start by turning on journaling for the newly created database.

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mupip set -journal="enable,on,before" -region "*"</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-JNLCREATE, Journal file /ramdisk/home/dsl/myVistA/tmp/mumps.mjl created for region DEFAULT with BEFORE_IMAGES</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-JNLSTATE, Journaling state for region DEFAULT is now ON</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">ls -l</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-rw-    1 dsl      staff      169472 Mar 23 12:48 mumps.dat</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-r--    1 dsl      staff        1024 Mar 23 12:48 mumps.gld</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-rw-    1 dsl      staff        2368 Mar 23 12:48 mumps.mjl</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">ZSYstem "ps -ef | grep mumps"</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl        <font color="#ff00ff">671</font>   631  0 12:48 ttyp1    00:00:00 mumps -dir</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl        672   671  0 12:49 ttyp1    00:00:00 /bin/bash -c ps -ef | grep mumps</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl        674   672  0 12:49 ttyp1    00:00:00 /bin/bash -c ps -ef | grep mumps</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">ZSYstem "ipcs -m"</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>------ Shared Memory Segments --------</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>key        shmid      owner      perms      bytes      nattch     status      </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>0x00000000 0          dsl       777        393216     2          dest         </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>0x00000000 557057     dsl       777        393216     2          dest         </b></font></font>


<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Kill ^X Set ^X=$Job</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">ZSYstem "ipcs -m"</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>------ Shared Memory Segments --------</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>key        shmid      owner      perms      bytes      nattch     status      </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>0x00000000 0          dsl       777        393216     2          dest         </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>0x00000000 557057     dsl       777        393216     2          dest         </b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>0x00000000 <font color="#ff00ff">655362</font>     dsl       777        2629632    1                       </b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font color="#ff00ff"><font face="Nimbus Mono L, monospace"><font size="2"><b>671</b></font></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">ZSYstem "sudo ipcrm -m <font color="#ff00ff">655362</font> ; kill -9 "_^X</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>Killed</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">ipcs -m</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>------ Shared Memory Segments --------</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>key        shmid      owner      perms      bytes      nattch     status      </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>0x00000000 0          dsl       777        393216     2          dest         </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>0x00000000 557057     dsl       777        393216     2          dest         </b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">ps -ef | grep mumps</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mupip journal -recover -backward mumps.mjl</font> </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUJNLSTAT, Initial processing started at Thu Mar 23 12:50:17 2006</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUJNLSTAT, Backward processing started at Thu Mar 23 12:50:17 2006</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUJNLSTAT, Before image applying started at Thu Mar 23 12:50:17 2006</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-FILERENAME, File /ramdisk/home/dsl/myVistA/tmp/mumps.mjl is renamed to /ramdisk/home/dsl/myVistA/tmp/mumps.mjl_2006082124931</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUJNLSTAT, Forward processing started at Thu Mar 23 12:50:17 2006<font color="#0000ff">Halt</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-S-JNLSUCCESS, Show successful</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-S-JNLSUCCESS, Verify successful</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-S-JNLSUCCESS, Recover successful</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUJNLSTAT, End processing at Thu Mar 23 12:50:17 2006</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>671</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Halt</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$</b></font></font>

Notice how the

journal file is used to recover the database.

<a name="Database replication|outline"></a>Database replication

When an application must have the best possible continuity of business, use database replication in addition to before image journaling to create a logical dual site configuration. A major restriction of GT.M replication today is that the primary and secondary must both be on Planet Earth. We will simulate a logical dual site configuration between a data center in Honolulu, Hawaii (21°N 157°W) and a data center in Ghanzi, Botswana (21°S 21°E), the furthest town from Honolulu big enough to have an airport, 12,400 miles away.

Network information: when Ghanzi is the secondary, it will listen to Honolulu on localhost:4265 (IP:port); when Honolulu is the secondary, it will listen to Ghanzi on localhost:3355. Configure replication as follows:

  • Create a directory /home/dsl/dualsite for this exercise, with subdirectories Honolulu and Ghanzi:

<font color="#ff0000"><font face="Nimbus Mono L, monospace"><font size="2"><b>mkdir -p myVistA/dualsite/{Honolulu,Ghanzi}</b></font></font></font>
  • Create two terminal windows, one simulating Honolulu and one simulating Ghanzi. Use different backgrounds so that they look visually different: right click on the screen background, choose Xshells and then your choice of background for the terminal window (Transparent, Light or Dark).

  • In the

    Honolulu window, change to the Honolulu subdirectory (cd myVistA/dualsite/Honolulu). In the Ghanzi window, change to the Ghanzi subdirectory (cd myVistA/dualsite/Ghanzi).

  • In each

    of Honolulu and Ghanzi (notice the use of the -replication=on switch to turn on replication):

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff0000">source /usr/local/gtm/gtmprofile</font></b></font></font>
<b><font face="Nimbus Mono L, monospace"><a href="mailto:dsl@box"><font color="#000000">dsl@box:~/myVistA/dualsite/Honolulu</font></a>$ <font color="#ff0000">export gtm_repl_instance=mumps.repl</font></font></b>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff0000">mumps -run ^GDE</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GDE> <font color="#0000ff">exit</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>...</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff0000">mupip create</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff0000">mupip set -journal="enable,before,on" -replication=on -region "*"</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff0000">mupip replicate -instance_create</font></b></font></font>
  • In Honolulu (/home/dsl/myVistA/dualsite/Honolulu), create four files as follows:

<font face="Nimbus Mono L, monospace"><font size="2"><b>primary_start:</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>#!/bin/bash</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>mupip replicate -source -start -buf=1 -secondary=localhost:4265 -log=source.log</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>primary_stop:</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>#!/bin/bash</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>mupip replicate -source -shutdown -timeout=0</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>mupip rundown -region "*"</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>secondary_start:</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>#!/bin/bash</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>mupip replicate -source -start -passive -buf=1 -log=source.log</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>mupip replicate -receive -start -listenport=3355 -buf=1 -log=receive.log</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>secondary_stop:</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>#!/bin/bash</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>mupip replicate -receive -shutdown -timeout=0</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>mupip replicate -source -shutdown -timeout=0</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>mupip rundown -region "*"</b></font></font>
  • Make the files executable: chmod a+x {primary,secondary}_{start,stop}

  • In Ghanzi

    (/home/dsl/myVistA/dualsite/Ghanzi) create files primary_start, primary_stop, secondary_start, secondary_stop which are identical to those in Honolulu, except that primary_start should specify the secondary as localhost:3355 and secondary_start

    should specify that the Receive Server should listen at port 4265. Make these files also executable. (It will probably be easiest to copy all four files and edit primary_start and secondary_start

    to make the changes.)

Operate the logical dual site configuration with Honolulu as the primary and Ghanzi as the secondary:

  • In Honolulu, start the primary: ./primary_start

  • In Ghanzi, start the secondary: ./secondary_start

  • Set a

    global variable in Honolulu, e.g., Set

    ^X=1

  • Notice how it is replicated in Ghanzi:

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>1</b></font></font>
  • Simulate a broken network connection (or a down secondary) by executing in Ghanzi: ./secondary_stop

  • Make a

    database change in Honolulu: e.g., Set

    ^X=2

  • Note how the change is not replicated in Ghanzi:

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>1</b></font></font>
  • Simulate restoring the network connection and/or bringing up the down secondary by executing in Ghanzi: ./secondary_start

  • Notice

    how Ghanzi automatically catches up (since with GT.M replication, the secondary listens at a TCP socket while the primary makes periodic attempts to connect to the secondary, it may take a few seconds for Honolulu to detect that Ghanzi is functional again and to resume replication; once replication is resumed, any backlog of

    data is rapidly streamed to the secondary):

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>2</b></font></font>

Execute a

failover for a planned outage at Honolulu:

  • Check the replication backlog in Honolulu to make sure that there is not a replication backlog: mupip replicate -source -showbacklog

  • Bring Honolulu down: ./primary_stop

  • Bring Ghanzi down as the secondary, and bring it back up as the primary:

<font color="#ff0000"><font face="Nimbus Mono L, monospace"><font size="2"><b>./secondary_stop</b></font></font></font>
<font color="#ff0000"><font face="Nimbus Mono L, monospace"><font size="2"><b>./primary_start</b></font></font></font>
  • Make some database updates to simulate Ghanzi operating as the primary. These will of course not be replicated in Honolulu – verify that Honolulu is indeed not being updated.

  • After

    simulated maintenance to Honolulu, bring it up as the secondary:

    ./secondary_start

  • Verify

    that Honolulu automatically catches up, that data is now replicated

    from Ghanzi to Honolulu and that Ghanzi reports no backlog.

<a name="Replication and Backlogs|outline"></a>Replication and Backlogs

In an ideal world, a primary never goes down when there is a backlog. In the real world, the primary may well go down with a backlog of updates that have not been replicated on the secondary. In order to provide continuity of business, the former secondary must come up as the new primary to keep the application available. When the former primary comes up as the new secondary, the updates that were part of the backlog must be handled. GT.M provides the hooks needed to create applications that are continuously available, but the application must take advantage of these hooks. Consider the following example (the notation P: 100 means that the site is operating as the primary and has committed update number 100):

<col width="128"> <col width="128"> <thead> </thead> <tbody> </tbody>

Honolulu

Ghanzi

P: 100

S: 95 (backlog of 5 updates)

Crashes

P: 95 (becomes the primary and starts processing)

Repaired and brought back up

P: 120 (processing moves it ahead)

This situation would appear to be problematic, because updates 96-100 on Honolulu are different from updates 96-100 on Ghanzi. The GT.M solution is to rollback those transactions on the former primary / new secondary. These rolled back updates (referred to as “lost transactions”) are placed in a file by GT.M, and must be handled. The -fetchresync and -losttrans qualifiers to the mupip journal -rollback command deal with the situation where a former primary comes up as the new secondary. The -fetchresync qualifier causes mupip journal -rollback to ask the new primary for the update number at which it became the primary, and rolls back the database to that point. The updates that are rolled off are placed in a “lost transaction file” from which the application can determine what should be done with them (they are sent to the new primary for reprocessing).

<col width="128"> <col width="128"> <thead> </thead> <tbody> </tbody>

Honolulu

Ghanzi

S: 95 (database recovered and rolled back from 100 to 95; lost transaction file created sent to Ghanzi for reprocessing)

P: 120

S: 120 (catches up shortly after coming back up and being reconnected)

P: 120

S: 125 (lost transactions make it back after reprocessing)

P: 125 (updates from lost transaction file reprocessed)

<a name="Exercise – replication backlogs|outline"></a>Exercise – replication backlogs

The exercise below simulates the situation above (as before fuchsia / light magenta is used for process ids and memory keys that will vary from run to run):

  • In Honolulu, start the primary, and simulate some updates (note that when simulating a crash in a replicated environment, there are two processes to be killed – the mumps process and the source server, a mupip process; also the shared memory sections are created by the source server even before the GT.M process attaches to them, which it does when it updates the database):

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff0000">ipcs -m</font>        </b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>------ Shared Memory Segments --------</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>key        shmid      owner      perms      bytes      nattch     status      </b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff0000">./primary_start</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff0000">ipcs -m</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>------ Shared Memory Segments --------</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>key        shmid      owner      perms      bytes      nattch     status      </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>0x00000000 <font color="#ff00ff">4653056</font>    dsl       777        1048576    1                       </b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>0x00000000 <font color="#ff00ff">4685825</font>    dsl       777        2629632    1                       </b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff3366">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Set ^X=$Job</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>926</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">ZSYstem "ps -ef | grep -E \(mumps\)\|\(mupip\) ; ipcs -m"</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl        <font color="#ff00ff">924</font>     1  0 14:28 ?        00:00:00 mupip replicate -source -start -buf=1 -secondary=localhost:4265 -log=source.log</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl        <font color="#ff00ff">926</font>   863  0 14:29 ttyp1    00:00:00 mumps -dir</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl        928   926  0 14:29 ttyp1    00:00:00 /bin/bash -c ps -ef | grep -E \(mumps\)\|\(mupip\) ; ipcs -m</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl        930   928  0 14:29 ttyp1    00:00:00 /bin/bash -c ps -ef | grep -E \(mumps\)\|\(mupip\) ; ipcs -m</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>------ Shared Memory Segments --------</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>key        shmid      owner      perms      bytes      nattch     status      </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>0x00000000 <font color="#ff00ff">4653056</font>    dsl       777        1048576    2                       </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>0x00000000 <font color="#ff00ff">4685825</font>    dsl       777        2629632    2                       </b></font></font>


<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM></b></font></font>
  • In Ghanzi, verify that replication is operating normally. Then bring down the secondary so that a backlog can be built up on the primary to simulate a crash with a backlog:

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Ghanzi$ <font color="#ff0000">./secondary_start</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Ghanzi$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>926</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Halt</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Ghanzi$ .<font color="#ff0000">/secondary_stop</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Thu Mar 23 14:32:39 2006 : Initiating shut down</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Signalling immediate shutdown</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Receive pool shared memory removed</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Receive pool semaphore removed</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Thu Mar 23 14:32:40 2006 : Initiating shut down</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>Signalling shutdown immediate</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Journal pool shared memory removed</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Journal pool semaphore removed</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUFILRNDWNSUC, File /ramdisk/home/dsl/myVistA/dualsite/Ghanzi/mumps.dat successfully rundown</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Ghanzi$ </b></font></font>
  • In Honolulu, perform an update, which will become the backlog when Honolulu crashes (after Honolulu recovers and becomes a new secondary, this backlog will become the lost transaction(s)). Simulate a crash (note that in a replicated environment, in addition to the shared memory segment for the database region, there is also one for the journal pool; also both the mumps and mupip processes will need to be terminated):

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Set ^X=^X_" Backlog "_$H</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>926 Backlog 60347,52517</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">ZSYstem "mupip replicate -source -showbacklog"</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>1 : backlog number of transactions written to journal pool and yet to be sent by the source server</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>2 : sequence number of last transaction written to journal pool</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>1 : sequence number of last transaction sent by source server</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">ZSYstem "mupip replicate -source -checkhealth"</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>PID <font color="#ff00ff">924</font> Source server is alive</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">ZSYstem "ipcrm -m <font color="#ff00ff">4653056</font> -m <font color="#ff00ff">4685825</font> ; kill -9 <font color="#ff00ff">924</font> <font color="#ff00ff">926</font>"</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>Killed</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ ipcs -m</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>------ Shared Memory Segments --------</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>key        shmid      owner      perms      bytes      nattch     status      </b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ ps -ef | grep -E \(mupip\)\|\(mumps\)</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ </b></font></font>
  • Bring Ghanzi up to take over as the new primary, keeping the application available, and perform some updates to simulate activity. Also, verify that the backlog in Honolulu really is a backlog, and was not replicated to Ghanzi.

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Ghanzi$ <font color="#ff0000">./primary_start</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Ghanzi$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>926</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Set ^X=$J_" Ghanzi "_$H</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>974 Ghanzi 60347,52928</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM></b></font></font>
  • Now simulate a recovery of the system in Honolulu. When it comes up, use the -fetchresync qualifier to have Honolulu query Ghanzi so that it can roll back the lost transactions.

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff0000">mupip journal -rollback -backward -fetchresync=3355 -losttrans=Lost_Trans_Report_`date +%Y%m%d%H%M%S`.txt "*"</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUJNLSTAT, Initial processing started at Thu Mar 23 14:44:16 2006</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUJPOOLRNDWNSUC, Jnlpool section (id = 688129) belonging to the replication instance /ramdisk/home/dsl/myVistA/dualsite/Honolulu/mumps.repl successfully rundown</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-SEMREMOVED, Semaphore id 688129 removed from the system</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUJNLSTAT, FETCHRESYNC processing started at Thu Mar 23 14:44:16 2006</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Thu Mar 23 14:44:16 2006 : Waiting for a connection...</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Thu Mar 23 14:44:20 2006 : Connection established</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Thu Mar 23 14:44:20 2006 : Received RESYNC SEQNO is 2</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUJNLSTAT, Backward processing started at Thu Mar 23 14:44:20 2006</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-RESOLVESEQNO, Resolving until sequence number 0x0000000000000002</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUJNLSTAT, Before image applying started at Thu Mar 23 14:44:20 2006</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-FILERENAME, File /ramdisk/home/dsl/myVistA/dualsite/Honolulu/mumps.mjl is renamed to /ramdisk/home/dsl/myVistA/dualsite/Honolulu/mumps.mjl_2006082143523</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUJNLSTAT, Forward processing started at Thu Mar 23 14:44:20 2006</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-FILECREATE, Lost transactions extract file Lost_Trans_Report_20060323144416.txt created</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-RLBKJNSEQ, Journal seqno of the instance after rollback is 2 [0x0000000000000002]</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-S-JNLSUCCESS, Show successful</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-S-JNLSUCCESS, Verify successful</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-S-JNLSUCCESS, Rollback successful</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUJNLSTAT, End processing at Thu Mar 23 14:44:21 2006</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:<font color="#ff0000">~/myVistA/dualsite/Honolulu$ cat Lost_Trans_Report_20060323144416.txt</font> </b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GDSJEX01</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>05\60347,52517\2\926\0\2\^X="926 Backlog 60347,52517"</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ </b></font></font>
  • Now start Honolulu as the secondary, and note how it automatically catches up with updates made in Ghanzi (with a possible lag of a few seconds for Ghanzi to detect that Honolulu is up and ready to receive updates):

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff0000">./secondary_start</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>926</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>926</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write ^X</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>974 Ghanzi 60347,52928</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Halt</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$</b></font></font>
  • Shut down Honolulu and Ghanzi cleanly to end the exercise:

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Ghanzi$ .<font color="#ff0000">/primary_stop</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Thu Mar 23 14:47:17 2006 : Initiating shut down</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>Signalling shutdown immediate</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Journal pool shared memory removed</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Journal pool semaphore removed</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUFILRNDWNSUC, File /ramdisk/home/dsl/myVistA/dualsite/Ghanzi/mumps.dat successfully rundown</b></font></font>
<b><font face="Nimbus Mono L, monospace"><a href="mailto:dsl@box">dsl@box</a>:~/myVistA/dualsite/Ghanzi$</font></b>

<font face="Nimbus Mono L, monospace"><font size="2"><b>...</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$ <font color="#ff0000">./secondary_stop</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>Thu Mar 23 14:47:20 2006 : Initiating shut down</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Signalling immediate shutdown</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Receive pool shared memory removed</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Receive pool semaphore removed</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Thu Mar 23 14:47:21 2006 : Initiating shut down</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Signalling shutdown immediate</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Journal pool shared memory removed</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Journal pool semaphore removed</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-MUFILRNDWNSUC, File /ramdisk/home/dsl/myVistA/dualsite/Honolulu/mumps.dat successfully rundown</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/dualsite/Honolulu$</b></font></font>

<a name="Backup|outline"></a>Backup

Backup when an application is not running is straightforward – just copy the database files.

Backup when an application is operating normally, without impacting the application (except of course for the additional IO load of the backup activity) is easy with GT.M, and can be accomplished in two ways, one non-GT.M and other GT.M:

  • The non-GT.M way is to use a disk mirror (e.g., RAID or SAN). Issue a mupip freeze to momentarily freeze updates and flush updates to disk, break the mirror; then release the freeze. After backing up the mirror, remake it, and let it “catch up.”

  • The GT.M

    way: a transaction-consistent backup of an entire multi-region database can be accomplished with a single GT.M command: mupip backup. There are numerous options to satisfy virtually every type

    of backup need.

<a name="Exercise - backup|outline"></a>Exercise - backup

  • Create a temporary directory (if you don't have one already) and a subdirectory for the backup database files, and change to the temporary directory. Create a global directory & database file, and turn journaling on (see <a href="#Exercise%20-%20journaling%7Coutline">above</a> if you don't remember how to do this).

  • Create a

    GT.M program XYZ in file XYZ.m as follows (the Hang

    command is not strictly necessary, but is used simply to keep the volume of data manageable in a demonstration environment that may be operating in a “disk” with tight space constraints, such as a USB flash drive):

<font face="Nimbus Mono L, monospace"><font size="2"><b>XYZ    Set (^x,^y)=0</b></font></font>
       <b><font face="Nimbus Mono L, monospace">For  Do</font></b>
       <b><font face="Nimbus Mono L, monospace">.Hang 0.1</font></b>

       <b><font face="Nimbus Mono L, monospace">.Tstart ()</font></b>
       <b><font face="Nimbus Mono L, monospace">.Set r=$Random(2147483646)</font></b>
       <b><font face="Nimbus Mono L, monospace">.Set ^x=^x-r</font></b>
       <b><font face="Nimbus Mono L, monospace">.Set ^y=^y+r</font></b>
       <b><font face="Nimbus Mono L, monospace">.Tcommit</font></b>
       <b><font face="Nimbus Mono L, monospace">Quit</font></b>
  • Start the program as a background process from the shell: mumps -run ^XYZ </dev/null >&/dev/null &

  • Take a

    backup of the entire database (a “comprehensive”

    backup):

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mupip backup "*" backup/</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-FILERENAME, File /ramdisk/home/dsl/myVistA/tmp/mumps.mjl is renamed to /ramdisk/home/dsl/myVistA/tmp/mumps.mjl_2006083154324</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-JNLCREATE, Journal file /ramdisk/home/dsl/myVistA/tmp/mumps.mjl created for region DEFAULT with BEFORE_IMAGES</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>DB file /ramdisk/home/dsl/myVistA/tmp/mumps.dat backed up in file backup//mumps.dat</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Transactions up to 0x0000000000000287 are backed up.</b></font></font>


<font face="Nimbus Mono L, monospace"><font size="2"><b>BACKUP COMPLETED.</b></font></font>
  • Take a backup of that part of the database that has changed (a “bytestream” backup). Note the use of the -since=database qualifier to only backup those database blocks that have changed since the last backup of the entire database):

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mupip backup -bytestream -since=database "*" backup/mumps`date +%Y%m%d%H%M%S`.bck</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-FILERENAME, File /ramdisk/home/dsl/myVistA/tmp/mumps.mjl is renamed to /ramdisk/home/dsl/myVistA/tmp/mumps.mjl_2006083154420</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-JNLCREATE, Journal file /ramdisk/home/dsl/myVistA/tmp/mumps.mjl created for region DEFAULT with BEFORE_IMAGES</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>MUPIP backup of database file /ramdisk/home/dsl/myVistA/tmp/mumps.dat to backup/mumps20060324154420.bck</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>DB file /ramdisk/home/dsl/myVistA/tmp/mumps.dat incrementally backed up in file backup/mumps20060324154420.bck</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>5 blocks saved.</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>Transactions from 0x0000000000000287 to 0x000000000000047C are backed up.</b></font></font>


<font face="Nimbus Mono L, monospace"><font size="2"><b>BACKUP COMPLETED.</b></font></font>
  • Take further bytestream backups of that part of the database that has changed – as many as desired (note the use of the -since=bytestream qualifier to backup only those blocjs that have changed since the last bytestream backup):

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$  <font color="#ff0000">mupip backup -bytestream -since=bytestream "*" backup/mumps`date +%Y%m%d%H%M%S`.bck</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-FILERENAME, File /ramdisk/home/dsl/myVistA/tmp/mumps.mjl is renamed to /ramdisk/home/dsl/myVistA/tmp/mumps.mjl_2006083154449</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-JNLCREATE, Journal file /ramdisk/home/dsl/myVistA/tmp/mumps.mjl created for region DEFAULT with BEFORE_IMAGES</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>MUPIP backup of database file /ramdisk/home/dsl/myVistA/tmp/mumps.dat to backup/mumps20060324154449.bck</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>DB file /ramdisk/home/dsl/myVistA/tmp/mumps.dat incrementally backed up in file backup/mumps20060324154449.bck</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>5 blocks saved.</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Transactions from 0x000000000000047C to 0x0000000000000586 are backed up.</b></font></font>


<font face="Nimbus Mono L, monospace"><font size="2"><b>BACKUP COMPLETED.</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mupip backup -bytestream -since=bytestream "*" backup/mumps`date +%Y%m%d%H%M%S`.bck</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-FILERENAME, File /ramdisk/home/dsl/myVistA/tmp/mumps.mjl is renamed to /ramdisk/home/dsl/myVistA/tmp/mumps.mjl_2006083154508</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-JNLCREATE, Journal file /ramdisk/home/dsl/myVistA/tmp/mumps.mjl created for region DEFAULT with BEFORE_IMAGES</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>MUPIP backup of database file /ramdisk/home/dsl/myVistA/tmp/mumps.dat to backup/mumps20060324154508.bck</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>DB file /ramdisk/home/dsl/myVistA/tmp/mumps.dat incrementally backed up in file backup/mumps20060324154508.bck</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>5 blocks saved.</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Transactions from 0x0000000000000586 to 0x000000000000062C are backed up.</b></font></font>


<font face="Nimbus Mono L, monospace"><font size="2"><b>BACKUP COMPLETED.</b></font></font>
  • Stop the process updating the database, take a final backup, and note the values of ^x and ^y (and verify that they still sum to zero). After the final restore, we will verify that the values restored from the backup is the same as these values. As before, note the use of fuschia to idenfy process ids that will change from machine to machine and run to run:

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">ps -ef | grep mumps</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl       <font color="#ff00ff">1183</font>  1180  0 15:42 ttyp1    00:00:01 mumps -run ^XYZ</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mupip stop</font> <font color="#ff00ff">1183</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>STOP issued to process <font color="#ff00ff">1183</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-F-FORCEDHALT, Image HALTed by MUPIP STOP</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>[1]+  Exit 241                mumps -run ^XYZ </dev/null >/dev/null</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mupip backup -bytestream -since=bytestream "*" backup/mumps`date +%Y%m%d%H%M%S`.bck</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-FILERENAME, File /ramdisk/home/dsl/myVistA/tmp/mumps.mjl is renamed to /ramdisk/home/dsl/myVistA/tmp/mumps.mjl_2006083154529</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>%GTM-I-JNLCREATE, Journal file /ramdisk/home/dsl/myVistA/tmp/mumps.mjl created for region DEFAULT with BEFORE_IMAGES</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>MUPIP backup of database file /ramdisk/home/dsl/myVistA/tmp/mumps.dat to backup/mumps20060324154619.bck</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>DB file /ramdisk/home/dsl/myVistA/tmp/mumps.dat incrementally backed up in file backup/mumps20060324154619.bck</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>5 blocks saved.</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Transactions from 0x000000000000062C to 0x00000000000006EC are backed up.</b></font></font>


<font face="Nimbus Mono L, monospace"><font size="2"><b>BACKUP COMPLETED.</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write "^x+^y=",^x,"+",^y,"=",^x+^y,! Halt</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>^x+^y=-1879255318702+1879255318702=0</b></font></font>
  • Notice that each backup create a new journal file generation, and there is a chain of journal files. After a successful backup, older generations of journal files are no longer needed in a single site operating environment. In a dual site environment, primary journal files could be needed until the completion of a successful backup on the secondary.

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">ls -l</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-r--    1 dsl      staff         122 Mar 24 14:35 XYZ.m</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-r--    1 dsl      staff         825 Mar 24 15:42 XYZ.o</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>drwxrwxr-x    2 dsl      staff        4096 Mar 24 15:46 backup</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-rw-    1 dsl      staff      169472 Mar 24 15:47 mumps.dat</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-r--    1 dsl      staff        1024 Mar 24 14:32 mumps.gld</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-rw-    1 dsl      staff        2368 Mar 24 15:46 mumps.mjl</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-rw-    1 dsl      staff      116584 Mar 24 15:43 mumps.mjl_2006083154324</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-rw-    1 dsl      staff       91288 Mar 24 15:44 mumps.mjl_2006083154420</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-rw-    1 dsl      staff       49880 Mar 24 15:44 mumps.mjl_2006083154449</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-rw-    1 dsl      staff       32280 Mar 24 15:45 mumps.mjl_2006083154508</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-rw-    1 dsl      staff       36608 Mar 24 15:45 mumps.mjl_2006083154529</b></font></font>
  • To simulate restoring and recovering the database, first delete the database and journal files. Then “restore” the backup of the entire database by copying it in. Check the values of ^x and ^y to ensure that they add to zero.

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">rm mumps.dat mumps.mjl*</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">ls -l</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-r--    1 dsl      staff         122 Mar 24 14:35 XYZ.m</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-r--    1 dsl      staff         825 Mar 24 15:42 XYZ.o</b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>drwxrwxr-x    2 dsl      staff        4096 Mar 24 15:46 backup</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>-rw-rw-r--    1 dsl      staff        1024 Mar 24 14:32 mmumps.gld</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">cp -p backup/mumps.dat .</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write "^x+^y=",^x,"+",^y,"=",^x+^y,! Halt</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>^x+^y=-725290066926+725290066926=0</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$</b></font></font>
  • Restore the each bytestream backup, and verify that the absolute values of ^x and ^y increase, but they always sum to zero (because of the use of transaction processing). After the last backup is restored, note that the values of ^x and ^y are the same as they were in the original database when the process running routine XYZ was stopped.

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mupip restore mumps.dat backup/mumps20060324154420.bck</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>RESTORE COMPLETED</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>7 blocks restored</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write "^x+^y=",^x,"+",^y,"=",^x+^y,! Halt</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>^x+^y=-1233626317102+1233626317102=0</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mupip restore mumps.dat backup/mumps20060324154449.bck</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>RESTORE COMPLETED</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>7 blocks restored</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write "^x+^y=",^x,"+",^y,"=",^x+^y,! Halt</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>^x+^y=-1502392564483+1502392564483=0</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mupip restore mumps.dat backup/mumps20060324154508.bck</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>RESTORE COMPLETED</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>7 blocks restored</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write "^x+^y=",^x,"+",^y,"=",^x+^y,! Halt</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>^x+^y=-1670563955262+1670563955262=0</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mupip restore mumps.dat backup/mumps20060324154619.bck</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>RESTORE COMPLETED</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>5 blocks restored</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write "^x+^y=",^x,"+",^y,"=",^x+^y,! Halt</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>^x+^y=-1879255318702+1879255318702=0</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ </b></font></font>

<a name="Potential surprises|outline"></a>Potential surprises

If you are used to other M implementations, here are examples of things you may be used to that you won't find in GT.M:

  • Job Examine – there is not a built in function. But the functionality is easy to set up if you need it, e.g., see <a href="http://sourceforge.net/docman/display_doc.php?docid=19563&group_id=11026">GT.M Job Examine / System Status How To</a> (or <a href="file:///home/ivaldes/.gvfs/GT.MAcculturation0.4.iso/20060324JobExamineSystemStatusHowTo.html">local copy</a>).

  • Kill –

    there is no setting to prevent a Kill in a process that has update permission to a database file from killing an entire global

    variable.

  • Break –

    there is no concept of a “production” mode in which

    Break can be turned off.

<a name="Exploit integration with underlying operating system|outline"></a> Exploit integration with underlying operating system

If you need functionality that is not in GT.M, use it from the underlying operating system. For example, you can use Xdialog for dialog boxes for user interaction. In a temporary directory:

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mumps -dir</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Set file="/tmp/gtm"_$Job_".tmp"</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">ZSYstem "Xdialog --calendar ""Choose date"" 0 0 0 0 0 >&"_file</font></b></font></font><img src="index_files/20060324Xdialog.jpg" name="graphics6" align="right" border="0" height="246" width="280">

At this time, an Xdialog calendar prompt pops up, and you can choose a date. You can

choose a date, press OK, and read that date into GT.M:

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Open file Use file Read date</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Use $Principal Write date</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>13/03/2006</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Close file:Delete</font></b></font></font>

You can use

$ZCMdline to get command line parameters:

<font face="Nimbus Mono L, monospace"><font size="2"><b>dsl@box:~/myVistA/tmp$ <font color="#ff0000">mumps -dir Passing command lines to GT.M programs is really cool</font></b></font></font>

<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM><font color="#0000ff">Write $ZCMdline</font></b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>Passing command lines to GT.M programs is really cool</b></font></font>
<font face="Nimbus Mono L, monospace"><font size="2"><b>GTM></b></font></font>

You can freely mix routines written in C with routines written in M (caveat: a few restrictions apply because the GT.M runtime environment in each process includes a high performance database engine; refer to the documentation for details).

<a name="7.In conclusion|outline"></a>In conclusion

I hope that this write up has been useful to you. Please think about the following and send me e-mail.. Thank you very much.

  • What did you like about this GT.M Acculturation CD? What are some things that it accomplished well for you? In what way(s), if any, did it exceed your expectations?

  • What are

    some things that you did not care for? In what way(s) did it fall

    short? How can it be improved?

  • What is your background with M?

  • What is your background with GT.M?

If there is anything that you would like to share to help make GT.M, or this Acculturation CD more useful to you, please let me know.

K.S. Bhaskar
VP, Product Manager
Fidelity National Information Services, Inc.
<a href="mailto:ks.bhaskar@fnf.com">ks.bhaskar@fnf.com</a>
+1 (610) 578-4265



</body></html>