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.

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:

Furthermore there are some useful additional commands:

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).

Captcha

Nach monatelangen Belästigungen habe ich jetzt hoffentlich erstmal Ruhe vor den stumpfsinnigsten Spammern dieser Welt. Endlich habe ich ein Captcha für das Verfassen von Kommentaren eingebaut. Seit Monaten werden die Kommentare von Spammern geflutet. Teilweise bis zu 100 Kommentare am Tag über alle Varianten von Medikamenten, Glücksspiel und was noch so alles unheimlich uninteressant ist.

Dabei reichte die Spannbreite der Einträge von halbwegs netten Floskeln (neben den Links) wie “your site is cool” bis zu völlig dröger Einfaltslosigkeit “Lok here” (und Rechtschreibschwäche :-) )

Ich frage mich allerdings ob die Spambots nicht von ihren Erzeugern irgendwann auf ihre Wirkung überprüft werden. Seit Monaten müssen die Kommentare auf dieser Site manuell freigeschaltet werden. D.h. keiner der Spam-Einträge hat jemals das Licht der Internetwelt erblickt. Komischerweise hat das keinen Spambot davon abgehalten munter weiter Links zu verteilen wie ein Hustenkranker Viren im vollbesetzen Stadtbus.
“Hey, Ihr Spammer! Hand vor den Mund!”
Weiterlesen

Die anonymisierte Gebotsform

Gestern stand ich so schön bei IKEA in der Schlange. Da fiel mir das Schild mit dem Text “Bitte zieh eine Aufrufmarke” auf.

Ich bin ganz verwundert. Normalerweise werde ich doch von Schildern gar nicht angesprochen. Da steht doch landläufig immer so etwas wie “Bitte Aufrufmarke ziehen!”. Eine gelungene Konstruktion in der sich auch gleich geschickt um die Ansprache (“du” oder “sie”) herumgewunden wird.

Für dieses Konstrukt gibt es bestimmt auch einen hochtrabenden grammatikalischen Begriff. Der ist mir nur nicht gerade entfallen, ich kenne ihn grundsätzlich nicht (PISA sei dank). Ich nenne das Konstrukt einfach mal “anonymisiertes Gebot”.
Weiterlesen

Auge im Herz

“Man sieht nur mit dem Herzen gut. Das Wesentliche ist für die Augen unsichtbar.”
Antoine de Saint-Exupéry

Metaphorische Beschreibungen sind scheinbar für Kinder nicht so ganz einfach zu verstehen. D.h. nein, eigentlich verstehen sie diese Umschreibungen sehr gut, nur nicht in ihrem versteckten Sinne, sondern direkt wie die Worte daher kommen.

Die große Weisheit von Saint-Exupéry entfaltet daher bei Fabian und Felix ihren “eigentlichen” Sinn.

Beim Frühstück kommt es auf einigen Umwegen zu folgendem Gespräch:
Weiterlesen

Das ist doch klar

Nachdem gestern einer Bekannten das Auto aufgebrochen wurde, kommt Annabelle nicht umhin einen Schwank aus ihrer Jugend zu erzählen.

Annabelle
Damals hatte ich mir von meinem ersten verdienten Geld ein teures Autoradio für meinen Benny gekauft.
(Vergeben eigentlich Männer auch Namen für ihre Autos? – Anmerkung des Verfassers)
Und kaum hatte ich es eingebaut, wurde am nächsten Tag die Autoscheibe aufgeschnitten und das Autoradio geklaut.
Die haben sogar meine selbst aufgenommenen Kassetten geklaut. Ich weiß gar nicht, was die Gauner damit anfangen wollten.
Fabian
Mama, ich weiß, was die damit anfangen wollten!
Annabelle
(etwas verwirrt) Ah ja?
Fabian
Die wollten Musik hören! (entrüstet) Das ist doch klar!

Aye! Aye! Kapitän!

Felix ist heute beim Frühstück ganz verzweifelt. Ich merke es allerdings viel zu spät (schließlich muss ich ja erst mal eine Weile in mich hineinlachen).

Felix
Wie heißt denn der Kapitän?
Annbelle
(schaut etwas verduzt) Welcher Kapitän?
Felix
Na DER Kapitän. Wie heißt der denn? Mit Vornamen?

Na gut, da keiner Bescheid weiß, geht die Frage im allgemeinen Frühstücksgetümmel etwas unter.

Fabian
(er wollte schon länger etwas sagen, kam aber nicht zu Wort – eigentlich nur unsere Kinder zu Wort kommen) Mammmaaaa, UUUUUUND. Weil nääämlich …

Stöhn! So fangen die Sätze fast immer an. Vor allem … wenn dann nichts Interessantes mehr folgt.
Weiterlesen

Steiger Production oder einfach nur unverschämt

Manchmal frage ich mich ja wirklich wie dreist man sein kann. Offensichtlich jedoch gibt es für alles Grenzen; nur nicht für das Universum und die Dreistigkeit (die menschliche Dummheit sei diesmal nicht erwähnt).Wir hatten uns für den 24.4 Karten für die Vorstellung von Hans Klok in Hanau besorgt. Veranstalter hierfür ist die Steiger Production GmbH.

Unerwähnt lasse ich auch (neben der Dummheit), dass der 24.4 schon ein Nachholtermin war, da die vorherige Veranstaltung ausgefallen war. Offensichtlich war man wohl nicht fähig die Bühne rechtzeitig aufzubauen bzw. der Bühnenaufbau verzögerte sich durch einen Stromausfall.

Nun gut, die Veranstaltung fällt erneut aus. Man ist ja schon daran gewöhnt. Gründe werden nicht mitgeteilt. Wozu auch?
Weiterlesen

Betten fegen

Deutsche Sprache, schwere Sprache. Das merke ich immer wieder, wenn sich unsere Kids neue Möglichkeiten zur Sprachumbiegung ausdenken. Es liegt natürlich einmal in der Natur der Dinge, dass den Beiden nur ein etwas eingeschränkterer Wortschatz zur Verfügung steht. Glücklicherweise sind sie so hemmungslos mit den Wörtern, die sie zur Verfügung haben alles auszudrücken was sie möchten. Das Schöne daran ist, dass man sie im Kontext gut verstehen kann.

Außerhalb des Kontext sorgt die Frage: “Hast du dein Bett schon gefegt?”, sicherlich für eine Bewegung der Augenbrauen nach oben.

Aber so ist es. Fabian und Felix fegen morgens ihre Betten. Soll heißen: Sie machen ihre Betten (allerdings gibt das nicht ganz den Umfang der Tätigkeiten her).
Weiterlesen

Lkw Amok

LKW-Amok … oder warum Handys für Gewaltfreiheit sorgen.

Da stand ich heute wie so oft im Stau nach Hause und quäle mich gelangweilt durch die vollen Frankfurter Straßen. An einer Ecke will ich die Spur nach rechts wechseln. Da steht ein großer Kipper, o.k. er macht Anstalten als wolle er mich vorlassen. Ich winke zum Dank und will losfahren, da höre ich noch

RÖÖÖÖHHHHR HUUUUUPPP

Das Tonnengefährt macht fast einen Sprung. Erschreckt bremse ich … schließlich sitze ich ungefähr 2 Meter tiefer als der Fahrer dieses Monstrums. Ich fahre noch so ein kleines Stück neben ihm her bis sich die Spur verengt bzw. der Kipper versucht noch mehr von der Straße einzunehmen als er ja sowieso schon tut. Ich sehe jedenfalls direkt auf meiner Beifahrerseite sehr deutlich das Profil der Reifen (SEHR deutlich). Ich weiß ja nicht genau was der Kerl am Steuer will, aber er schreit irgendwas aus dem offenen Fenster (richtig verstehen kann ich nur “Arschloch” … wen meint er nur?). Dann gibt er wieder ordentlich Gas. Das Ding macht einen echt krassen Sound.
Weiterlesen

Auswirkungen der Gehaltsunterschiede von Männern und Frauen

Gute-Nacht-Zeit. Unser komplexes Regelwerk über wer (Annabelle oder ich) in welcher Reihenfolge wem (Fabian oder Felix) abends vorliest und Gute-Nacht sagt, werde ich demnächst als eigene Website aufbauen (vom Umfang wird das so ein Projekt wie Wikipedia). Daher verzichte ich jetzt auf die Details. Ich sitze also bei Fabian am Bett und wir reflektieren den Tag.

ich
“Was fandest du denn heute besonders schön?”

Fabian überlegt … au weia … er überlegt lange

Fabian
“Ich fand schön, dass du heute gearbeitet hast!”

Ähhhh. Jetzt bin ich etwas baff. Vielleicht sollte ich ja am Wochenende auch lieber das Haus verlassen, weil dann meine Kinder glücklicher sind?

ich
(versucht gefasst zu wirken) “Ähm, warum fandest du das schön?”
Fabian
“Ja, weeeiiiilll (er betont das ‘weil’ immer sehr witzig), wenn die Mama arbeiten würde, dann würde die nicht soviel Geld verdienen. Uuuuuund (er betont auch das ‘und’ am Satzanfang immer witzig) wenn wir dann noch viel Eis essen wollen, dann reicht das nicht. Und dann müsste die Mama arbeiten und du müsstest arbeiten. Damit wir auch genug Geld zum Eis essen haben.”
Fabian
“Und deswegen bin ich froh, dass nur du arbeiten musst, sonst wären wir ja ganz alleine.”

Puh, mir fällt ein Stein vom Herzen.

Da sag mir noch einer Kinder wären nicht politisch interessiert (Meldung der Tagesschau).

Sicherlich wird Fabian für mehr Gleichstellung sorgen, wenn er erst mal groß ist.

Fabian
“Und du bist dann ja immer noch Abends da und auch Nachts. Deswegen bist du auch der Abendmann oder der Nachtmann!”

Na, immerhin bin ich keine Nachtmütze.