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. | [reply] [Watch: Dir/Any] |
1. Kind of. Since you plan on only storing user objects, you ought to make sure that the objects are stored separate from any other objects (even if you don't got any now, a /users/ or /sessions/ directory ought to be appropriate). I'd personally go with File::Cache for easy session maintenance (expired objects get expunged automagically, merlyn had an article here, I got a CGI::App sample here).
2. Hmm, see the Storable documentation, all of it (there is freeze/thaw to do it from memory, meaning a scalar, which is what you're looking for, or should've been)
3. Hmm, can you say PPM my boy, can you (1.012 seems recent enough for me as well as 1.0.10, but in case you need 2.4 or whatever, i'll didtry'n'compile and put it on my ppm repository)?
| [reply] [Watch: Dir/Any] |
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 :)
| [reply] [Watch: Dir/Any] [d/l] |
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.
| [reply] [Watch: Dir/Any] |
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 | [reply] [Watch: Dir/Any] [d/l] [select] |
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.
| [reply] [Watch: Dir/Any] [d/l] |
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
| [reply] [Watch: Dir/Any] [d/l] [select] |
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'}); | [reply] [Watch: Dir/Any] |
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. | [reply] [Watch: Dir/Any] |