3. Connecting to MUMPS
- John Willis
The first thing you need to do in order to begin using either of the two main CFMumps APIs is to open a connection to the MUMPS database. Unlike the MUMPS language, where your connection to the database is implicit and automatic, the CFML and CFScript environments require you to initiate and terminate this connection explicitly. Although this requires a couple of extra steps, it does not significantly expand the number of lines of code your application will use, as you can open the database, perform as many database operations as needed, and then close the database. You do not have to open and close the database for each operation individually.
This connection model introduces some interesting flexibility: it allows us to implement the CFMumps connectors either directly, via an in-process binding, or indirectly, over a TCP socket or REST interface, the latter two options of which are slower, but allows your application and your MUMPS database to be located on separate servers.
Let's look at the connection model for each of the two major CFMumps APIs.
Connecting with the Basic API
With the basic API, you access the MUMPS database with familiar methods, including but not limited to get, set, kill, data, and order. These operations should be familiar to you as a MUMPS programmer. However, in order to begin using these API methods, you need a connection to the MUMPS database.
In this example, you will create an instance of lib.cfmumps.Mumps, open the database, fetch the value of ^people("Smith,Joe","birthday") into a CF variable, write it to the page, and close the database.
var db = new lib.cfmumps.Mumps(); db.open(); var joeBirthday = db.get("people", ["Smith,Joe","birthday"]); writeOutput("Joe's birthday is " & joeBirthday); db.close();
<cfset db = new lib.cfmumps.Mumps()> <cfset db.open()> <cfset var joeBirthday = db.get("people", ["Smith,Joe", "birthday"])> <cfoutput>#joeBirthday#</cfoutput> <cfset db.close()>
You should not attempt to either re-open an already opened database, nor close one that's already closed. As a safeguard against this, the isOpen() method will return true if the database has already been opened, or false otherwise.
Connecting with the Globals API
The Globals API lets you project MUMPS globals to native CF structures, and vice versa, as well as providing a few other operations like value, defined, and delete. Unlike the Basic API, the Globals API does not expose an implicit open() method. Instead, the global or global sub-tree is specified (along with options controlling atomicity) when instantiating the API. See Globals API Instantiation for more information on this mechanism.
Atomicity
Atomicity can provide a measure of protection against data inconsistency when two processes attempt to modify the same data concurrently: a commonplace event in multi-user web apps such as those you can develop in CFMumps. Under the hood, CFMumps' atomicity controls are powered by MUMPS incremental locks. These locks provide fine-grained access control to any global or global sub-tree.
See Appendix A: Concurrency Protection for more information.
In this example, you will use the Globals API to open a reference to ^DD(200) and fetch all of its data and child subscripts into the CFML variable newPersonFile:
var global = new lib.cfmumps.Global("DD", [200]); var newPersonFile = global.getObject(); global.close();
<cfset var global = new lib.cfmumps.Global("DD", [200])> <cfset var newPersonFile = global.getObject()> <cfset global.close()>
As you can see in the above code snippets, the global variable has been initialized to an instance of the Globals API component, and opened with a reference to ^DD(200). The getObject() API was then used to populate the newPersonFile variable with a structure whose layout and members contain all the data from ^DD(200) and its descendants. You can now work with this information in-memory, without incurring the performance penalties of further accesses to fixed storage.
Please note that even with atomicity enabled in the Globals API, other applications may still read or change on-disk information after you've read it into an in-memory structure, resulting in a potential race condition. It is vital for data integrity to carefully architect your CFMumps applications in order to avoid race conditions and manage concurrent access.