1. mdh
    1. Usage
    2. Programming interface
    3. Caveats
    4. Author
    5. Repository
    6. Version history
    7. License


An interface to a Multidimensional Hierarchical database. This egg includes code from the open source MUMPS system available at http://www.cs.uni.edu/~okane/. It provides a simple and efficient interface to a persistent file-based database of arbitrary size. The database can also be seen as a tree and can be traversed and inspected.

See also the MDH programming guide for a more detailed look. This egg just provides a Scheme layer on top of the MDH C++ API.


(import mdh)

Programming interface

Access to the database is done through "globals", named entities stored in the database, with an optional list of indexes specifiying multi-dimensional arrays. Up to 10 dimensions can be given.

[procedure] (global GLOBAL)

Allocates a an object representing a global persistent variable. The object should be freed using global-free when it is no longer required. There may be multiple references to the same global variable at the same time in existance. GLOBAL may be a string, symbol or number and will be converted to a string. The result of global is a wrapper procedure, invoking it with a (possibly empty) set of indices creates a reference to a specific location than can be further accessed and queried.

(define g (global "foo"))

(global-set! (g) 123)
(global-ref (g)) => "123"

Indices for as many as 10 dimensions may be given:

(global-set! (g 1 2) "xxx")
(global-ref (g 1 2)) => "xxx"
[procedure] (global-object X)

Returns the object contained in the global reference or wrapper procedure X or #f, if X is not related to a global. If X is already a global object, it is returned unchanged.

[procedure] (global? X)

Returns true if X is a global object record structure instance.

[procedure] (global-reference? X)

Returns true if X is a global object reference for a given location in the database.

[procedure] (global-name G)

Returns the name of the global object G.

[procedure] (global-reference-name GR)

Returns the name of the global addressed by the global reference GR.

[procedure] (global-set! GR VALUE)

Sets the value of the element addressed by the global reference GR to VALUE. VALUE will be converted to a string before it is stored. INDEX may be a string, symbol or number and will also be converted to string. If the element doesn't exist yet for G, then it is created. If GR refers to a global, then this is equivalent to global-set! (GR) VALUE).

[procedure] (global-ref GR)

Returns the value of the element addressed by the global reference GR. If no element exists at that position, then the empty string is returned.

[procedure] (global-count GR)

Returns the number of descendants of the node specified by the global reference.

[procedure] (global-free G)

Releases the storage required for the global object or wrapper procedure G. After using this procedure, referencing the database through G or any global reference derived from it will signal an error.

[procedure] (global-kill GR)

Removes the given element and all its descendants from the database.

[procedure] (global-next GR)

Returns the next index for the last item addressed by the given reference. Use the empty string as the final index if you want to obtain the first valid index holding data. If no further index is defined, returns the empty string:

(define g (global "foo"))
(global-set! (g 1) "a")
(global-set! (g 2) "b")
(global-next (g ""))      => "1"
(global-next (g "1"))     => "w"
(global-next (g "2"))     => ""
[procedure] (global-previous GR)

Similar to global-next but retrieves the previous index.

[procedure] (global-data GR)

Returns a symbol or #f identifying the type of node addressed by the reference GR.

[procedure] (global-merge GR1 GR2)

Copies the element and all its descendants given by the reference GR2 to the position identified by the reference GR1.

[procedure] (^ NAME INDEX ...)

Creates a temporary global reference for NAME and returns its value using global-ref. NAME may be a global object, a global wrapper procedure or a name that is converted to a string.

[setter] (set! (^ NAME INDEX ...) VALUE)

Equivalent to (global-set! (global NAME) VALUE INDEX ...) but takes care to free the wrapper object of the global reference properly after assigning the value. NAME may be a global object or a name that is converted to a string.

[procedure] (^data NAME INDEX ...)
[procedure] (^next NAME INDEX ...)
[procedure] (^previous NAME INDEX ...)
[procedure] (^count NAME INDEX ...)
[procedure] (^kill NAME INDEX ...)

These are all convenience procedures that perform the named operation with an existing global object or a temporarily allocated global reference if NAME is not a global object.

[procedure] (flush-globals)

Flushes any unwritten operations to the database and commits all pending operations.

[procedure] (close-globals)

Performs a flush-globals and closes all access to the database. This procedure is called automatically on normal or abnormal exit of the process. Also see "Caveats", below.


It is crucial to properly flush or close the database on exit or the file holding the persistent data may be incomplete or corrupted. For normal exit this is taken care of by setting [implicit-]exit-handler and handling the case when the process terminates with an error. When signals cause a process abort then code wanting to properly close the database must invoke flush-globals or close-globals explicitly.

Stored values and index strings can be at most 10000 bytes long.

More than 10 dimensions are currently not supported.


The original MDH database is maintained by Kevin O'Kane http://www.cs.uni.edu/~okane/, see also the AUTHORS file in the egg distribution.

This egg was written and is maintained by Felix Winkelmann, using a subset of the original MDH source code. Many thanks to Luke K for the inspiration to create this egg and for providing helpful comments and suggestions.


This egg is hosted on the CHICKEN Subversion repository:


If you want to check out the source code repository of this egg and you are not familiar with Subversion, see this page.

Version history

Initial release


GNU General Public License