Tgdbm Library for Tcl (Version 0.5) This is the documentation of the functions provided by the Gdbm-Tcl-Wrapper. Overview When opening a gdbm-database-file a handle for this database is provided for accessing the file. This handle is used to call the gdbm-commands (see the man-page from gdbm). 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. For information about downloads, ... see the Tgdbm-overview. Commands Let's have a look at a simple walk-through. package require tgdbm set gdbm_handle [gdbm_open -wrcreat -newdb first.gdbm] $gdbm_handle -insert store key1 {Some value to be stored.} set value [$gdbm_handle fetch key1] puts "value: $value" $gdbm_handle close That's nearly all there is. When opening/creating a gdbm-database-file a handle is returned, which is used as a Tcl-command for accessin this database-file. When calling this command you provide the "usual" gdbm-commands (like gdbm_store, ...) but without the gdbm-prefix as a parameter. Now let's use the persistant array feature: package require tgdbm gdbm_open -wrcreat -newdb -array my_array second.gdbm set my_array(1) one ;# this will store 1/one in my_array and directly ;# in file "second.gdbm" set my_array(2) two unset my_array(2) ;# this will delete key '2' from second.gdbm set my_array(1) eins ;# this will update key '1' to 'eins' my_array -replace store 2 zwei set x $my_array(2) ;# x == zwei unset my_array ;# this will close the file second.gdbm ;# this could be done with: ;# my_array close ;# too, which will also unset the array The following commands are available which are directly mapped from aequivalent gdbm-commands (for a detailed discussion of these commands you should also look-up the gdbm-man-page): gdbm_open gdbm_handle close gdbm_handle store gdbm_handle fetch gdbm_handle exists gdbm_handle delete gdbm_handle firstkey and gdbm_handle nextkey gdbm_handle reorganize gdbm_handle sync Furthermore there are some useful additional commands: gdbm_handle count gdbm_handle maxkey gdbm_handle attach_array gdbm_handle detach_array gdbm_handle keys gdbm_open Syntax: gdbm_open [option] file Options: -reader (default) -writer -wrcreat -newdb -nolock -sync -block_size block_size_number -mode file-mode -fatal_func function_name -array array_name -full_cache -no_trailing_null Gdbm-Command: gdbm_open Return-Value: Handle (and Tcl-command) to database-file file or list of currently opened handles. Description: If no option is provided to gdbm_open, it will simply return all currently opened gdbm_handles as a list. The specified file is opened either for reading or writing. Gdbm sets a lock on this file so there is only one writer. With -wrcreat the file is created if it is not existent. -newdb creates file regardless if one exists. With -mode the file mode may be specified. In case of a fatal-error a Tcl-callback-function may be specified with -fatal_func. This Tcl-callback will be called if something inside Tgdbm crashes. The fatal-error-function my_callback_fct must be defined as this: proc my_callback_fct {error_message} { ... } Example: gdbm_open -writer -newdb -nolock -fatal_func my_callback_fct help.gdbm Opens/creates a new gdbm-database-file help.gdbm and doesn't lock the file even though it will write to this file (should really be used with care). Array-Handling (Version 0.5) With -array_name an array named array_name is attached to the gdbm-file. When given an array_name this is also the returned gdbm-handle. gdbm_open -writer -array_name my_array test.gdbm returns my_array. When the name of the given (global) array is already attached to a gdbm-file an error is thrown. If -array_name is given the caching-mechanism can be specified with -full_cache, which means that the whole gdbm-file is stored in the given array directly (be careful, should be used with small files anyway). When -full_cache is not specified, the gdbm-file is read as needed. An array could be attached after opening a file with: gdbm_handle attach_array (then the name of the array is the same as the handle). Warning: Due to the problem that one cannot determine if a variable is global or local to a current procedure (you can use Tcl_FindNamespaceVar but than you cannot compile the tgdbm-library with stubs-enabled, because this function is not in the stub-enabled-library). If you want to use the array attached to a gdbm-file in a procedure you have to make this a global array (else you access a procedure local-array, which is not the same!). Here is an example: gdbm_open -writer -array ini ini.gdbm set ini(font) Times proc setSize {size} { # wrong!!!: set ini(size) $size global ini set ini(size) $size } End-of-string-Handling (Version 0.5) -no_trailing_null Usually all strings either stored or returned have the usual C-style-string-ending (null). In some cases you don't want to store this trailing null or you have gdbm-files which have the keys and values stored without trailing null. In such rare cases you could use argument -no_trailing_null. Tgdbm will not store end-of-string within the gdbm-file. close Syntax: gdbm_handle close Options: none Gdbm-Command: gdbm_close Return-Value: none Description: Close the database-file which is associated with gdbm_handle. Where gdbm_handle is retrieved with a call to gdbm_open store Syntax: gdbm_handle [option] store key value Options: -insert -replace Gdbm-Command: gdbm_store Return-Value: none Description: The given value is stored in the database-file with the given key. If -insert is specified and the provided key is already stored in the database an error is thrown (with error-code GDBM_ILLEGAL_DATA). fetch Syntax: gdbm_handle [option] fetch key Options: none Gdbm-Command: gdbm_fetch Return-Value: The value associated with key in the database. Description: Fetch the key/value-pair from the database. exists Syntax: gdbm_handle exists key Options: none Gdbm-Command: gdbm_exists Return-Value: 0 or 1 Description: If the key does exists, 1 is returned. Otherwise 0. delete Syntax: gdbm_handle delete key Options: none Gdbm-Command: gdbm_delete Return-Value: none Description: Delete the given key from databasefile. If the key does not exist an error is thrown. firstkey, nextkey Syntax: gdbm_handle firstkey gdbm_handle firstkey key Options: none Gdbm-Command: gdbm_firstkey, gdbm_nextkey Return-Value: key Description: These commands are used for iterating through the database-file. You can use it like this: set gdbm [gdbm_open -reader file.gdbm] if {[set key [$gdbm firstkey]] != ""} { puts "key: '$key' value: '[$gdbm fetch $key]'" while {[set key [$gdbm nextkey $key]] != ""} { puts "key: '$key' value: '[$gdbm fetch $key]'" } } $gdbm close reorganize Syntax: gdbm_handle reorganize Options: none Gdbm-Command: gdbm_reorganize Return-Value: none Description: When you have done many deletes on a database-file, the space is not freed until you call reorganize. sync Syntax: gdbm_handle sync Options: none Gdbm-Command: gdbm_sync Return-Value: none Description: Unless you have opened a gdbm-file with option -sync writes are not flushed directly to the disk. With this function you can force a flush to the disk. count (extension of gdbm) Syntax: gdbm_handle count Options: none Gdbm-Command: none Return-Value: Number of total rows in gdbm-file Description: This is aequivalent to a "select count(*) from table" in a relational database. maxkey (extension of gdbm) Syntax: gdbm_handle maxkey Options: none Gdbm-Command: none Return-Value: Number of the maximum primary-key Description: Should be used only when the primary-key consists of integer-numbers (as always when you use an ID as the primary key). In most cases you want to insert a new element and give this element a unique ID. Use [expr [gdbm_handle maxkey] +1] for this purpose. You could also simulate sequences that way. attach_array (extension of gdbm) Syntax: gdbm_handle attach_array Options: none Gdbm-Command: none Return-Value: none Description: To attach an array after opening a file you can use this command. The name of the array is the same as the name of the gdbm_handle. detach_array (extension of gdbm) Syntax: gdbm_handle detach_array Options: none Gdbm-Command: none Return-Value: none Description: If you don't want the transparent storing/retrieving of data through the array you can remove the array from the gdbm_handle with this command. keys (extension of gdbm) Syntax: gdbm_handle keys Options: none Gdbm-Command: none Return-Value: List of ALL keys from gdbm-file. Description: This works like array keys (without the option to add a search-pattern). You should be careful to use this, if your data exceeds the medium-amount of data. Versions and Errors Variablename/Syntax: GDBM_VERSION, GDBM_ERRNO, gdbm_strerror error-code Options: none Gdbm-Command: gdbm_version, gdbm_errno, dbm_strerror Return-Value: gdbm_version returns a version-string gdbm_strerror gives an error-description to an error-number|| Description: You can access the version-string provided in the variable GDBM_VERSION. In case of an error the variable GDBM_ERRNO is filled with the corresponding gdbm-error-number (see gdbm.h for detailer error-numbers). With gdbm_strerror $GDBM_ERRNO an error-description could be retrieved. In case of most errors the error-description is thrown with the error-command. Variablename: gdbm_error Description: To provide a way to access the error-code-defines in gdbm (e.g.: GDBM_FILE_OPEN_ERROR, ..) the array gdbm_error is provided. With these you can check GDBM_ERRNO for specific error-codes without using the integer-values of the gdbm-error-code-defines. The following "defines" (that is array-entries) exists: gdbm_error(GDBM_NO_ERROR) gdbm_error(GDBM_MALLOC_ERROR) gdbm_error(GDBM_BLOCK_SIZE_ERROR) gdbm_error(GDBM_FILE_OPEN_ERROR) gdbm_error(GDBM_FILE_WRITE_ERROR) gdbm_error(GDBM_FILE_SEEK_ERROR) gdbm_error(GDBM_FILE_READ_ERROR) gdbm_error(GDBM_BAD_MAGIC_NUMBER) gdbm_error(GDBM_EMPTY_DATABASE) gdbm_error(GDBM_CANT_BE_READER) gdbm_error(GDBM_CANT_BE_WRITER) gdbm_error(GDBM_READER_CANT_DELETE) gdbm_error(GDBM_READER_CANT_STORE) gdbm_error(GDBM_READER_CANT_REORGANIZE) gdbm_error(GDBM_UNKNOWN_UPDATE) gdbm_error(GDBM_ITEM_NOT_FOUND) gdbm_error(GDBM_REORGANIZE_FAILED) gdbm_error(GDBM_CANNOT_REPLACE) gdbm_error(GDBM_ILLEGAL_DATA) gdbm_error(GDBM_OPT_ALREADY_SET) gdbm_error(GDBM_OPT_ILLEGAL) Example: set gdbm [gdbm_open -wrcreat file.gdbm] if {[catch {$gdbm fetch store key1} result]} { if {$GDBM_ERRNO == $gdbm_error(GDBM_ITEM_NOT_FOUND)} { puts stderr "Item not found." } } Examples Even though the Tgdbm-commands should be easy enough (if you know the gdbm-library) a few examples should help to start immediately. Pay attention to the reduced error-handling. 1. Store a bunch of data (which is stored in the array data) 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 } # ISBN - Booktitles array set books {1-567xyz "XML Pocket Reference" abc "The Bible"} store_array books.gdbm books 2. List the content of a database-file See Description of firstkey, nextkey 3. Using the array-commands Example with array-extension (since version 0.5). package require tgdbm gdbm_open -wrcreat -array books books.gdbm # this one automagically stores the data in books.gdbm # in the form (ISBN title) array set books { 1-567xyz "XML Pocket Reference" abc "The Bible" } # now closing the file unset books # this could also be done with # books close 4. gdbm-arrays and namespaces This example shows how to use "global" gdbm-arrays inside namespaces: package require tgdbm namespace eval gdbm::ar { variable myArray } proc gdbm::ar::init {gdbm_file} { variable myArray gdbm_open -wrcreat -array myArray $gdbm_file } proc gdbm::ar::close {} { variable myArray myArray close } proc gdbm::ar::printData {} { variable myArray parray myArray } proc gdbm::ar::get {key} { variable myArray return $myArray($key) } proc gdbm::ar::fillData {args} { variable myArray array set myArray $args } gdbm::ar::init "airports.gdbm" gdbm::ar::fillData ADD "Addis Ababa" MUC "Munich" ZAG "Zagreb" gdbm::ar::printData gdbm::ar::close This example can be immediately used for implementing something similar to ini-files (where configurable user-data like window-positions or font-selections are stored).