Using exists() on a tie'd DB_File hash 
Author Message
 Using exists() on a tie'd DB_File hash

Hello-

I have a hash that I have tied like this:
$db = tie(%{$hashref}, DB_File, $filename, O_RDONLY, 0660) || return 0;

I'd like to take the hash (let's call it %this_hash) and use exists() on
it, like I would with a normal hash, for instance:
if (exists($this_hash{'key'})) {
        #do something

Quote:
}

The problem is this error:
DB_File doesn't define an EXISTS method at test.pl line 14

Now, I suppose I could subclass DB_File and define an EXISTS method
myself, but I'm not all that experienced/confident with Object-Oriented
stuff, so I'd rather not do that.  What I want to do is write a
subroutine called &exists() or something that will do a good check of
whether a hash entry exists.  I also don't want to step through all the
keys (using a while loop or something) and check for a match, because my
dbms are pretty big.

Can anyone suggest some tests I can stick in my subroutine?

Actually, this is all coming from a more general question: is there a
way to have a tie'd hash behave _exactly_ like a regular hash, and not
just similar to it?  For instance, I can't do
$hash{'key'}++;
unless $hash{'key'} already exists, or else I get the following error
message:

inst fault=4, status word=               8, pc=       14005d468
Illegal instruction

Whereas if %hash were just a normal hash and not a tie'd hash,
$hash{'key'}++ would work fine even if $hash{'key'} didn't already
exist.

Can anyone comment on this?  Thanks!

-Ken Williams
 The Math Forum



Sat, 27 Mar 1999 03:00:00 GMT  
 Using exists() on a tie'd DB_File hash

: Hello-

: I have a hash that I have tied like this:
: $db = tie(%{$hashref}, DB_File, $filename, O_RDONLY, 0660) || return 0;

: I'd like to take the hash (let's call it %this_hash) and use exists() on
: it, like I would with a normal hash, for instance:
: if (exists($this_hash{'key'})) {
:       #do something
: }

: The problem is this error:
: DB_File doesn't define an EXISTS method at test.pl line 14

: Now, I suppose I could subclass DB_File and define an EXISTS method
: myself, but I'm not all that experienced/confident with Object-Oriented
: stuff, so I'd rather not do that.  What I want to do is write a
: subroutine called &exists() or something that will do a good check of
: whether a hash entry exists.  I also don't want to step through all the
: keys (using a while loop or something) and check for a match, because my
: dbms are pretty big.

: Can anyone suggest some tests I can stick in my subroutine?

As of DB_File version 1.03, 'exists' is supported. If you get the
latest development relase of Perl, version 5.003_05, it will be
included in it. Alternatively, read on.

The reason 'exists' was never implemented in DB_File is because it
doesn't really give you anything that 'defined' can't already in the
context of a hash tied to a DBM file. Here is part of the manual page
entry on exists and defined:

    exists EXPR

    Returns TRUE if the specified hash key exists in its hash array,
    even if the corresponding value is undefined.

    defined EXPR

    Returns a boolean value saying whether EXPR has a real value or
    not.  
    ...

    When used on a hash array element, it tells you whether the value
    is defined, not whether the key exists in the hash.  Use exists()
    for that.

        print "Exists\n" if exists $array{$key};
        print "Defined\n" if defined $array{$key};
        print "True\n" if $array{$key};

The concept of a value being undefined is part of Perl. DBM files in
general, and Berkeley DB in this particular case, cannot associate a
key with a Perl undefined value. The best they can do is store an empty
string ("") instead, and 'defined' can test for the existance of your
key in this case.

So the bottom line is, 'defined' and 'exists' do exactly the same thing
in DB_File.

: Actually, this is all coming from a more general question: is there a
: way to have a tie'd hash behave _exactly_ like a regular hash, and not
: just similar to it?  For instance, I can't do
: $hash{'key'}++;
: unless $hash{'key'} already exists, or else I get the following error
: message:

: inst fault=4, status word=               8, pc=       14005d468
: Illegal instruction

: Whereas if %hash were just a normal hash and not a tie'd hash,
: $hash{'key'}++ would work fine even if $hash{'key'} didn't already
: exist.

: Can anyone comment on this?  Thanks!

Yes, there is something seriously wrong. What you tried to do should
work as expected. Did you have the database opened read-only as implied
by your code above?

Try using O_RDWR, like this:

 $db = tie(%{$hashref}, DB_File, $filename, O_RDWR, 0660) || return 0;

Apart from the comment about exists (and the ability to store code in
real hashes) tied hashes do work just like real ones.

If you are still getting the program crash, could you send me details
of your Perl installation (typing perl -V on recent versions will do)
and the version of Berkeley DB you are running.

Paul



Sat, 27 Mar 1999 03:00:00 GMT  
 Using exists() on a tie'd DB_File hash

Hi-

Quote:

> As of DB_File version 1.03, 'exists' is supported. If you get the
> latest development relase of Perl, version 5.003_05, it will be
> included in it. Alternatively, read on.

Aha.  I've got version 5.001, Unofficial patchlevel 1m.  I'll try to
convince the authorities around here to update if I keep having
problems.

Quote:

> The reason 'exists' was never implemented in DB_File is because it
> doesn't really give you anything that 'defined' can't already in the
> context of a hash tied to a DBM file.

Thanks, Paul!  This indeed fixes the problem.

Quote:
> Yes, there is something seriously wrong. What you tried to do should
> work as expected. Did you have the database opened read-only as implied
> by your code above?

Oh, gosh.  Sorry, what I'm really doing in this case is this:
$db = tie(%{$hashref}, DB_File, $filename, O_CREAT|O_RDWR, 0660) ||
return 0;

Then I do this:
($fd = $db->fd);
flock ($filehandle{$hashref}, 6);

So I don't think it's a permissions problem, at least not one I
understand.  Here's another thing: if I do
$hash{'key'}++;
I get the confusing error I mentioned before.  If I do
$hash{'key'} = $hash{'key'} + 1;
everything works fine and the value is stored properly in the database.

I'm using version 1.85 of Berkeley DB.

Thanks a lot for your earlier response, Paul!

-Ken
 The Math Forum



Sat, 27 Mar 1999 03:00:00 GMT  
 Using exists() on a tie'd DB_File hash

: Hi-

: > As of DB_File version 1.03, 'exists' is supported. If you get the
: > latest development relase of Perl, version 5.003_05, it will be
: > included in it. Alternatively, read on.

: Aha.  I've got version 5.001, Unofficial patchlevel 1m.  I'll try to
: convince the authorities around here to update if I keep having
: problems.

: >
: > The reason 'exists' was never implemented in DB_File is because it
: > doesn't really give you anything that 'defined' can't already in the
: > context of a hash tied to a DBM file.

: Thanks, Paul!  This indeed fixes the problem.

Good.

: > Yes, there is something seriously wrong. What you tried to do should
: > work as expected. Did you have the database opened read-only as implied
: > by your code above?

: Oh, gosh.  Sorry, what I'm really doing in this case is this:
: $db = tie(%{$hashref}, DB_File, $filename, O_CREAT|O_RDWR, 0660) ||
: return 0;

: Then I do this:
: ($fd = $db->fd);
: flock ($filehandle{$hashref}, 6);

: So I don't think it's a permissions problem, at least not one I
: understand.  Here's another thing: if I do
: $hash{'key'}++;
: I get the confusing error I mentioned before.  If I do
: $hash{'key'} = $hash{'key'} + 1;
: everything works fine and the value is stored properly in the database.

You shouldn't be getting that behaviour. If you disable the file
locking code does it still crash?

: I'm using version 1.85 of Berkeley DB.

That is the latest and greatest.

What version of Perl are you running? What OS? If you have a recent
version of Perl post me the output when you run "perl -V".

Paul



Sun, 28 Mar 1999 03:00:00 GMT  
 Using exists() on a tie'd DB_File hash

Hi-

Quote:

> You shouldn't be getting that behaviour. If you disable the file
> locking code does it still crash?

> : I'm using version 1.85 of Berkeley DB.

> That is the latest and greatest.

> What version of Perl are you running? What OS? If you have a recent
> version of Perl post me the output when you run "perl -V".

> Paul

Well, I've whittled down the code to almost nothing, and I still get the
problem:
*******************************************************************
#!/usr/bin/perl

use DB_File;
use Fcntl;

tie(%hash, DB_File, "hash.db", O_CREAT|O_RDWR, 0660);
$hash{'ken'}++;
untie (%hash);
*******************************************************************
Which produces this error if $hash{'ken'} doesn't already exist:
inst fault=4, status word=               8, pc=       140054068
Illegal instruction

My version of Perl doesn't recognize the -V tag, but here's what I get
when I do perl -v (I put this in my previous posting too) (#'s mine):
###################################################################
This is perl, version 5.001

        Unofficial patchlevel 1m.

Copyright 1987-1994, Larry Wall

Perl may be copied only under the terms of either the Artistic License
or the
GNU General Public License, which may be found in the Perl 5.0 source
kit.
###################################################################

I'm running this all on a DEC AlphaServer 1000/266, running Digital UNIX
V3.2C  (Rev. 148).  

-Ken



Mon, 29 Mar 1999 03:00:00 GMT  
 Using exists() on a tie'd DB_File hash

-----BEGIN PGP SIGNED MESSAGE-----

 KW> I have a hash that I have tied like this:
 KW> $db = tie(%{$hashref}, DB_File, $filename, O_RDONLY, 0660) || return 0;
 KW>
 KW> I'd like to take the hash (let's call it %this_hash) and use exists() on
 KW> it, like I would with a normal hash, for instance:
 KW> if (exists($this_hash{'key'})) {
 KW>         #do something
 KW> }
 KW>[...]
 KW> $hash{'key'}++;
 KW> unless $hash{'key'} already exists, or else I get the following error
 KW> message:
 KW>
 KW> inst fault=4, status word=               8, pc=       14005d468
 KW> Illegal instruction
 KW>
 KW> Whereas if %hash were just a normal hash and not a tie'd hash,
 KW> $hash{'key'}++ would work fine even if $hash{'key'} didn't already
 KW> exist.

Where does SIGILL actually happen?
Try running your script with 'use sigtrap;' and you may find SIGILL
trapped after exiting your script.

A workaround may be untie-ing all tied hashes before exiting. You may
do this automatically by something like this:

        END { untie(%{$hashref}) if defined $hashref }

[ Remember: only one END per source file (or per package?) allowed! ]

What happend? Well, I suppose the underlying database library urgently
needs some proper cleanup (untie) before exiting. If so, then this a
bug and should be corrected withing the database libraries .pm
interface.  The very same happens with other tie-packages like Msql.

- - Andreas

-----BEGIN PGP SIGNATURE-----
Version: 2.6.2i
Comment: Processed by Mailcrypt 3.3, an Emacs/PGP interface

iQBVAwUBMms24EVdjNvyndGpAQEpVQH+MRFO8zq3eNDikQ/d477CQyi8LznJHpqC
ZALydi4dFoqaMVk8+2lr3mcXPjQIHfRc6l6LYDArsBFGnx2CGDKQ6Q==
=Bcm6
-----END PGP SIGNATURE-----
--
Andreas Koppenhoefer, Student der Universitaet Stuttgart, BR Deutschland
Franz-Schubert-Str. 2, 97616 Bad Neustadt; Phone +49 9771 7943, Fax/Data 7947


URL <http://www.informatik.uni-stuttgart.de/menschen/ako/impressum.html>



Fri, 09 Apr 1999 03:00:00 GMT  
 Using exists() on a tie'd DB_File hash

-----BEGIN PGP SIGNED MESSAGE-----

 KW> This is perl, version 5.001

You should upgrade now! Perl versions prior 5.002 tended to crash every
now and then - its memory management was totally broken!

- - Andreas
-----BEGIN PGP SIGNATURE-----
Version: 2.6.2i
Comment: Processed by Mailcrypt 3.3, an Emacs/PGP interface

iQBVAwUBMms3k0VdjNvyndGpAQH3EQH+JlC9bpDb1jgG1r0w44wuhx53CxPV1Wp+
e1/ZzTooGT4C3zysqdNgAV5enrTJyFXvpciM/tjoET0/Rqst1raQfg==
=eZHW
-----END PGP SIGNATURE-----
--
Andreas Koppenhoefer, Student der Universitaet Stuttgart, BR Deutschland
Franz-Schubert-Str. 2, 97616 Bad Neustadt; Phone +49 9771 7943, Fax/Data 7947


URL <http://www.informatik.uni-stuttgart.de/menschen/ako/impressum.html>



Fri, 09 Apr 1999 03:00:00 GMT  
 
 [ 7 post ] 

 Relevant Pages 

1. design considerations for using DB_File tie hashes ???

2. need to lock a tied hash using DB_File ?

3. Tie::Hash EXISTS not implemented?

4. Problems with tied hash and DB_File

5. Operators for Tied hashes on NBDM_File and GDBM_File, plus DB_File for AIX

6. Help storing a hash of hashes using DB_File

7. How to tie a hash of references to a DB_File

8. Problems with tie %HASH, DB_File

9. tie %HASH to DB_File not working

10. Using the hash DB_File uses, after untie it??

11. Tie hash of hash using MLDBM

12. using IPC::Shareable and using Tie::IxHash for the same hash

 

 
Powered by phpBB® Forum Software