File Coverage

blib/lib/DBI/Gofer/Transport/Base.pm
Criterion Covered Total %
statement 52 78 66.6
branch 13 28 46.4
condition 8 27 29.6
subroutine 10 12 83.3
pod 0 2 0.0
total 83 147 56.4


line stmt bran cond sub pod time code
1             package DBI::Gofer::Transport::Base;
2              
3             # $Id: Base.pm 12536 2009-02-24 22:37:09Z Tim $
4             #
5             # Copyright (c) 2007, Tim Bunce, Ireland
6             #
7             # You may distribute under the terms of either the GNU General Public
8             # License or the Artistic License, as specified in the Perl README file.
9              
10 52     52   270 use strict;
  52         66  
  52         1563  
11 52     52   238 use warnings;
  52         70  
  52         1101  
12              
13 52     52   244 use DBI;
  52         56  
  52         1978  
14              
15 52     52   239 use base qw(DBI::Util::_accessor);
  52         66  
  52         3988  
16              
17 52     52   18294 use DBI::Gofer::Serializer::Storable;
  52         101  
  52         1172  
18 52     52   20229 use DBI::Gofer::Serializer::DataDumper;
  52         121  
  52         37213  
19              
20             our $VERSION = "0.012537";
21              
22             __PACKAGE__->mk_accessors(qw(
23             trace
24             keep_meta_frozen
25             serializer_obj
26             ));
27              
28              
29             # see also $ENV{DBI_GOFER_TRACE} in DBI::Gofer::Execute
30 0   0 0   0 sub _init_trace { (split(/=/,$ENV{DBI_GOFER_TRACE}||0))[0] }
31              
32              
33             sub new {
34 705     705 0 1116 my ($class, $args) = @_;
35 705   33     4511 $args->{trace} ||= $class->_init_trace;
36 705   33     6146 $args->{serializer_obj} ||= DBI::Gofer::Serializer::Storable->new();
37 705         2294 my $self = bless {}, $class;
38 705         5091 $self->$_( $args->{$_} ) for keys %$args;
39 705 50       2218 $self->trace_msg("$class->new({ @{[ %$args ]} })\n") if $self->trace;
  0         0  
40 705         3101 return $self;
41             }
42              
43             my $packet_header_text = "GoFER1:";
44             my $packet_header_regex = qr/^GoFER(\d+):/;
45              
46              
47             sub _freeze_data {
48 10589     10589   13536 my ($self, $data, $serializer, $skip_trace) = @_;
49 10589         10188 my $frozen = eval {
50 10589 50 66     29647 $self->_dump("freezing $self->{trace} ".ref($data), $data)
51             if !$skip_trace and $self->trace;
52              
53 10589         20816 local $data->{meta}; # don't include meta in serialization
54 10589   33     33784 $serializer ||= $self->{serializer_obj};
55 10589         27360 my ($data, $deserializer_class) = $serializer->serialize($data);
56              
57 10589         32710 $packet_header_text . $data;
58             };
59 10589 50       19154 if ($@) {
60 0         0 chomp $@;
61 0         0 die "Error freezing ".ref($data)." object: $@";
62             }
63              
64             # stash the frozen data into the data structure itself
65             # to make life easy for the client caching code in DBD::Gofer::Transport::Base
66 10589 100       27821 $data->{meta}{frozen} = $frozen if $self->keep_meta_frozen;
67              
68 10589         29696 return $frozen;
69             }
70             # public aliases used by subclasses
71             *freeze_request = \&_freeze_data;
72             *freeze_response = \&_freeze_data;
73              
74              
75             sub _thaw_data {
76 10575     10575   16709 my ($self, $frozen_data, $serializer, $skip_trace) = @_;
77 10575         9470 my $data;
78 10575         10607 eval {
79             # check for and extract our gofer header and the info it contains
80 10575 50       79131 (my $frozen = $frozen_data) =~ s/$packet_header_regex//o
81             or die "does not have gofer header\n";
82 10575         25080 my ($t_version) = $1;
83 10575   33     38655 $serializer ||= $self->{serializer_obj};
84 10575         26038 $data = $serializer->deserialize($frozen);
85 10575 50       338889 die ref($serializer)."->deserialize didn't return a reference"
86             unless ref $data;
87 10575         28048 $data->{_transport}{version} = $t_version;
88              
89 10575 100       25675 $data->{meta}{frozen} = $frozen_data if $self->keep_meta_frozen;
90             };
91 10575 50       18501 if ($@) {
92 0         0 chomp(my $err = $@);
93             # remove extra noise from Storable
94 0         0 $err =~ s{ at \S+?/Storable.pm \(autosplit into \S+?/Storable/thaw.al\) line \d+(, \S+ line \d+)?}{};
95 0         0 my $msg = sprintf "Error thawing: %s (data=%s)", $err, DBI::neat($frozen_data,50);
96 0         0 Carp::cluck("$msg, pid $$ stack trace follows:"); # XXX if $self->trace;
97 0         0 die $msg;
98             }
99 10575 50 66     32162 $self->_dump("thawing $self->{trace} ".ref($data), $data)
100             if !$skip_trace and $self->trace;
101              
102 10575         30024 return $data;
103             }
104             # public aliases used by subclasses
105             *thaw_request = \&_thaw_data;
106             *thaw_response = \&_thaw_data;
107              
108              
109             # this should probably live in the request and response classes
110             # and the tace level passed in
111             sub _dump {
112 0     0   0 my ($self, $label, $data) = @_;
113              
114             # don't dump the binary
115 0 0 0     0 local $data->{meta}{frozen} if $data->{meta} && $data->{meta}{frozen};
116              
117 0         0 my $trace_level = $self->trace;
118 0         0 my $summary;
119 0 0       0 if ($trace_level >= 4) {
    0          
120 0         0 require Data::Dumper;
121 0         0 local $Data::Dumper::Indent = 1;
122 0         0 local $Data::Dumper::Terse = 1;
123 0         0 local $Data::Dumper::Useqq = 0;
124 0         0 local $Data::Dumper::Sortkeys = 1;
125 0         0 local $Data::Dumper::Quotekeys = 0;
126 0         0 local $Data::Dumper::Deparse = 0;
127 0         0 local $Data::Dumper::Purity = 0;
128 0         0 $summary = Data::Dumper::Dumper($data);
129             }
130             elsif ($trace_level >= 2) {
131 0   0     0 $summary = eval { $data->summary_as_text } || $@ || "no summary available\n";
132             }
133             else {
134 0   0     0 $summary = eval { $data->outline_as_text."\n" } || $@ || "no summary available\n";
135             }
136 0         0 $self->trace_msg("$label: $summary");
137             }
138              
139              
140             sub trace_msg {
141 9006     9006 0 11987 my ($self, $msg, $min_level) = @_;
142 9006 50       18585 $min_level = 1 unless defined $min_level;
143             # transport trace level can override DBI's trace level
144 9006 50       18358 $min_level = 0 if $self->trace >= $min_level;
145 9006         37774 return DBI->trace_msg("gofer ".$msg, $min_level);
146             }
147              
148             1;
149              
150             =head1 NAME
151              
152             DBI::Gofer::Transport::Base - Base class for Gofer transports
153              
154             =head1 DESCRIPTION
155              
156             This is the base class for server-side Gofer transports.
157              
158             It's also the base class for the client-side base class L.
159              
160             This is an internal class.
161              
162             =head1 AUTHOR
163              
164             Tim Bunce, L
165              
166             =head1 LICENCE AND COPYRIGHT
167              
168             Copyright (c) 2007, Tim Bunce, Ireland. All rights reserved.
169              
170             This module is free software; you can redistribute it and/or
171             modify it under the same terms as Perl itself. See L.
172              
173             =cut
174