////
Package: Reference Standard M
File:    README.adoc
Summary: Basic getting started documentation

David Wicksell <dlw@linux.com>
Copyright © 2020-2024 Fourth Watch Software LC
https://gitlab.com/Reference-Standard-M/rsm

Based on MUMPS V1 by Raymond Douglas Newman
Copyright © 1999-2003
https://gitlab.com/Reference-Standard-M/mumpsv1

Permission is granted to copy, distribute and/or modify this document under
the terms of the GNU Free Documentation License, Version 1.3 or any later
version published by the Free Software Foundation; with no Invariant
Sections, with no Front-Cover texts, and with no Back-Cover Texts.

You should have received a copy of the GNU Free Documentation License along
with this program. If not, see https://www.gnu.org/licenses/.

SPDX-FileCopyrightText:  © 2020 David Wicksell <dlw@linux.com>
SPDX-License-Identifier: GFDL-1.3-no-invariants-or-later
////

:source-highlighter: highlight.js
:highlightjs-languages: bash, cos
:logo: image:https://www.fourthwatchsoftware.com/images/fws-logo-horizontal.png
:documentation: https://reference-standard-m.gitlab.io/rsm[documentation]

= Reference Standard M

{logo}[caption="Fourth Watch Software Logo", width="480", height="80"]

'''

== ANSI/MDC Standard M X11.1-1995 (ISO/IEC 11756:1999)

[.lead]
*Version 1.82.4 - 2024 Dec 9*

=== Copyright and License

Developed and maintained by David Wicksell <dlw@linux.com> +
Copyright © 2020-2024 Fourth Watch Software LC +
https://gitlab.com/Reference-Standard-M/rsm

Originally based on MUMPS V1 by Raymond Douglas Newman +
Copyright © 1999-2018 +
https://gitlab.com/Reference-Standard-M/mumpsv1

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License (AGPL) as published by the
Free Software Foundation, either version 3 of the License, or (at your option)
any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program. If not, see https://www.gnu.org/licenses/.

Full license text: link:COPYING[AGPL-3.0-or-later]

=== Summary and Information

Reference Standard M (RSM) is an implementation of the M programming language
and database, which implements the latest M standard that has been released by
the M Development Committee (MDC), currently ANSI/MDC X11.1-1995 (ISO/IEC
11756:1999).

RSM was originally named MUMPS V1 (MV1), and was created by Raymond Douglas
Newman. When I took over maintenance and development of MV1, I changed its name
to better reflect its use as a reference implementation for the MDC.

See the link:CHANGELOG.adoc[Changelog] for more information on the development
of Reference Standard M. The RSM {documentation} is a work-in-progress.
This software uses https://semver.org/[semantic versioning].

_This is the post-relational database._

=== Installation

RSM builds and runs on most UNIX, and UNIX-derived platforms, running 32-bit and
64-bit processors, in little-endian and big-endian mode. The platforms that have
been tested, and/or known (or suspected) to build and run RSM, are:

* Linux (Ubuntu, Debian, Red Hat, OpenSUSE, and Slackware) on i386 and x86_64
* Debian Linux on ppc64le
* Gentoo Linux on IA-64
* FreeBSD on amd64
* NetBSD on amd64
* OpenBSD on amd64
* macOS 10.4 and newer on ILP32 and LP64 Intel (Clang or GCC)
* macOS 11.0 and newer on 64-bit M1 ARMv8 (Clang or GCC)
* Solaris on i86pc and Sun-4v (SPARC)
* Tru64 on Alpha
* AIX on ppc32be and ppc64be
* HP-UX on IA-64
* Windows XP, 7, 10, and 11, under Cygwin
* Windows 10 and 11, under Windows Subsystem for Linux (WSL) 1 and 2
* Raspberry Pi on armv6l and armv7l running Raspbian
* Mobian (Mobile Debian Linux) on aarch64

Thanks to https://gitlab.com/jpwillis[John Willis] for providing access to the
build farm, and to https://github.com/racingmars[Matthew Wilson], Terry
Wiechmann, and Flavio Fornazier for helping me with testing.

To build RSM, clone the RSM git repository:

[source,bash]
----
$ git clone https://gitlab.com/Reference-Standard-M/rsm.git
----

Change to the `rsm` directory and build the `rsm` executable:

[source,bash]
----
$ make
----
or
[source,bash]
----
$ make -j
----

On Solaris:

[source,bash]
----
$ gmake
----
or
[source,bash]
----
$ gmake -j
----

The resulting `rsm` executable will be optimized for your system.

Install the `rsm` executable to the default bin directory [/usr/local/bin], and
the `utils.rsm` utilities to the default rsm directory [/usr/local/share/rsm]:

[source,bash]
----
$ sudo make install
----

Install the `rsm` executable to a different bin directory [/usr/bin], and the
`utils.rsm` utilities to a different rsm directory [/usr/share/rsm]:

[source,bash]
----
$ sudo make install prefix=/usr
----

On Cygwin (as administrator):

[source,bash]
----
$ make install
----

Clean up the build environment after installation:

[source,bash]
----
$ make clean
----

Uninstall the `rsm` executable from the default bin directory [/usr/local/bin],
and the `utils.rsm` utilities from the default rsm directory
[/usr/local/share/rsm]:

[source,bash]
----
$ sudo make uninstall
----

Uninstall the `rsm` executable from a different bin directory [/usr/bin], and
the `utils.rsm` utilities from a different rsm directory [/usr/share/rsm]:

[source,bash]
----
$ sudo make uninstall prefix=/usr
----

Install the documentation (asciidoc/man page) to the default rsm and man1
directories [/usr/local/share/doc/rsm, /usr/local/share/man/man1]:

[source,bash]
----
$ sudo make install-docs
----

Install the documentation (asciidoc/man page) to different rsm and man1
directories [/usr/share/doc/rsm, /usr/share/man/man1]:

[source,bash]
----
$ sudo make install-docs prefix=/usr
----

On Cygwin (as administrator):

[source,bash]
----
$ make install-docs
----

NOTE: On macOS and AIX, you might have to add the path that `make install-docs`
installed the `rsm` man page in, to the `MANPATH` environment variable

Uninstall the documentation (asciidoc/man page) from the default rsm and man1
directories [/usr/local/share/doc/rsm, /usr/local/share/man/man1]:

[source,bash]
----
$ sudo make uninstall-docs
----

Uninstall the documentation (asciidoc/man page) from different rsm and man1
directories [/usr/share/doc/rsm, /usr/share/man/man1]:

[source,bash]
----
$ sudo make uninstall-docs prefix=/usr
----

=== Usage

Output a short version string:

[source,bash]
----
$ rsm -V
----

Output a helpful options menu:

[source,bash]
----
$ rsm -h
----

NOTE: Set the environment variable `RSM_DBFILE` to the database file path to
avoid having to pass it to `rsm`

To use RSM, create a database:

[source,bash]
----
# Optional arguments in square brackets
#  -v <volume-name>        Name of volume             (1-32 alpha characters)
#  -b <block-size>         Size of database blocks    (1-256 KiB)
#  -s <database-size>      Initial size of database   (100-2147483647 blocks)
# [-m <map-size>]          Size of map block          (0-262147 KiB)
# [-e <environment-name>]  Name of manager UCI        (1-32 alpha characters)
# [<database-file>]        Name of the database file

$ rsm -v TST -b 16 -s 4096 tst.dat
----
or
[source,bash]
----
$ export RSM_DBFILE="/home/user/tst.dat"
$ rsm -v TST -b 16 -s 4096
----

NOTE: In order to load the supplied M utilities, use a block size of 14 KiB or
larger

Initialize and start the environment:

[source,bash]
----
# Optional arguments in square brackets
#  -j <max-jobs>          Size of job table in environment  (1-1024 jobs)
# [-g <global-buffers>]   Size of global buffers            (1-131072 MiB)
# [-r <routine-buffers>]  Size of routine buffers           (1-4095 MiB)
# [<database-file>]       Name of the database file

$ rsm -j 12 tst.dat
----
or
[source,bash]
----
$ export RSM_DBFILE="/home/user/tst.dat"
$ rsm -j 12
----

On macOS, you might need to increase the accessible shared memory before
starting the environment, if the previous command failed. If so, as root or
using `sudo`, run the following commands, adjusted based on your system
resources:

[source,bash]
----
# 2 GiB shared segment max:
$ sudo sysctl -w kern.sysv.shmmax=2147483648

# 8 GiB of system shared memory (in number of pages at 4096 bytes per page):
$ sudo sysctl -w kern.sysv.shmall=2097152
----

To persist the above configuration changes on macOS, you'll need to create a
property list configuration and load it so the daemon picks it up at boot time.
There is a sample plist XML file at `rsm/etc/sysctl.plist`. Run these commands,
after adjusting the `kern.sysv.shmmax` and `kern.sysv.shmall` settings based on
your system resources, and ensuring you aren't overwriting an existing file with
that name:

[source,bash]
----
# Copy plist configuration to the correct system location
$ sudo cp /Users/user/rsm/etc/sysctl.plist /Library/LaunchDaemons/sysctl.plist

# Change its ownership
$ sudo chown root:wheel /Library/LaunchDaemons/sysctl.plist

# Load it for the launch daemon to run at boot
$ sudo launchctl load /Library/LaunchDaemons/sysctl.plist
----

On Cygwin, you need to configure and start `cygserver` (as administrator) before
starting the RSM environment, as it provides the SysV shared memory support.

[source,bash]
----
$ cygserver-config
$ cygrunsrv -S cygserver
----

Output a database and environment configuration:

[source,bash]
----
$ rsm -i tst.dat
----
or
[source,bash]
----
$ export RSM_DBFILE="/home/user/tst.dat"
$ rsm -i
----

Load the M utilities (using the bootstrap method):

[source,bash]
----
# Optional arguments in square brackets
# -x <M-command(s)>        String of M commands to execute
# [-e <environment-name>]  Name of initial UCI environment
# [<database-file>]        Name of the database file

$ rsm -x 'open 1:("utils.rsm":"read") use 1 read code xecute code' tst.dat
----
or
[source,bash]
----
$ export RSM_DBFILE="/home/user/tst.dat"
$ rsm -x 'open 1:("utils.rsm":"read") use 1 read code xecute code'
----

Start direct mode:

[source,bash]
----
# Optional arguments in square brackets
# [-e <environment-name>]  Name of initial UCI environment
# [-R]                     Starts in restricted mode
# [<database-file>]        Name of the database file

$ rsm tst.dat
----
or
[source,bash]
----
$ export RSM_DBFILE="/home/user/tst.dat"
$ rsm
----

Run an M routine in indirect mode:

[source,bash]
----
# Start the M Command Language shell
# Optional arguments in square brackets
# -x <M-command(s)>        String of M commands to execute
# [-e <environment-name>]  Name of initial UCI environment
# [-R]                     Starts in restricted mode
# [<database-file>]        Name of the database file

$ rsm -x "do ^%M" tst.dat
----
or
[source,bash]
----
$ export RSM_DBFILE="/home/user/tst.dat"
$ rsm -x "do ^%M"
----

When upgrading to a new version of RSM, you might occasionally run in to an
issue executing a routine. Normally this will not be an issue, but if it is, you
can fix it by recompiling the routines:

[source,cos]
----
RSM [MGR,TST]> merge ^$routine("%RECOMP")=^$routine("%RECOMP")
RSM [MGR,TST]> do ^%RECOMP
----

Stop and shut down environment:

[source,bash]
----
$ rsm -k tst.dat
----
or
[source,bash]
----
$ export RSM_DBFILE="/home/user/tst.dat"
$ rsm -k
----

From within an RSM job:

[source,cos]
----
RSM [MGR,TST]> kill ^$job
----

If `utils.rsm` has been loaded:

[source,cos]
----
RSM [MGR,TST]> do ^SSD
----

=== Docker Container

To download the latest RSM Docker image from Docker Hub:

[source,bash]
----
$ docker pull dlwicksell/rsm
----

To build the RSM Docker image from source, while in the `rsm` directory:

[source,bash]
----
$ docker build -t rsm .
----
or
[source,bash]
----
$ docker buildx build -t rsm .
----

You can change a few build parameters, by passing them as follows:

[source,bash]
----
# Pass each build argument with a separate --build-arg  - as below
# journal=on       Turns journaling on in the image     - defaults to off
# bsize=<bsize>    The size of a database block in KiB  - defaults to 16
# blocks=<blocks>  The number of blocks in the database - defaults to 16384

$ docker build -t rsm \
      --build-arg journal=on \
      --build-arg bsize=32 \
      --build-arg blocks=32768 .
----
or
[source,bash]
----
$ docker buildx build -t rsm \
      --build-arg journal=on \
      --build-arg bsize=32 \
      --build-arg blocks=32768 .
----

NOTE: If you build the image from source, using the previous example, replace
dlwicksell/rsm with rsm below

To create and run the Docker container with RSM in direct mode:

[source,bash]
----
$ docker run -it --rm --name rsm dlwicksell/rsm
----
or
[source,bash]
----
$ docker run -it --name rsm dlwicksell/rsm
----

To create and run it in detached mode:

[source,bash]
----
$ docker run -itd --name rsm dlwicksell/rsm
----

The RSM Docker container runs with port 80 open. To map an open port on your
host machine to the container port (replace 8080 with an available local port):

[source,bash]
----
$ docker run -itd --name rsm -p 8080:80 dlwicksell/rsm
----

You can change a few runtime parameters, by passing them as follows:

[source,bash]
----
# The first argument [32|2] will set the number of maximum RSM jobs - default 12
# The second argument ['write...'] will run that M code and remove the container

$ docker run -it --rm --name rsm dlwicksell/rsm 32
$ docker run -it --rm --name rsm dlwicksell/rsm 2 'write $system,!'
----

To run RSM in direct mode while the container is in detached mode:

[source,bash]
----
$ docker exec -it rsm rsm
----

To run RSM commands while the container is in detached mode:

[source,bash]
----
$ docker exec -it rsm rsm -i
$ docker exec -it rsm rsm -h
$ docker exec -it rsm rsm -V
$ docker exec -it rsm rsm -x 'write $system,!'
----

To run the Bash shell while the container is in detached mode:

[source,bash]
----
$ docker exec -it rsm bash
----

To start the container while in detached mode:

[source,bash]
----
$ docker start rsm
----

To stop the container while in detached mode:

[source,bash]
----
$ docker stop rsm
----

Consult the Docker https://docs.docker.com/[documentation] to learn about other
ways you can run and manage the RSM Docker image and container.

=== Database Upgrade

Version 1.73.0 of RSM introduced a change from 8 character identifiers to 32
character identifiers. This necessitated a change to the database format, the
routine bytecode format, and the journal format, which required bumping the
database version from 1 to 2, the compiler version from 7 to 8, and the journal
version from 1 to 2.

The RSM runtime image will detect a database in the older format, as well as
compiled bytecode in the older format, and return an appropriate error. If you
would like to move your globals and routines from an old database to a new one,
which works with this version of RSM, please follow these database
link:doc/adoc/upgrade.adoc[upgrade] instructions, or run the
link:bin/upgrade[upgrade] script.

Enjoy!
