ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/TDB_FileX/TDB_FileX.pm
Revision: 1.13
Committed: Fri May 2 22:37:19 2025 UTC (16 months, 3 weeks ago) by root
Branch: MAIN
Changes since 1.12: +6 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 package TDB_FileX;
2    
3     use common::sense;
4    
5     use Exporter ();
6     use XSLoader ();
7    
8     our @ISA = qw(Exporter);
9    
10     # Items to export into callers namespace by default. Note: do not export
11     # names by default without a very good reason. Use EXPORT_OK instead.
12     # Do not simply export all your public functions/methods/constants.
13    
14     our %EXPORT_TAGS = (
15     flags => [qw(
16     ALLOW_NESTING
17     BIGENDIAN
18     CLEAR_IF_FIRST
19     CONVERT
20     DEFAULT
21     DISALLOW_NESTING
22     INCOMPATIBLE_HASH
23     INTERNAL
24     MUTEX_LOCKING
25     NOLOCK
26     NOMMAP
27     NOSYNC
28     SEQNUM
29     VOLATILE
30     )],
31     insert => [qw(
32     INSERT
33     MODIFY
34     REPLACE
35     )],
36     error => [qw(
37     SUCCESS
38     ERR_CORRUPT
39     ERR_EXISTS
40     ERR_IO
41     ERR_LOCK
42     ERR_LOCK_TIMEOUT
43     ERR_NOEXIST
44     ERR_NOLOCK
45     ERR_OOM
46     ERR_EINVAL
47     ERR_RDONLY
48     )],
49     debug => [qw(
50     DEBUG_FATAL
51     DEBUG_ERROR
52     DEBUG_WARNING
53     DEBUG_TRACE}
54     )],
55     );
56    
57     our @EXPORT_OK;
58    
59     Exporter::export_ok_tags qw(flags insert error debug);
60    
61     $EXPORT_TAGS{all} = \@EXPORT_OK;
62    
63     our $VERSION = '0.97';
64    
65     XSLoader::load __PACKAGE__, $VERSION;
66    
67     1;
68     __END__
69    
70     =head1 NAME
71    
72     TDB_FileX - Perl access to the trivial database library
73    
74     =head1 SYNOPSIS
75    
76     use TDB_FileX;
77    
78     # tie interface
79     tie %hash, TDB_FileX => $filename,
80     hash_size => 8000,
81     mutex => 1,
82     ;
83     $hash{key} = 'value';
84     while (my ($k, $v) = each %hash) { print "$k -> $v\n" }
85    
86     # OO interface
87     my $tdb = TDB_FileX->open ($filename, flags => TDB_FileX::CLEAR_IF_FIRST)
88     or die $!;
89    
90     $tdb->store (key => 'value') or die $tdb->errorstr;
91     $tdb->traverse (sub { print "$_[0] -> $_[1]\n" });
92    
93     =head1 DESCRIPTION
94    
95     TDB is a simple database similar to GDBM, but allows multiple simultaneous
96     writers. It's main drawback is the need to manually configure a hash table
97     size in advance - see the C<hash_size> option for C<open>.
98    
99     TDB_FileX provides a simple C<tie> interface, similar to DB_File and
100 root 1.3 friends; and an object-oriented interface, which provides access to most
101     of the functions in the TDB library.
102    
103     =head1 ERROR HANDLKING
104    
105     The TDB C API is not well designed - among other things, error handling is
106     a bit erratic. Many functions that normally should just work are marked
107     with a [CROAK] - these will throw an exception on error, the exception
108     string being the error message. C<$!> is set to the numerical error value
109     in that case (and will stringify into the wrong OS-error string, so don't
110     do that!).
111    
112     This is so that you can concentrate on the important parts, while there
113     are still no silent unexpected errors.
114    
115     The other functions will not generally croak - check their description for
116     details on how errors are handled.
117 root 1.1
118     =head2 FUNCTIONS
119    
120     =over 4
121    
122 root 1.3 =item $tdb = tie %hash, TDB_FileX => $path[ , key => value...]
123    
124     =item $tdb = TDB_FileX->open ($path[, key => value...])
125    
126     TDB_FileX constructor (same as C<TIE>). Opens $path and returns a
127     TDB_FileX object. The same arguments may be passed to the C<tie>
128     function. On error, C<undef> is returned.
129 root 1.1
130 root 1.10 You should consider specifying at least C<log_cb> and C<hash_size> (and
131     possibly C<mutex>), everything else has sensible defaults.
132    
133 root 1.3 To open a tdb file that is created and used by another application
134 root 1.6 (maximising compatibility):
135 root 1.3
136     my $tdb = TDB_FileX->open ($path, log_cb => sub { warn $_[1] })
137     or die "$path: failed to open\n";
138    
139 root 1.10 To successfully open another database, you might have to duplicate some of
140     the settings, e.g. whether mutex locking is used or the hash function. The
141     C<log_cb> output usually will tell you what's wrong.
142    
143 root 1.3 To open a tdb file with good performance for many thousands of large keys,
144 root 1.10 maybe not compatible to other programs:
145 root 1.3
146     my $tdb = TDB_FileX->open ($path,
147     hash_size => 10000,
148     hash => "xxh3",
149     mutex => 1,
150 root 1.6 nocow => 1,
151 root 1.3 log_cb => sub { warn $_[1] },
152     ) or die "$path: failed to open\n";
153 root 1.1
154 root 1.10 The following key-value pairs are understood:
155 root 1.1
156     =over
157    
158     =item tdb_flags => $flags (default: C<TDB_FileX::DEFAULT>)
159    
160     A set of flags that influence the behaviour and format of the database.
161    
162 root 1.11 =over
163    
164     =item C<DEFAULT>
165    
166     Same as C<0> - no flags.
167    
168     =item C<CLEAR_IF_FIRST>
169    
170     If this is the first open, wipe the db.
171    
172     =item C<INTERNAL>
173    
174     In-memory database only, path will be ignored.
175    
176     =item C<NOLOCK>
177    
178     Don't do any locking.
179    
180     =item C<NOMMAP>
181    
182     Don't use mmap.
183    
184     =item C<NOSYNC>
185    
186     Don't use synchronous transactions.
187 root 1.1
188 root 1.11 =item C<SEQNUM>
189    
190     Maintain a sequence number.
191    
192     =item C<VOLATILE>
193    
194 root 1.13 Activate the per-hashchain freelist, default 5. (Same as calling
195     C<set_max_dead> with C<5> instead of the default C<0>).
196 root 1.11
197     =item C<ALLOW_NESTING>
198    
199     Allow transactions to nest.
200    
201     =item C<DISALLOW_NESTING>
202    
203     Disallow transactions to nest.
204    
205     =item C<INCOMPATIBLE_HASH>
206    
207     Better default hash functioa, but can't be opened by tdb < 1.2.6.
208    
209     =item C<MUTEX_LOCKING>
210    
211     Optimized locking using robust mutexes if supported,
212    
213     =back
214 root 1.10
215 root 1.1 =item open_flags => $flags (default: C<Fcntl::O_RDWR | Fcntl::O_CREAT>)
216    
217     Standard open flags, as used in C<sysopen>.
218    
219     =item mode => $mode (default: C<0666>)
220    
221     Standard file open mode, as use din C<sysopen>. Only used when creating
222     the database file.
223    
224     =item hash_size => $int (default: internal to libtdb, but normally C<131>)
225    
226     The size of the internal hash table - only used when creating the
227     database. The default is usually very low and only good for a few thousand
228     keys. As a rule of thumb, it should be at least one percent of the number
229     of keys you plan to store, e.g. for C<800000> keys you should use around a
230     size of C<8000>.
231    
232 root 1.5 Every hash entry is only 4 octets, os usually it isn't an issue to make the
233 root 1.2 hash table too large.
234    
235     To give you an idea of the performance, I inserted about 600000 records,
236     3GB of data, into a TDB file, using different hash sizes.
237 root 1.1
238     size time
239     131 160s
240     256 85s
241     1024 12s
242     4096 5s
243     8192 4s
244    
245 root 1.3 As you can see, the default hash table size for this case caused it to
246     use 40 times the time to insert than a larger hash table, the optimum
247 root 1.5 being around 75 keys per hash entry. But the databse easily was cached in
248 root 1.3 memory. If that is not the case, you might want to consider a hash table
249     that is larger than the number of keys you want to store - each hash slot
250     only uses 4 octets.
251 root 1.1
252     =item log_cb => $cb->($level, $msg)
253    
254 root 1.2 Sets a code reference that is called with a message and a log level
255 root 1.1 (lower means more important, there are C<DEBUG_FATAL>, C<DEBUG_ERROR>,
256     C<DEBUG_WARNING> and C<DEBUG_TRACE}>). Unlike the "debug" in the name
257     might indicate, if you want to find out why, for instance, you could not
258     open a database, you need to use a logging callback.
259    
260     =item hash => $hash (default: C<undef>)
261    
262     Selects a hash function to use.
263    
264     =over
265    
266     =item C<"default"> or C<undef>
267    
268     Use autodetection and use either C<"jenkins"> or the original tdb hash function.
269    
270     =item C<"jenkins">
271    
272     The jenkins hash function. Relatively fast, and recommended for modern tdb databases
273     that need to be interoperable between implementations.
274    
275     =item C<"fnv1ax">
276    
277 root 1.10 The FNV1-A hash with 32 bit post-mixing. Pretty good and very fast for
278 root 1.1 keys up to 10-20 octets.
279    
280     =item C<"xxh3">
281    
282     The XXH3 hash. Very good and fast especially for long keys.
283    
284     =item C<1> .. C<4>
285    
286     Specify one of up to four custom hash functions (see L<set_hash_function>).
287    
288     =back
289    
290     =item mutex => $bool (default: C<0>)
291    
292 root 1.6 TDB can take advantage of fast interprocess mutexes, which can be
293     orders of magnitude faster than the syscall-based locking used by
294     default, but only works on the same machine.
295    
296     Normally, you need to call C<TDB_FileX::runtime_check_for_robust_mutexes>
297     and set the C<MUTEX_LOCKING> flag if support is indicated.
298 root 1.1
299     This option, when enabled, enables C<MUTEX_LOCKING> if it is supported
300     by the platform - which involves a fork when opening the database. When
301     disabled, it will remove the flag.
302    
303     It is recommended to keep this one, but enabling this changes the format
304     of the database, so might not be an option if interoperability with other
305     programs is required.
306    
307 root 1.6 =item nocow => $bool (default: C<0>)
308    
309     Set the no-copy-on-write flag I<iff> this flag is true, C<open_flags>
310 root 1.7 contains C<O_CREAT>, C<tdb_flags> do not contain C<INTERNAL> and this is
311     supported on the platform and filesystem. Copy-on-write filesystems have
312     to make a copy of every block written to, which can both be costly and can
313     cause massive fragmentation of the database file.
314 root 1.6
315     Setting the no-copy-on-write flag (same as C<chattr +C>) disables this,
316     usually at the expense of data protection (checksumming), reducing the
317     safety to the level of a normal filesystem such as ext4.
318    
319     This is best effort and usually only takes effect when the
320     database is initially created. If it fails, TDB_FileX will simply
321     continue. Correctness should not be affected either way.
322    
323 root 1.1 =back
324    
325     There is no explicit close function. The database is closed implicitly
326     when there are no remaining references.
327    
328 root 1.3 =item $tdb->store ($key, $value[, $flag=REPLACE]) [CROAK]
329 root 1.1
330     Store $value in the database with key w$key. The $flag defaults to
331     C<REPLACE>, but can also be C<INSERT> or C<MODIFY>, see tdb_store(3) for
332     details.
333    
334 root 1.3 =item $tdb->append ($key, $value) [CROAK]
335    
336     Appends $data to the data already stored for $key, or creates a new entry with it.
337 root 1.1
338 root 1.12 =item $data = $tdb->fetch ($key) [CROAK]
339 root 1.1
340 root 1.3 Fetch the value associated with $key, or C<undef> if it is not found (or
341     on any error).
342 root 1.1
343 root 1.3 =item $tdb->delete ($key) [CROAK]
344 root 1.1
345     Delete the value associated with $key.
346    
347 root 1.3 =item $bool = $tdb->exists ($key)
348 root 1.1
349     Return true if the $key is found, false otherwise.
350    
351 root 1.12 =item $key = $tdb->firstkey
352 root 1.1
353     Return the key of the first value in the database. Returns C<undef> on
354     failure or if there are no keys in the database. See tdb_firstkey(3)
355     for details.
356    
357 root 1.12 =item $key = $tdb->nextkey ($lastkey)
358 root 1.1
359     Return the next key in the database after $lastkey. Returns C<undef> on
360     failure or if there are no more keys in the database. See tdb_nextkey(3)
361     for details.
362    
363 root 1.12 =item $code = $tdb->error
364 root 1.1
365     Returns the current error state of the C<$tdb> object. See the list of
366     error codes given in L<EXPORTS>.
367    
368 root 1.12 =item $mesage = $tdb->errorstr
369 root 1.1
370     Returns a printable string that describes the error state of the
371     database.
372    
373 root 1.3 =item $tdb->reopen [CROAK]
374 root 1.1
375     Closes and reopens the database. Required after a
376     L<fork|perlfunc/fork>, if both processes wish to use the database.
377    
378 root 1.3 B<NB:> If C<reopen> fails, then it is unsafe to call any further methods
379     on C<$tdb>. Thus, the only way to find out I<why> C<reopen> failed is to
380     use a logging function.
381 root 1.1
382 root 1.3 =item TDB_FileX::reopen_all [CROAK]
383 root 1.1
384 root 1.12 Closes and reopens all open databases. See C<reopen>.
385 root 1.1
386 root 1.3 B<NB:> If C<reopen_all> fails, there is no indication of I<which> C<$tdb>
387     objects failed or why. If you have to survive failures, you may wish to do
388     your own C<reopen> loop instead.
389 root 1.1
390 root 1.4 =item $tdb->traverse ($cb->($key, $data)) [CROAK]
391 root 1.1
392 root 1.4 Call $cb for each entry in the database. The callback should return false
393     to continue, or a true value to abort the traversal.
394 root 1.1
395 root 1.3 The callback is called with the key and value as arguments and should
396 root 1.4 return a false value if you wish to continue traversal, and a true value
397     if the traversal should be aborted.
398 root 1.1
399 root 1.4 C<traverse> returns the number of elements traversed. If $cb is C<undef>,
400     then this function simply counts the number of elements.
401    
402     =item $tdb->traverse_read ($cb->($key, $data)) [CROAK]
403    
404     Like C<traverse>, but only acquires a read lock.
405 root 1.1
406 root 1.3 =item $tdb->set_logging_function ($cb->($level, $msg))
407 root 1.1
408     Set the logging function to use when this database object encounters
409 root 1.3 errors.
410 root 1.1
411 root 1.3 $cb is called with the severity level (an integer) and the message (a
412 root 1.1 string).
413    
414 root 1.3 =item $tdb->lockall [CROAK]
415 root 1.1
416 root 1.2 Lock an entire database with an exclusive write lock, returning false on
417     error. The purpose of this call is to avoid locking overhead for many
418     operations, but the database has to be unlocked manually when done.
419 root 1.1
420 root 1.3 =item $tdb->unlockall [CROAK]
421 root 1.1
422     Unlock an entire database previously locked with
423 root 1.12 C<lockall>.
424 root 1.1
425 root 1.3 =item $tdb->lockall_read [CROAK]
426 root 1.2
427 root 1.12 Same as C<lockall>, but uses a shared read lock instead of a writer lock.
428 root 1.2
429 root 1.3 =item $tdb->unlockall_read [CROAK]
430 root 1.2
431 root 1.12 Opposite of C<lockall_read>.
432 root 1.2
433 root 1.3 =item $tdb->lockall_mark [CROAK]
434 root 1.2
435 root 1.3 =item $tdb->lockall_unmark [CROAK]
436 root 1.2
437 root 1.8 These apparently mark and unmark locks internally, but do not actually do
438     locking. Probably you should not use this, but feel free to tell me when
439     these are useful.
440 root 1.2
441 root 1.3 =item $tdb->lockall_nonblock [CROAK]
442 root 1.2
443 root 1.8 =item $success = $tdb->lockall_read_nonblock [CROAK]
444 root 1.2
445 root 1.8 Try to lock, but instead of waiting, fail if the lock could not
446     be acquired. Returns true if the lock could be acquired, false
447     otherwise. Croaks on all other errors.
448 root 1.2
449 root 1.3 =item $tdb->transaction_start [CROAK]
450 root 1.2
451     Starts a transaction - all operations will be queued, but not applied
452 root 1.12 to the database, until the transaction is either committed C<transaction_commit>
453     or aborted/thrown away, with C<transaction_cancel>.
454 root 1.2
455 root 1.3 =item $tdb->transaction_start_nonblock [CROAK]
456 root 1.2
457 root 1.8 Tries to start a transaction, but instead of waiting, fail if the lock
458     could not be acquired. Returns true if the transaction could be started,
459     false otherwise. Croaks on all other errors.
460    
461 root 1.2 Please tell me what this does.
462    
463 root 1.3 =item $tdb->transaction_commit [CROAK]
464 root 1.2
465     Applies all changes in the transaction.
466    
467 root 1.3 =item $tdb->transaction_cancel [CROAK]
468 root 1.2
469     Throws away all changes in the transaction.
470    
471 root 1.3 =item $tdb->transaction_prepare_commit [CROAK]
472 root 1.2
473 root 1.12 Instead of calling C<transaction_commit> you can do the commit in
474 root 1.2 two phases by calling this method before commit, which does the expensive
475     steps first.
476    
477     =item $bool = $tdb->transaction_active
478    
479     Returns true if a transaction is currently active.
480    
481     =item $tdb->enable_seqnum
482    
483     Enables sequence number generatiuon supporet for the database.
484    
485     =item $seq = $tdb->get_seqnum
486    
487     Returns the current sequence number. Internally, this is a 32 bit unsigned
488     integer, but the API converts it into a native integer, so the same
489     internal sequence number might be represented differently on different
490     machines.
491    
492     =item $tdb->increment_seqnum_nonblock
493    
494     Increments the sequence number. Note that the sequence number is also
495     incremented by TDB itself oon many operations.
496    
497     =item $size = $tdb->hash_size
498    
499     Returns the size of the hash table. The size cannot be changed other than
500     by recreating the database.
501    
502     =item $octets = $tdb->map_size
503    
504     Returns the current mmap size for the database.
505    
506     =item $flags = $tdb->get_flags
507    
508     Returns the flags for the database (the same as the C<tdb_flags> in C<open>).
509    
510     =item $tdb->add_flags ($flag)
511    
512     Tried to add flags to the database - yes, the parameter says C<$flag> (singular)
513     but the documentation and the code say I<flags> (plural).
514    
515     =item $tdb->remove_flags ($flag)
516    
517     Attempts to remove flags from the database.
518    
519 root 1.13 =item $tdb->set_max_dead ($max_dead)
520    
521     Set the maximum number of dead records per hash chain.
522    
523 root 1.2 =item $fileno = $tdb->fd
524    
525     Returns the file descriptor (not file handle) for the underlying database file.
526    
527     =item $path = $tdb->name
528    
529     Returns the path used to open the database.
530    
531 root 1.3 =item $tdb->wipe_all [CROAK]
532 root 1.2
533     Efficientlly deletes all entries in the database. This does not shrink the
534     file itself.
535    
536 root 1.3 =item $tdb->repack [CROAK]
537 root 1.2
538     Tries to improve layout of the database by copying all items into a
539     temporary in-memory database, wiping the database, and copying all items
540 root 1.3 back. Yes, everything must fit into memory.
541 root 1.2
542 root 1.4 =item $bool = $tdb->check ($cb->($key, $value))
543    
544     Does extensive checks on the database, optionally (if not C<undef>)
545     calling a check function for each pair, which must return true if the data
546     is valid.
547    
548     Returns a boolean indicating whether the database was found healthy and
549     all the calls to the callback returned true.
550    
551     =item $bool = $tdb->rescue ($cb->($key, $value))
552    
553     Tries to recover some or all key-value pairs from a potentially damanged
554     database file. For each recovered pair it calls the given callback.
555    
556     Returns a boolean indicating whether the database was found healthy and
557     all the calls to the callback returned true.
558    
559 root 1.2 =item $bool = TDB_FileX::runtime_check_for_robust_mutexes
560    
561     Tests whether robust mutexes are available for locking. This involves
562     forking the process, so it can be costly and problematic. This function
563     needs to be called before using the C<MUTEX_LOCKING> flag. But see the
564     C<mutex> parametrer to C<open> for an alternative.
565    
566 root 1.1 =item $tdb->dump_all
567    
568     Dump the records and freelist to STDOUT in an almost human readable
569     form.
570    
571 root 1.9 =item $summary = $tdb->summary
572    
573     Return a textual summary of the database. The format isn't documented,
574     but for some random databas,e I got this output:
575    
576     Size of file/data: 325001216/238324906
577     Header offset/logical size: 4001792/320999424
578     Number of records: 117209
579     Incompatible hash: no
580     Active/supported feature flags: 0x00000001/0x00000001
581     Robust mutexes locking: yes
582     Smallest/average/largest keys: 11/36/102
583     Smallest/average/largest data: 10/1997/2921430
584     Smallest/average/largest padding: 9/530/749374
585     Number of dead records: 0
586     Smallest/average/largest dead records: 0/0/0
587     Number of free records: 1126
588     Smallest/average/largest free records: 12/15312/14681136
589     Number of hash chains: 100000
590     Smallest/average/largest hash chains: 0/1/8
591     Number of uncoalesced records: 0
592     Smallest/average/largest uncoalesced runs: 0/0/0
593     Percentage keys/data/padding/free/dead/rechdrs&tailers/hashes: 1/72/19/5/0/1/0
594    
595     =item $octets = $tdb->freelist_size
596    
597     Returns the total number of free (unused) octets in the file.
598    
599 root 1.1 =item $tdb->printfreelist
600    
601     Dump the freelist to STDOUT.
602    
603     =back
604    
605     =head2 EXPORTS
606    
607     Nothing constants are exported by default.
608    
609     The tag C<:all> exports allpo of the constants.
610    
611     Individually or with the tag C<:flags>:
612    
613     DEFAULT
614     CLEAR_IF_FIRST
615     INTERNAL
616     NOLOCK
617     NOMMAP
618     CONVERT
619     BIGENDIAN
620     NOSYNC
621     SEQNUM
622     VOLATILE
623     ALLOW_NESTING
624     DISALLOW_NESTING
625     INCOMPATIBLE_HASH
626     MUTEX_LOCKING
627    
628     Individually or with the tag C<:insert>:
629    
630     REPLACE
631     INSERT
632     MODIFY
633    
634     Individually or with the tag C<:error>:
635    
636     SUCCESS
637     ERR_CORRUPT
638     ERR_IO
639     ERR_LOCK
640     ERR_OOM
641     ERR_EXISTS
642     ERR_NOLOCK
643     ERR_LOCK_TIMEOUT
644     ERR_NOEXIST
645     ERR_EINVAL
646     ERR_RDONLY
647    
648     Individually or with the tag C<:debug>:
649    
650     DEBUG_FATAL
651     DEBUG_ERROR
652     DEBUG_WARNING
653     DEBUG_TRACE
654    
655 root 1.2 =head1 UNICODE HANDLING
656    
657     TDB databases can only store octet strings. Unlike most other database
658     interfaces, TDB_FileX will safely handle Perl strings by downgrading
659     them. Perl will warn about strings that cnanot be downgraded.
660    
661     =head1 DISK USAGE
662    
663     TDB databses use 24 octets for every key-value pair, plus the octet size
664     of the key and sata, e.g. the pair "key" => "value" takes up 24+3+5 octets
665     on disk.
666    
667     The database header is 168 octets (if I haven't miscounted).
668    
669     Each hashtable entry is 4 octets, and one more than the hash size is
670 root 1.10 allocated, so the hash table size is (hash_size + 1) * 4.
671 root 1.2
672     =head1 LIMITATIONS
673    
674     =head2 Database Size
675    
676     As far as I can see, TDB dastabases are limited to 4 GB.
677    
678     =head2 Hash Functions
679    
680     Hash functioons need to be set globally - they are limited to a maximum of
681     4, but this can be easily extended, but requires source code editing. This
682     is due to a limitation of the TDB C API.
683    
684     =head2 No recoivery after failed C<reopoen_all>
685 root 1.1
686     There is no way to survive an error during C<reopen_all>.
687     Unfortunately this is a limitation in the TDB C API.
688    
689     =head1 SEE ALSO
690    
691     tdb(3), L<perltie>.
692    
693     =head1 AUTHOR
694    
695     Angus Lees, E<lt>gus@inodes.org>
696    
697     Currently maintained by Marc A. Lehmann <schmorp@schmorp.de>
698     http://home.schmorp.de/
699    
700     =cut