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

Monks, etc, please help: I am using version 0.611 of the Storable module on a win32 platform. This is the most current version that ActiveState's PPM installation will give me, though a much newer version is available on CPAN. I have a need to use file locking when storing data structures. The latest version of Storable on CPAN (which I am having problems installing, but that aside for now, please) implements a lock_store and lock_retrieve function. But for now, I have tried writing my own storable file lockin wrapper around the old version, and am having problems, in essence, using store_fd instead of store.

I have code written that uses the 'store' function, which accepts a filename to save as. However, if I change it to use store_fd, which accepts a file handle/descriptor instead, I would think I could use flock to do the locking for me.

This is not a question on how to use flock (it fails whether I lock or not), but rather, why isn't store_fd working for me when I use sysopen to get a file handle? It doesn't update the storable file. If I get the file description with perl's 'open' for writing instead, it will update the file, but does not write in a format that retrieve is happy with. I will post my code. Any ideas?? Hopefully I am just making some simple mistake. Thanks!
# # lock a file handle # # arg 1: reference to file handle # # call like this: &lockFile(\*MYFILEHANDLE); # # locking/unlocking should be done in situations when a file handle is # opened for WRITING, in this sequence: # # open (FILE, ">some_file.txt"); # &lockFile(\*FILE); # . # . (process your info here) # . # &unlockFile(\*FILE); # close (FILE); # # # # sub lockFile { my ($fh); $fh = shift; # # win 9x and some really old perls won't support flock # this will determine if we have flock capabilities # and write to constant HAS_FLOCK # use constant HAS_FLOCK => eval { flock STDOUT, 0; 1 }; if (HAS_FLOCK) { flock ($fh, 2); } } # # unlock a filehandle # # arg 1: reference to file handle # # call like this: &unlockFile(\*MYFILEHANDLE); # sub unlockFile { my ($fh); $fh = shift; if (HAS_FLOCK) # sub lockFile already determined if 'flock' suppor +ted { flock ($fh, 8) } } # # this implements the storable module's store functionality with locki +ng # arg 1: reference to perl data object # arg 2: filename of storable data file # # the latest Storable module supports store_lock, which does this, but + it is # currently not available via ppm installation. So we will use this wr +apper # instead. The method is described in the perl cookbook, so it should +be # trustworthy. # # # and since we use our own lockFile and unlockFile functions, locking +will # gracefully NOT be used when it's not supported. # sub storeWithLocking { my ($reference, $fn); $reference = $_[0]; $fn = $_[1]; use Storable qw(store_fd); sysopen(DF, "$fn", O_RDWR|O_CREAT, 0666) or die "can't open ${fn}: $!"; &lockFile(\*DF); eval ' store_fd($reference, \*DF); '; if ($@) { print "Error in store_fd call: \"$@\"<BR>\n"; } truncate(DF, tell(DF)); &unlockFile(\*DF); close(DF); }

Edit kudra, 2002-08-05 Added a READMORE tag

Replies are listed 'Best First'.
Re: File Locking using (older) Storable Module
by PodMaster (Abbot) on Aug 05, 2002 at 06:56 UTC
    This is the most current version that ActiveState's PPM installation will give me, though a much newer version is available on CPAN.
    That is the precise reason I opened http://crazyinsomniac.perlmonk.org/perl/ppm/. It's my ppm repository, and if I can compile it, i'll put it up. Right now I have Storable-2.04. Just add my site as a repository, in ppm3
    ppm>rep add http://crazyinsomniac.perlmonk.org/perl/ppm/
    or in older versions of ppm
    ppm>set rep http://crazyinsomniac.perlmonk.org/perl/ppm/
    and install it. If you're having trouble doing so using ppm, I have instructions at my repository for doing it by hand (it's really just a perl program, just scroll down ;).

    The version up there is for the 5.6x version of perl. If you got an older perl , just ask and i'll see if I can compile it for that version of perl and put it up, ooor, just go ahead and download perl 5.8.0 from my website, cause it has the latest version of Storable.

    update: what demerphq? No, perl 5.6 is not binary compatible with perl 5.8.0. Since perl 5.8.0 comes with storable, i gotta say what?

    Oh I get it. When I say download perl 5.8.0, I mean download perl, not a ppm of storable for perl 5.8.0. Since perl 5.8.0 available from my repository above, is built with Storable, I don't provide it as a separate ppm package, not until 2.5 anyway ;)

    This is perl, v5.8.0 built for MSWin32-x86-multi-thread by a crazy insomniac

    update: Here's how to set-up your own ppm repository.

    All you need is a web-server, preferably apache, and a world readable directory, which lists all the files in it.

    You need to know how to make a PPM package, and the ActivePerl docs say:

    How do I make a PPM package?

    If you want to make a PPM package for use on other machine you can do it like this:

    Specify the AUTHOR and ABSTRACT parameters in the Makefile.PL. However you should only pass them to WriteMakefile if the version of the perl is greater than 5.005 - older perls do not have these parameters added and do not expect to see them. This is an example Makefile.PL:

    use ExtUtils::MakeMaker;
    # See lib/ExtUtils/MakeMaker.pm for details of how to influence
    # the contents of the Makefile that is written.
    WriteMakefile(
        'NAME' => 'Term::Control',
        'VERSION_FROM' => 'Control.pm', # finds $VERSION
        ($] ge '5.005') ? (
            'AUTHOR' => 'Johnny Doel (johnny@doel.org)',
            'ABSTRACT' => 'Control the IO for terminals',
        ) : (),
    );

    Then you make the archive with the commands

    perl Makefile.PL<br> nmake

    The resulting files are placed in the blib directory that is created when you run nmake. These files should be packed into an archive like this:

    tar cvf <i>package</i>.tar blib<br> gzip --best <i>package</i>.tar

    You now have an archive called package.tar.gz. Then you generate the PPD file by:

    nmake ppd

    You have to edit the resulting PPD file and add the location of the package archive into <CODEBASE HREF="" />. The location is relative to the PPD file.

    Here is a sample ppd file.
    <SOFTPKG NAME="AxKit" VERSION="1,6,0,0"> <TITLE>AxKit</TITLE> <ABSTRACT></ABSTRACT> <AUTHOR></AUTHOR> <IMPLEMENTATION> <OS NAME="MSWin32" /> <ARCHITECTURE NAME="MSWin32-x86-multi-thread" /> <CODEBASE HREF="AxKit.tar.gz" /> </IMPLEMENTATION> </SOFTPKG>
    Right now at my repository, all my PPD's and .tar.gz's are all in the same directory, but as I start building perl 5.8.0 compatible packages, i'll start mainting a directory structure like Randy Kobes.

    **TIP: When making ppm packages, or perl modules which rely upon external libraries, like JavaScript.pm, which relies on the SpiderMonkey JavaScript library, include those *.dll's into the blib/arch/auto/Modulename library, where the other .dll's particular to that module reside. That way you don't have to mess with search paths and stuff. Example package ;)

    +---blib
    |   +---arch
    |   |   \---auto
    |   |       \---JavaScript
    |   |               .exists
    |   |               JavaScript.bs
    |   |               JavaScript.dll
    |   |               JavaScript.exp
    |   |               JavaScript.lib
    |   |               js32.dll
    |   |
    |   \---lib
    |       |   .exists
    |       |   JavaScript.pm
    |       |   JavaScript.pod
    |       |   test.js.pl
    |       |
    |       \---auto
    |           \---JavaScript
    |                   .exists
    |                   autosplit.ix
    

     

    ____________________________________________________
    ** The Third rule of perl club is a statement of fact: pod is sexy.

      just go ahead and download perl 5.8.0 from my website, cause it has the latest version of Storable.

      I though 5.8 wasnt binary compatible with 5.6?

      Yves / DeMerphq
      ---
      Writing a good benchmark isnt as easy as it might look.

Re: File Locking using (older) Storable Module
by crenz (Priest) on Aug 04, 2002 at 20:19 UTC

    Sorry, can't give you the answer for the fd-problem, but I can provide a fix:

    Why not flock "$fn.lock" instead of trying to lock $fn directly? This way, you don't have to open $fn, so you can store the normal way. For you application, it won't make a difference, I guess. Also, it's quite a widespread unix practice when having to lock around "black boxes" that you can't/don't want to change.

Re: File Locking using (older) Storable Module
by JupiterCrash (Monk) on Aug 06, 2002 at 03:33 UTC
    Hi: I am the original poster, who created an account just to ask this question, and then forgot to log in while asking it. (hence, the Anonymous Monk thing.. ) Oops.

    First of all, thank you everyone for your help.

    Locking filename.lck is a good solution which I did not think of. I would still love to get a newer storable module working, though that would probably be a perfectly fine last resort.

    Crazy Insomniac: Your PPM site is a most excellent service, and I am very glad to know about it! I am, unfortunately, using Perl 5.005_03. I would just upgrade to 5.6, but then I have a feeling that some of my existing binary modules might fail (dbi, dbd?), or even to 5.8, but then even more might fail. I am going to experiment with this one night when I have more time. Do you think it will result in having to re-install many modules? If you are able to compile a Storable 2.04 for Perl 5.005_03 on win32 without much trouble, that would be my easiest option, and I'd be very appreciative. This is what happens when I try. Any ideas?


    C:\Storable-2.04>perl Makefile.pl Warning: prerequisite Test::More 0.41 not found at (eval 1) line 220. Usage: xsubpp [-v] [-C++] [-except] [-prototypes] [-noversioncheck] [- +nolinenumb ers] [-s pattern] [-typemap typemap]... file.xs Writing Makefile for Storable C:\Storable-2.04>nmake Microsoft (R) Program Maintenance Utility Version 1.50 Copyright (c) Microsoft Corp 1988-94. All rights reserved. mkdir blib mkdir blib\lib mkdir blib\arch mkdir blib\arch\auto mkdir blib\arch\auto\Storable mkdir blib\lib\auto mkdir blib\lib\auto\Storable cp Storable.pm blib\lib\Storable.pm AutoSplitting blib\lib\Storable.pm (blib\lib\auto/Storable) C:\Perl\bin\perl.exe -IC:\Perl\lib -IC:\Perl\lib C:\Perl\lib\E +xtUtils/xs ubpp -typemap C:\Perl\lib\ExtUtils\typemap Storable.xs >xstmp.c && C: +\Perl\bin\ perl.exe -IC:\Perl\lib -IC:\Perl\lib -MExtUtils::Command -e mv xstmp.c + Storable. c Usage: xsubpp [-v] [-C++] [-except] [-prototypes] [-noversioncheck] [- +nolinenumb ers] [-s pattern] [-typemap typemap]... file.xs NMAKE : fatal error U1077: 'C:\PERL\BIN\PERL.EXE' : return code '0xff' Stop.