Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Infinite recursion for iterator of tied hash with perldbmfilter for filter_fetch_key

by Pickwick (Beadle)
on Sep 08, 2014 at 21:29 UTC ( [id://1099905]=perlquestion: print w/replies, xml ) Need Help??

Pickwick has asked for the wisdom of the Perl Monks concerning the following question:

Dear wise monks,

I have a tied hash in Perl which uses SDBM_File and I need to do some character encoding conversions when storing or fetching values. I followed the documentation of perldbmfilter and in general it seems to work: I get the results from the hash properly encoded like expected and it stores the byte values for my encoding in the file, if I check using a hex editor.

What is not working is any kind of iteration over all elements of the hash, either using keys(...) or each(...) or things like Dumper(...) or even a simple copy operation to another hash. What I always get is an infinite recursion, it seems like the used iterator doesn't ever get to it's end and if I use each(...) and print the iterated values they are repeated all over. I hunted the problem down to the use of filter_fetch_key and the charset conversion I'm doing there: If I comment filter_fetch_key the iteration works again or if I change the called method to not do anything, but only do a "return shift;" Either of both solves my problem, but I need to use filter_fetch_key to send the caller properly encoded strings.

$dbm->filter_fetch_key (sub { $_ = $self->_normalizeCharset($_); }); sub _normalizeCharset { my $self = shift || Carp::croak(...); #return shift; return ...::windows2utf(shift); }

If I uncomment "return shift", the iteration works, but commented like above it doesn't. I guess it has something to do what happens to $_, but I have no idea, as windows2utf just copies the given data and does some character encoding. This works the same way for storing keys and values and even for fetching values. Only keys are the problem and only if I do an iteration, not if I directly ask for specific keys.

Any hints on what I'm doing wrong? Thanks!

Replies are listed 'Best First'.
Re: Infinite recursion for iterator of tied hash with perldbmfilter for filter_fetch_key
by choroba (Cardinal) on Sep 08, 2014 at 21:32 UTC
    Do not use each.

    Update: Crossposted at StackOverflow. It's considered polite to inform about crossposting not to make people not attending both sites waste their efforts hacking a problem already solved at the other end of the Internets.

    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Sorry, was late already yesterday and just forgot to mention the crosspost. As for each, that's not the problem here, only a symptom, because the problem occurs with keys(...) and copying the hash as well.

Re: Infinite recursion for iterator of tied hash with perldbmfilter for filter_fetch_key
by Pickwick (Beadle) on Sep 09, 2014 at 09:42 UTC

    I have found the issue: During the tests I recognized that filter_fetch_key calls my function once with a key value of undef and my functions return an empty string for convenience in that case. This seems to be what's causing the infinite loop, I guess someone wants to add that empty string as a new key to the hash for some reason and runs into problems with some iterator which gets invalid or such. The interesting part about that is that changes to keys should be perfectly fine, because one of the examples in the documentation is exactly about that and my tests show that I can replace each key except the undef one which whatever I like, I can create completely new keys by prepending __ for example. No problem, only if I don't return undef for undef I get the infinite loop. The first version of the following method works, the second does not.

    sub _normalizeCharset { my $self = shift || Carp::croak(...); my $value = shift; my $key = shift || 0; return undef unless (defined($value)); #return '' unless (defined($value)); $value = "__$value" if ($key); return ...::windows2utf($value); }
    sub _normalizeCharset { my $self = shift || Carp::croak(...); my $value = shift; my $key = shift || 0; #return undef unless (defined($value)); return '' unless (defined($value)); $value = "__$value" if ($key); return ...::windows2utf($value); }

    I guess undef may be some special signal of the filter to indicate the end of iterated keys or such and simply is not meant as a regular hash key. At least I don't put it anywhere.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1099905]
Approved by AppleFritter
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (3)
As of 2024-03-19 06:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found