Tgdbm is an easy-to-use Tcl-wrapper to the GNU-dbm-library (gdbm).
Overview
Tgdbm provides an easy to understand interface to the
GNU-dbm-library (gdbm).
Gdbm uses extendible hashing and stores key/value pairs, where each key must be unique (Gdbm can be downloaded at the GNU-Website, there
is also my windows-port of gdbm).
Though gdbm provides compatibility for ndbm and dbm only the gdbm-commands are supported in Tgdbm.
Furthermore you can use Tgdbm for transparently accessing and storing tcl-arrays (persistant arrays). An array is attached to the gdbm-file as a handle. With this you can set an array-entry which is stored or updated transparently in the corresponding gdbm-file.
Tgdbm is meant to be used in Tcl-Applications which has to store some small/medium amount of data. In many cases there is not enough data to be stored, so that a „real“ database is justified.
But though there is only a small amount of data, you often have to use an efficient way to store them (not just write them in a plain text-file).
Because Tgdbm is provided as a loadable Tcl-Module, it can be easily
integrated into any Tcl-Application.
Download
You can download Tgdbm with the following links:
History
14. April 2005
Released Version 0.5:
Yes it’s still 0.5 but has some improvements. All those fixes were sent to me from Thomas Maeder (thanks a lot). Have a look at the file CHANGES.txt inside the distribution to see what happened.
9. Jan. 2004
Released Version 0.5:
Persistant arrays were added to Tgdbm. Because of a nearly equivalent concept for tcl-arrays (which have unique keys) and gdbm-key-value pairs which also have unique keys, these are now combined to have a transparent handling of persistant arrays.
You can simply attach an array-name to a gdbm-file. Afterwards every operation on the array (read/write/unset) is traced and the key/values are automatically fetched/stored or updated/deleted in/from the gdbm-file.
For further information see README.txt.
Cleanup and restructuring of the C-Code, added sync
-command …
1. Feb. 2000
Released Version 0.4
A quick and simple example
Even though the Tgdbm-commands should be easy enough (if you know the gdbm-library) a few examples should help to start immediately.
package require tgdbm proc store_array {file data} { upvar $data dat # create file if it doesn't exist set gdbm [gdbm_open -wrcreat $file] foreach entry [array names dat] { $gdbm -replace store $entry $dat($entry) } $gdbm close }
You can also try the file tests/demo.tcl
which implements a simple gdbm-file-viewer. This viewer stores it’s configuration-options (like colors or window-positions) in option.gdbm
(like an INI-file).
Gdbm-viewer needs the tablelist
-widget from Dr. Casa Nemethi (which can be obtained from: http://www.nemethi.de).
Is Tgdbm + gdbm thread safe? I’d like to use it under AOLServer, and Berkeley DB’s Tcl API is *not* thread safe, so this would be a nice alternative…
-john
Hi John,
no, gdbm ist not thread safe due to static variables which e.g. holds the error-code (see also http://webauth.stanford.edu/manual/developer/thread_safety.html)
But thanks for looking for Tgdbm.
Opening a gdbm file with tgdbm and attaching it to an array works incorrectly in case the array is empty at this point.
array size returns 0 while array exists also returns 0.
The following is a workaround for this inconsistency;
#
# Note: fix for TGDBM problem: an empty array is NOT an array ?
#
if { ([array size $arrayVarName] == 0) && ([array exists $arrayVarName] == 0) } {
set ${arrayVarName}(DUMMY) dummyVal
unset ${arrayVarName}(DUMMY)
}
After this, array exists returns 1 and array size still returns 0.
Should be possible to fix in an upcoming release?
Thanks and regards Hermann
Thanks, Hermann! I will have a look at it!
Dear Sir,
I try to compile this package on FreeBSD:
FreeBSD miniBeastie 8.0-RELEASE-p2 FreeBSD 8.0-RELEASE-p2 #0: Wed Mar 31 22:02:56 EDT 2010 root@miniBeastie:/usr/obj/usr/src/sys/MINIBEASTIE3 i386
tgdbm: tgdbm0.5a.zip
gdbm: gdbm-1.8.3_3
I modified the Makefile to reflect the FreeBSD architecture: add /local to every path:
INCLUDES = -I/usr/local/include -I/usr/local/include/tcl8.4
LIBS = -L. -L/usr/local/lib -lgdbm -llibtclstub84
But I got the following error:
gcc -shared -o tgdbm.so -L. -L/usr/local/lib -lgdbm -llibtclstub84
/usr/bin/ld: cannot find -llibtclstub84
*** Error code 1
I got the tcl8.4: tcl-8.4.19_3,1
pkg_info -L tcl-8.4.19_3,1:/usr/local/lib/libtcl84.a
/usr/local/lib/libtcl84.so
/usr/local/lib/libtcl84.so.1
/usr/local/lib/libtclstub84.a
Could you help me ?
Regards,
Yves
Hi Yves,
thanks for your interest. This thing is rather old, but nevertheless it works 🙂
The actual version of Tcl is 8.5. Maybe it’s enough to adapt the version-nummers?
Could you try it? I didn’t have a FreeBSD-system at hand.
Thanks and best regards
Stefan
Interesting article and one which should be more widely known about in my view. Your level of detail is good and the clarity of writing is excellent. I have bookmarked it for you so that others will be able to see what you have to say.
Dear Sir,
I finally have it to compile in my FreeBSD, I change the include and lib path
INCLUDES = -I/usr/local/include -I/usr/local/include/tcl8.4
# append the needed library-paths: -L/??
LIBS = -L. -L/usr/lib -L/usr/local/lib -lgdbm -ltclstub84
I got hte following warning when running make:
gcc -Wall -DUSE_TCL_STUBS -I/usr/local/include -I/usr/local/include/tcl8.4 -o tgdbm.o -c tgdbm.c
tgdbm.c: In function ‚copyResultNull‘:
tgdbm.c:277: warning: cast from pointer to integer of different size
tgdbm.c:283: warning: cast from pointer to integer of different size
tgdbm.c: At top level:
tgdbm.c:44: warning: ‚rcsid‘ defined but not used
gcc -shared -o tgdbm.so -L. -L/usr/lib -L/usr/local/lib -lgdbm -ltclstub84
And I try to load the lib (to test it)
[root@miniBeastie /opt1/temp/tclgdbm]# /usr/local/bin/tclsh8.4
% load ./tgdbm.so
couldn’t find procedure Tgdbm_Init
% pkg_mkIndex -verbose — . *.so
warning: error while loading tgdbm.so: couldn’t find procedure Tgdbm_Init
%
I try with tcl8.5 and got the same result.
Thank in advance for your help. I will be able to test it on FreeBSD, if you need a FreeBSD testbed, I am ready to help you.
FreeBSD:
FreeBSD miniBeastie 8.0-RELEASE-p2 FreeBSD 8.0-RELEASE-p2 #0: Wed Mar 31 22:02:56 EDT 2010 root@miniBeastie:/usr/obj/usr/src/sys/MINIBEASTIE3 i386
tcl: 8.4.19 and 8.5.8
contact me at: yvesguerin (at) yahoo (point) ca
Regards,
Yves
Hi Yves,
thanks for trying it. I’m not sure why the loader doesn’t find „Tgdbm_Init“ because it’s there in tgdbm.c
Further discussion in email …
Thanks for the fix. I’ve been having all sorts of problems trying to figure this out. I’ll try to follow suit, I’m such a techie noob 🙂