Perl TM Tutorial: TMDBMS 4 The People (Part IX)

(Followup to part VIII)

As long you deal with a small number of separate topic maps, then you can spend a variable for each of the topic map objects. Since Perl TM topic map instances are just data structures, you can also arrange several maps in lists or hashes. Why not.

You might reach a state, though, where you want to organize more maps and maybe attach information to them, such as authorships, date of creation and so forth. You may even want to associate individual topic maps with each other.

What would be cool is to do this with yet another topic map, one into which you put your pool of maps whereby each map is represented by a single topic. That topic would be of type TOPICMAP, predefined in your system. Let's call this top-level map the root map.

To add one single map to the root map you would need to name a topic and the topic map this topic should reify. Reification of maps is not novel, except that here the topic is outside the map it reifies. But so what.

Root of All Goodness

Let us assume that we have such a root map:

my $root = new TM;

To allow other maps to be hooked into it we have to add MapSphere functionality by adding a corresponding trait:

use Class::Trait;
Class::Trait->apply ($root, 'TM::MapSphere');

You have seen traits already.

If we now want to hook another map into $root under a topic xyz, then this can be done with the method mount:

my $child = new TM;                # yet another map
$root->mount ('/xyz/' => $child);  # mount it

After that the topic xyz will not only exist in $root, it will also have an internal connection to the map it represents. That connection allows you to easily access the map afterwards:

my $lost_child = $root->is_mounted ('/xyz/');

Should you harbour the wish to get rid of the topic, and - with it the map - then you use umount:

$root->umount ('/xyz/');

UNIX Heritage

The syntax with the slashes may strike familiar and in fact it is borrowed from UNIX file systems. Also these have a root under which subdirectories are linked in. The beauty of this scheme is that in a UNIX filesystem one can hook in further devices into one global tree, regardless of the technology. With this mounting of devices you can so add USB sticks, floppy disks, ROM, remote file systems, etc.

With Perl TM you mount topic maps. And yes, this works also deeper than one level:

my $grandchild = new TM...;  # and yet another
$root->mount ('/xyz/abc/' => $grandchild);

The above will first find the root map, will then find the topic xyz in there, will follow to the map connected to it. Then it will then try to create a topic abc in that map and will connected it to $grandchild.

Should xyz not exist, or if it is not a map, then this will all fail horribly. As it should.

Multiculti

All maps we have created above are in-memory maps. These are of course empty at creation time. And once the map object goes out of scope or the program terminates the whole beautiful structure disappears.

If that is not your idea of a database and you want persistency, well then choose persistent map implementations instead. So let's recreate the root differently:

use TM::Materialized::MLDBM;
my $root = new TM::Materialized::MLDBM (file => '/tmp/map.dbm');

That implementation can load content from a DBM file, and if you ask nicely also writes it back:

$root->sync_in;  # this you say at the 'start'
...
$root->sync_out; # this at the 'end'

Notably, the sync_in and sync_out only affect the root map. So only that is stored into the DBM file. Still, the synchronisation events will propagate downwards to the children, so these will synchronize as well, each with their own persistency methods. You should raise an eyebrow now.

Update: The down-synchronisation does not happen by itself. You will have to add the trait TM::Synchronizable::MapSphere to make that happen.

If that whole synchronisation business is too cumbersome for you, then store your maps in a TM::Materialized::MLDBM2 form. That does the in-synchronisation when the object is created and the out-synchronisation when it goes out of scope.

TMDBMS in your backyard

And you could even go further and implement TMIP between a client and a server version of TM::MapSphere. That gives you remote access to the whole tree of maps. Like ODBC, but RESTful. Raise another eyebrow, if you wish.

If you put a TMQL processor on top of every map, then you are close to a decent TMDBMS. Raise your third brow now.


Work supported by the Austrian Research Centers.

Posted In