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

Hey, I'm new to PM and this is my first post. I'm also *fairly* new to Perl, but I do have a bit of experience under my belt.

I have a script that is converting a text file into a database. I wanted to use GDBM because of its "many-reader" aspect. I'm beginning to think it's not worth it, but I was curious about why I'm getting what I'm getting.

It appears as though the database file itself is full of code from the XSLoader module. First, here's the script:

#!/usr/local/stow/perl-5.6.1/bin/perl -w use GDBM_File; my $portlist = "/dfs/umaint/stow/UMno/libdata/portlist"; my %ports; tie(%ports,'GDBM_File','gdbmtest',&GDBM_NEWDB,0644) or die "$!\n"; open(PL, $portlist) or die "$!\n"; while(<PL>) { chomp; next if(/^\#/ || $_ eq ""); my ($switch,$ifnum,$trunk,$desc) = split(/:/); my ($generated,$conn,$notes) = split(/\s(\+|-|!)\s*/,$desc); my ($ifname,$vlan,$host) = split(/\s/,$generated); $ports{"$switch:$ifnum"} = "$trunk:$ifname:$vlan:$host:$conn:$note +s"; } untie(%ports) or warn "$!\n";

And now for the gdbmtest file:

^SW\232\316^D^D^D^H^D0^BXzr.pm. # Often these errors are actually occurring in the initialisation # C code of the extension XS file. Perl reports the error as being # in this perl code simply because this was the last perl code # it executed. + my $libref = dl_load_file($file, 0) or do { require Carp; Carp::croak("Can't load '$file' for module $module: " . dl_err +or()); }; push(@dl_librefs,$libref); # record loaded object + my @unresolved = dl_undef_symbols(); if (@unresolved) { require Carp; Carp::carp("Undefined symbols present after loading $file: @un +resolved\n"); } + my $boot_symbol_ref = dl_find_symbol($libref, $bootname) or do { require Carp; Carp::croak("Can't find '$bootname' symbol in $file\n"); }; + my $xs = dl_install_xsub("${module}::bootstrap", $boot_symbol_ref, + $file); push(@dl_modules, $module); # record loaded module # See comment block above return &$xs(@_); retry: require DynaLoader;

When I used regular dbm(open|close) to create the database I was able to write to it and read from it correctly. I couldn't find anything odd with the GDBM_File.pm or XSLoader.pm files, but I could be missing something. Should I post the text of those files as well?

Replies are listed 'Best First'.
Re: Strange GDBM behavior
by gam3 (Curate) on Jul 22, 2005 at 03:55 UTC
    I wrote a simple test writer and reader and did not have any problems.

    Here is the writer.

    #!/usr/bin/perl use GDBM_File; my %ports; tie(%ports,'GDBM_File','gdbmtest',&GDBM_NEWDB,0644) or die "$!\n"; for my $switch (0 .. 5) { for my $ifnum (0 .. 5) { $ports{"$switch:$ifnum"} = "test $switch $ifnum"; } } untie(%ports) or warn "$!\n";
    And a reader
    #!/usr/bin/perl use GDBM_File; my %ports; tie(%ports,'GDBM_File','gdbmtest',&GDBM_READER,0644) or die "$!\n"; for my $switch (0 .. 5) { for my $ifnum (0 .. 5) { print $ports{"$switch:$ifnum"}, "\n"; } } untie(%ports) or warn "$!\n";
    -- gam3
    A picture is worth a thousand words, but takes 200K.
      Oddly enough, further examination of the file showed that there was one huge incomplete line after what I posted (vi didn't like showing it but emacs did). I was able to read from the file and get correct output. Why is it inserting that text from the module, though? Is that intended behavior? I actually created my reader script by copying the writer, and forgot to change the GDBM_NEWDB the first time... when I examined that produced file, it had the entire text of the reader script in it. Oh well... I suppose all's well that's read well.
Re: Strange GDBM behavior
by graff (Chancellor) on Jul 22, 2005 at 05:01 UTC
    When you used "regular dbm(open|close)", did you also happen to have "use GDBM_File;" ? Or not? If not, then you were probably using some default dbm library other than GDBM, and maybe there was a problem with how your GDBM library and/or GDBM_File module were installed.

    (According to perldoc -f dbmopen -- at least in my 5.8.1 version -- you can say "use SOMEDBM_File;" in combination with dbmopen, in order to override whatever dbm library was designated as the default when your perl was installed.)

    But if the default dbm library works for you, all you need to do is find out what that is and check that it's available in all the places where you want your code to be portable to. Here's a one-liner to find out the default:

    perl -MAnyDBM_File -e 'print $AnyDBM_File::ISA[0],$/'

    I get "NDBM_File" on macosx/perl-5.8.1, freebsd/perl-5.8.6 and solaris/perl-5.8.0 -- and since NDBM, like GDBM, is not byte-order dependent, it seems like a safe choice (unless the 4K limit on record size is an issue for you, which it probably isn't).

    (minor update to fix grammar; also noticed that NDBM was also the default on 5.005_03 perl on solaris)

      No, I was not using GDBM. My point was just that I didn't think it was a problem with the method I was using to write or another error in my script. I'm actually thinking about using DB_File or just plain NDBM with flock. That's probably pretty much what GDBM does under the tie anyways (actually, the tie just gives you access to the C library, which I'm sure does file locking for you, likely with race condition checking, etc.)