http://www.perlmonks.org?node_id=177272

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

Basically my idea was to maintain state using 2 things. On the server side i have an object, with appropiate data stored in it and functions and so forth, and a database. On the client side i have a unique 'session id', possibly a md-5 checksum or something highly random of that nature. When i first get a request, i would generate my object, generate a md-5 sum, some how store the md-5 sum client side, possibly via cookie, or maybe hidden input fields, or something of that nature, then use the Storable's freeze() method to store the object in my database, using the md-5 sum as the key. Then on subsequent requests, i can quickly do a select from the database, and use the thaw() method to restore my object, then go on using the object for my purposes.

Now, my questions.
  1. Does anyone see any major flaw in this?
  2. How could i get Storable to read from a database, as opposed to a file
  3. And does anyone know how i could get Storable working on my win32 box, seeing as all i could find is the source, and i have not had much luck getting the .xs parts of the module to compile?

Replies are listed 'Best First'.
Re: Maintaining state through storable.pm?
by perrin (Chancellor) on Jun 26, 2002 at 03:33 UTC
    Did you know that this is exactly what the Apache::Session module does? All you have to do is store the key on the client side. Don't be put off by the name: it has nothing to do with Apache or mod_perl.

    To your specific questions, this is a good way to do it but don't put much data in the serialized object or it will start to get slow. You should only put things like keys into other tables in there (shopping cart ID, user ID). You don't need to get Storable to read from the database. You just give it a scalar containing serialized data that you fetched from the database. Storable is available from ActiveState's PPM system and I think they ship it with their distribution. There are other pre-built Perl distros for Win32 that have it, like the one Randy Kobes builds. Storable will be part of the standard library starting in perl 5.8.

Re: Maintaining state through storable.pm?
by crazyinsomniac (Prior) on Jun 26, 2002 at 03:35 UTC
Re: Maintaining state through storable.pm?
by djantzen (Priest) on Jun 26, 2002 at 03:41 UTC
    I'm using Storable against an Oracle DB with good success. It takes some finagling but it works reliably and it's surprisingly fast (in fact we're using it as a caching mechanism on our Web server). Last I checked, DBD::Oracle didn't support binary large objects, or BLOBS, only characters (CLOBS). So, we have to turn our object into hex and write it out to the table.
    #Freeze the object my $data = eval { unpack ('h*', Storable::nfreeze($object))} ; # ORACLE SPECIFIC # create a hash containing specifying to Oracle what # sort of data it will need to store. 112 is the value # for a CLOB, 113 is the value for a BLOB. # FIXME: make this a BLOB when DBD::Oracle supports that my %hash = (ora_types => 112, ora_field => 'data'); # END ORACLE # insert our values into the table my $query = "INSERT INTO $table (jobID, data) VALUES ('$jid','$data')" +; $db_handle->execute($query, \%hash); # To thaw (after retrieving from the DB) my $object = eval { Storable::thaw(pack('h*',$data)) }

    This may not be the best for your situation, especially since others have suggested off the shelf solutions that appear to address your needs, but this approach does work.

    Update: perrin++. I came up with this scheme in early '00, and at that time BLOBS weren't implemented, or at least not in the version of DBD::Oracle we were using. I guess now I can go back and fix the FIXME's :)

      Hmmm, DBD::Oracle has support for BLOB data. We used it that way at eToys two years ago. We used the bind_param call instead of passing the parameters to execute. You could also try using a LONG if you can't get BLOB to work.
      my %hash = (ora_types => 112, ora_field => 'data');
      Rather than using the less obvious 112, this may make the code a bit more self-documenting:
      use DBD::Oracle qw(:ora_types); ... my %hash = (ora_types => ORA_CLOB, ora_field => 'data');

      --Dave

Re: Maintaining state through storable.pm?
by Joost (Canon) on Jun 26, 2002 at 11:23 UTC
    1. Seems fine to me, except that there are some modules that do most of this already at CPAN: CGI::Session & Apache::Session

    3. If you can't get Storable to work, you might try Data::Dumper, which is in the standard distro.

    -- Joost downtime n. The period during which a system is error-free and immune from user input.
Re: Maintaining state through storable.pm?
by rcaputo (Chaplain) on Jun 27, 2002 at 06:03 UTC

    In case you intend to send frozen data between machines, here are two details I've run into. Both of these have caused silent and/or strangely located failures in the past.

    Use nfreeze(), not freeze(). Otherwise you may run into problems if both machines don't agree on a byte order.

    Data frozen with one version of Storable may not thaw properly with another. Be sure both ends are running identical versions.

    -- Rocco Caputo / poe.perl.org / poe.sf.net

Re: Maintaining state through storable.pm?
by Anonymous Monk on Jun 26, 2002 at 19:13 UTC
    To get Storale running you can simply go download the latest build from ActivePerl (its included by default).

    I use a very similar method, cept for extra security I also use the stuff from http://pajhome.org.uk/crypt/index.html to get the user submitted pwd across safely (I don't have SSL).

    I use BerkeleyDB for the DB backend && it goes something like this:
    $my_cool_db{'some_key'} = freeze({what=>'ever'}); my $var = thaw($my_cool_db{'some_key'});

Re: Maintaining state through storable.pm?
by BUU (Prior) on Jun 26, 2002 at 04:00 UTC
    Quick update on #3, Storable did come installed in my activestate distro, however ppm install /storable/i does not work. Nor does it tell me its already installed.