Author: spadkins
Date: Fri Feb 22 12:49:49 2008
New Revision: 10820
Added:
p5ee/trunk/App-Context/lib/App/SharedDatastore/
p5ee/trunk/App-Context/t/SharedDatastore.t (contents, props changed)
Modified:
p5ee/trunk/App-Context/CHANGES
p5ee/trunk/App-Context/lib/App/SharedDatastore.pm
Log:
add new service, SharedDatastore
Modified: p5ee/trunk/App-Context/CHANGES
==============================================================================
--- p5ee/trunk/App-Context/CHANGES (original)
+++ p5ee/trunk/App-Context/CHANGES Fri Feb 22 12:49:49 2008
@@ -2,6 +2,15 @@
# CHANGE LOG
#########################################
+VERSION 0.966 (unreleased)
+ o add SharedDatastore as a useful service (with a Repository-based
implementation)
+ o improved support for "temporary" services (named "temporary" or with the
{temporary} arg)
+ (a "temporary service" is akin to a stateless session bean in Java)
+ o add support for including/overlaying additional config files based on
values present in
+ the %$options hash or when a particular named service is instantiated
+ o App::Context::POE::Server
+ o App::Context::POE::ClusterController, App::Context::POE::ClusterNode
+
VERSION 0.965
x add UI timing log, activated by "app.Context.timer" option
Modified: p5ee/trunk/App-Context/lib/App/SharedDatastore.pm
==============================================================================
--- p5ee/trunk/App-Context/lib/App/SharedDatastore.pm (original)
+++ p5ee/trunk/App-Context/lib/App/SharedDatastore.pm Fri Feb 22 12:49:49 2008
@@ -12,6 +12,11 @@
use strict;
+use Storable qw(nfreeze thaw);
+use Digest::SHA qw(sha1_hex);
+
+$Storable::canonical = 1; # this will cause hashes to be serialized the same
way every time
+
=head1 NAME
App::SharedDatastore - Interface for sharing data between processes
@@ -75,9 +80,6 @@
implementations than an MLDBM (MLDBM is one of the implementations).
It also does not support the "tie" interface.
- * Throws: App::Exception::SharedDatastore
- * Since: 0.01
-
=cut
#############################################################################
@@ -100,6 +102,27 @@
=cut
#############################################################################
+# _init()
+#############################################################################
+
+=head2 _init()
+
+=cut
+
+sub _init {
+ &App::sub_entry if ($App::trace);
+ my ($self) = @_;
+ $self->{data} = {};
+ if ($self->{compress}) {
+ require Compress::Zlib;
+ }
+ if ($self->{base64}) {
+ App->use("MIME::Base64");
+ }
+ &App::sub_exit() if ($App::trace);
+}
+
+#############################################################################
# PUBLIC METHODS
#############################################################################
@@ -108,103 +131,236 @@
=cut
#############################################################################
+# set()
+#############################################################################
+
+=head2 set()
+
+ * Signature: $sds->set($key, $value);
+ * Signature: $sds->set($key, $value, $options);
+ * Param: $key scalar
+ * Param: $value scalar
+ * Param: $options HASH (optional)
+ * Return: void
+
+ $sds->set($key,$value);
+ $options = {
+ info_columns => [ "col1", "col2" ],
+ info_values => [ "value1", "value2" ],
+ };
+ $sds->set($key, $value, $options);
+
+=cut
+
+sub set {
+ &App::sub_entry if ($App::trace);
+ my ($self, $key, $value, $options) = @_;
+ $self->{data}{$key} = $value;
+ &App::sub_exit() if ($App::trace);
+}
+
+#############################################################################
# get()
#############################################################################
=head2 get()
* Signature: $value = $sds->get($key);
- * Param: $key string
- * Return: $value anything
- * Throws: App::Exception::SharedDatastore
- * Since: 0.01
+ * Param: $key scalar
+ * Return: $value scalar
- Sample Usage:
-
- $context = App->context();
- $sds = $context->service("SharedDatastore");
- $hash = $sds->get("user.spadkins");
- print %$hash, "\n";
+ $value = $sds->get($key);
=cut
sub get {
+ &App::sub_entry if ($App::trace);
my ($self, $key) = @_;
- return($self->{$key}); #dummy implementation
+ my $value = $self->{data}{$key};
+ &App::sub_exit($value) if ($App::trace);
+ return($value);
}
#############################################################################
-# set()
+# set_ref()
#############################################################################
-=head2 set()
+=head2 set_ref()
- * Signature: $value = $sds->set($key,$value);
- * Param: $key string
- * Param: $value anything
+ * Signature: $sds->set_ref($keyref,$valueref);
+ * Signature: $sds->set_ref($keyref,$valueref,$options);
+ * Param: $keyref anything (ref or scalar)
+ * Param: $valueref anything (ref or scalar)
+ * Param: $options HASH (optional)
* Return: void
- * Throws: App::Exception::SharedDatastore
- * Since: 0.01
- Sample Usage:
+ $sds->set_ref($keyref, $valueref);
+ $options = {
+ info_columns => [ "col1", "col2" ],
+ info_values => [ "value1", "value2" ],
+ };
+ $sds->set_ref($keyref, $valueref, $options);
- $context = App->context();
- $sds = $context->service("SharedDatastore");
- $hash = $sds->set("user.spadkins");
- print %$hash, "\n";
+=cut
+
+sub set_ref {
+ &App::sub_entry if ($App::trace);
+ my ($self, $keyref, $valueref, $options) = @_;
+ my $hashkey = $self->hashkey($keyref);
+ my $blob = $self->serialize($valueref);
+ $self->set($hashkey, $blob, $options);
+ &App::sub_exit() if ($App::trace);
+}
+
+#############################################################################
+# get_ref()
+#############################################################################
+
+=head2 get_ref()
+
+ * Signature: $valueref = $sds->get_ref($keyref);
+ * Param: $keyref anything (ref or scalar)
+ * Return: $valueref anything (ref or scalar)
+
+ $valueref = $sds->get_ref($keyref);
=cut
-sub set {
- my ($self, $key, $value) = @_;
- $self->{$key} = $value; #dummy implementation
+sub get_ref {
+ &App::sub_entry if ($App::trace);
+ my ($self, $keyref) = @_;
+ my $hashkey = $self->hashkey($keyref);
+ my $blob = $self->get($hashkey);
+ my $valueref = (defined $blob) ? $self->deserialize($blob) : undef;
+ &App::sub_exit($valueref) if ($App::trace);
+ return($valueref);
}
#############################################################################
-# PROTECTED METHODS
+# serialize()
#############################################################################
-=head1 Protected Methods:
+=head2 serialize()
+
+ * Signature: $blob = $sds->serialize($ref);
+ * Return: $ref any (ref)
+ * Return: $blob scalar (binary)
+
+ $blob = $sds->serialize($ref);
=cut
+sub serialize {
+ &App::sub_entry if ($App::trace);
+ my ($self, $ref) = @_;
+ my ($blob);
+ if (defined $ref) {
+ $blob = nfreeze($ref);
+ if ($self->{compress}) {
+ $blob = Compress::Zlib::memGzip($blob);
+ }
+ if ($self->{base64}) {
+ $blob = MIME::Base64::encode($blob);
+ }
+ }
+ else {
+ $blob = undef;
+ }
+ &App::sub_exit("<frozen-ref>") if ($App::trace);
+ return($blob);
+}
+
#############################################################################
-# Method: service_type()
+# deserialize()
#############################################################################
-=head2 service_type()
+=head2 deserialize()
-Returns 'SharedDatastore';
+ * Signature: $ref = $sds->deserialize($blob);
+ * Param: $blob scalar (binary)
+ * Return: $ref any (ref)
+
+
+ $ref = $sds->deserialize($blob);
- * Signature: $service_type = App::SharedDatastore->service_type();
- * Param: void
- * Return: $service_type string
- * Since: 0.01
+=cut
+
+sub deserialize {
+ &App::sub_entry if ($App::trace);
+ my ($self, $blob) = @_;
+ my ($ref);
+ if (defined $blob) {
+ if ($self->{base64}) {
+ $blob = MIME::Base64::decode($blob);
+ }
+ if ($self->{compress}) {
+ $blob = Compress::Zlib::memGunzip($blob);
+ }
+ $ref = thaw($blob);
+ }
+ else {
+ $ref = undef;
+ }
+ &App::sub_exit($ref) if ($App::trace);
+ return($ref);
+}
- $service_type = $sdata->service_type();
+#############################################################################
+# hashkey()
+#############################################################################
+
+=head2 hashkey()
+
+ * Signature: $hashkey = $sds->hashkey($keyref);
+ * Return: $keyref any (ref or scalar)
+ * Return: $hashkey scalar
+
+ $hashkey = $sds->deserialize($keyref);
=cut
-sub service_type () { 'SharedDatastore'; }
+sub hashkey {
+ &App::sub_entry if ($App::trace);
+ my ($self, $keyref) = @_;
+ my ($hashkey);
+ if (ref($keyref)) {
+ $hashkey = sha1_hex(nfreeze($keyref));
+ }
+ elsif (length($keyref) == 40 && $keyref =~ /^[a-f0-9]+$/) {
+ $hashkey = $keyref;
+ }
+ else {
+ $hashkey = sha1_hex($keyref);
+ }
+ &App::sub_exit($hashkey) if ($App::trace);
+ return($hashkey);
+}
#############################################################################
-# Method: _serialize()
+# PROTECTED METHODS
#############################################################################
-=head2 _serialize()
+=head1 Protected Methods:
- * Signature: $blob = $self->_serialize($ref);
- * Param: $ref any
- * Return: $blob scalar
- * Since: 0.01
+=cut
- $blob = $self->_serialize($ref);
+#############################################################################
+# Method: service_type()
+#############################################################################
+
+=head2 service_type()
+
+Returns "SharedDatastore";
+
+ * Signature: $service_type = App::SharedDatastore->service_type();
+ * Param: void
+ * Return: $service_type string
+
+ $service_type = $sds->service_type();
=cut
-sub _serialize {
- my ($self, $ref) = @_;
-}
+sub service_type () { "SharedDatastore"; }
=head1 ACKNOWLEDGEMENTS
Added: p5ee/trunk/App-Context/t/SharedDatastore.t
==============================================================================
--- (empty file)
+++ p5ee/trunk/App-Context/t/SharedDatastore.t Fri Feb 22 12:49:49 2008
@@ -0,0 +1,95 @@
+#!/usr/local/bin/perl -w
+
+use strict;
+
+use Test::More qw(no_plan);
+use lib "lib";
+use lib "../lib";
+
+BEGIN {
+ use_ok("App");
+}
+
+my $context = App->context(
+ conf_file => "",
+ conf => {
+ SharedDatastore => {
+ simple => {
+ class => "App::SharedDatastore",
+ },
+ compress => {
+ class => "App::SharedDatastore",
+ compress => 1,
+ },
+ base64 => {
+ class => "App::SharedDatastore",
+ base64 => 1,
+ },
+ compress_base64 => {
+ class => "App::SharedDatastore",
+ compress => 1,
+ base64 => 1,
+ },
+ },
+ },
+);
+
+{
+ my ($sds, $key, $value, $keyref, $valueref, $valueref2, $hashkey,
$serialized_value);
+
+ foreach my $name ("default", "simple", "compress", "base64",
"compress_base64") {
+ $sds = $context->service("SharedDatastore", $name);
+ ok(defined $sds, "[$name] constructor ok");
+
+ isa_ok($sds, "App::SharedDatastore", "[$name] right class");
+ is($sds->service_type(), "SharedDatastore", "[$name] right service
type");
+
+ my $dump = $sds->dump();
+ ok($dump =~ /^\$SharedDatastore__$name = /, "[$name] dump");
+
+ $sds->set("pi", 3.1416);
+ $value = $sds->get("pi");
+ is($value, 3.1416, "[$name] set()/get() works (for pi=$value)");
+
+ $keyref = [ "person",
+ { "age.ge" => 21, last_name => "Adkins" },
+ [ "person_id", "last_name", "first_name", "age", "eye_color" ],
+ { numrows => 20, cache => {}, },
+ ];
+ $valueref = [
+ [ 1, "Adkins", "Stephen", 40, "Blue", ],
+ [ 2, "Adkins", "Susan (Little)", 40, "Brown", ],
+ [ 3, "Adkins", "Bill", 43, "Brown", ],
+ [ 4, "Adkins", "Susan", 44, "Brown", ],
+ [ 5, "Adkins", "Marybeth", 47, "Blue", ],
+ ];
+
+ $sds->set_ref($keyref, $valueref);
+ $valueref2 = $sds->get_ref($keyref);
+ is_deeply($valueref, $valueref2, "[$name] set_ref()/get_ref() works");
+
+ $hashkey = $sds->hashkey($keyref);
+ $valueref2 = $sds->get_ref($hashkey);
+ is_deeply($valueref, $valueref2, "[$name] set_ref()/get_ref(hashkey)
works (hashkey=$hashkey)");
+
+ $serialized_value = $sds->serialize($valueref);
+ $value = $sds->get($hashkey);
+ is($value, $serialized_value, "[$name] set_ref()/get(hashkey) works");
+
+ $valueref2 = $sds->deserialize($serialized_value);
+ is_deeply($valueref, $valueref2, "[$name] serialize()/deserialize()
works");
+
+ $value = $sds->get("foo");
+ is($value, undef, "[$name] get(foo) is undef");
+
+ $valueref2 = $sds->get_ref("foo");
+ is($valueref2, undef, "[$name] get_ref(foo) is undef");
+
+ $sds->set_ref("foo", undef);
+ $value = $sds->get_ref("foo");
+ is($value, undef, "[$name] get_ref(foo) is undef after set to undef");
+ }
+}
+
+exit 0;
+