File Coverage

blib/lib/Device/Velleman/K8055/Server.pm
Criterion Covered Total %
statement 17 19 89.4
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Device::Velleman::K8055::Server;
2 1     1   37210 use strict;
  1         2  
  1         39  
3              
4             BEGIN {
5 1     1   5 use Exporter ();
  1         1  
  1         19  
6 1     1   4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %share %server $maxclientnum $clientnum $ipc);
  1         6  
  1         205  
7 1     1   2 $VERSION = '0.03';
8 1         17 @ISA = qw(Exporter);
9             #Give a hoot don't pollute, do not export more than needed by default
10 1         2 @EXPORT = qw();
11 1         2 @EXPORT_OK = qw();
12 1         1 %EXPORT_TAGS = ();
13            
14 1         23 $SIG{INT} = 'Device::Velleman::K8055::Server::cleanup';
15 1         32 $SIG{KILL} = 'Device::Velleman::K8055::Server::cleanup';
16            
17             }
18              
19 1     1   397 use IPC::ShareLite qw( :lock );
  0            
  0            
20             use Tie::ShareLite qw( :lock );
21             use Time::HiRes qw(usleep);
22             use Data::Dumper;
23             use Device::Velleman::K8055::libk8055;
24              
25              
26             sub new
27             {
28             my ($class, %parameters) = @_;
29              
30             my $self={ 'error' => undef,
31             'data' => undef,
32             maxclientum => 0,
33             share => undef,
34             };
35            
36            
37             bless( $self, $class);
38            
39             $clientnum = IPC::ShareLite->new(
40             -key => 8055,
41             -create => 'yes',
42             -destroy => 'yes',
43             -exclusive => 'no'
44             ) or die $!;
45            
46             $clientnum->store("0");
47              
48             die ("K8055 OpenDevice failed") unless (OpenDevice($port) == 0);
49              
50            
51            
52             $ipc = tie %server, 'Tie::ShareLite', -key => 8056,
53             -mode => 0666,
54             -create => 'yes',
55             -destroy => 'no'
56             or die("Could not tie to shared memory: $!");
57              
58             ClearAllDigital();
59            
60              
61              
62             return $self
63            
64            
65             }
66              
67              
68             sub create_segment($ $) {
69            
70             my $self = shift;
71             my $clientno = shift;
72            
73             $self->{share}->{$clientno} = IPC::ShareLite->new(
74             -key => 8057 + $clientno,
75             -create => 'yes',
76             -destroy => 'yes',
77             -exclusive => 'no'
78             ) or die $!;
79            
80             }
81              
82              
83              
84              
85              
86             sub run {
87            
88             my $self = shift;
89            
90            
91            
92             while( 1 == 1) {
93            
94             check_for_client($self);
95            
96            
97             my $cmd="";
98             my $str="";
99             my $clientno="";
100             my $client;
101             my $share=$self->{share};
102            
103            
104             foreach $client (sort keys %$share ) {
105              
106             my @data = split(/:/, $share->{$client}->fetch );
107             $fetch=$data[0];
108            
109             if( !($fetch eq "" or $fetch eq "OK" ) ) {
110            
111             $share->{$client}->lock( LOCK_EX );
112             if( $fetch ne "DIE" ) {
113             $str = $share->{$client}->fetch;
114             my @data = split(/:/,$str);
115             my $cmd = shift @data;
116             print $cmd . "(" . $data[0], ")" . "\n";
117             $retval = &$cmd(@data);
118             $share->{$client}->store("OK:$retval");
119             $share->{$client}->unlock();
120             } else {
121             disconnect($self, $client);
122             }
123            
124              
125             }
126             }
127             usleep 5000;
128             }
129             }
130              
131              
132              
133             sub check_for_client ($) {
134            
135             my $self = shift;
136            
137             my $share = $self->{share};
138            
139             if( $clientnum->fetch > $maxclientnum ) {
140             $maxclientnum = $clientnum->fetch;
141            
142             create_segment($self,$maxclientnum-1);
143            
144             print "Clientno $maxclientnum attached with key->" . $self->{share}->{$maxclientnum-1}->key . ". \n";
145            
146            
147             }
148            
149             }
150              
151              
152             sub cleanup {
153             my $self = shift;
154             my $share = $self;
155             print "Cleaning up Shared Memory\n";
156             $clientnum="";
157             $ipc="";
158             $server="";
159            
160             foreach my $client ( sort keys %$share ) {
161             $self->{share}->{$client}="";
162             }
163             exit(1);
164             }
165              
166              
167             sub disconnect {
168            
169             my $self = shift;
170             my $client = shift;
171            
172             print "Client $client disconnected.\n";
173             $self->{share}->{$client}->destroy();
174             delete $self->{share}->{$client};
175            
176             }
177              
178             ############################################################################
179             #
180             #
181             #
182             ############################################################################
183              
184              
185              
186             =head1 NAME
187              
188             Device::Velleman::K8055::Server - IPCS Server for the K8055 Device
189              
190             =head1 SYNOPSIS
191              
192             use Device::Velleman::K8055::Server;
193            
194             my $server = Device::Velleman::K8055::Server->new();
195              
196              
197             =head1 DESCRIPTION
198              
199             Sets up a server that handles all communication with the K8055 device. Communicates with clients through shared memory.
200              
201             =head1 USAGE
202              
203             Example of a daemon that initiates the server:
204              
205             use Device::Velleman::K8055::Server;
206             use Proc::Daemon;
207             use Tie::Hash;
208            
209             $SIG{HUP} = 'shutdown';
210            
211            
212             foreach my $argnum (0 .. $#ARGV) {
213            
214             if( $ARGV[$argnum] eq '--debug' ) {
215             $debug=1;
216             }
217             if( $ARGV[$argnum] eq '--nodaemon' ) {
218             $nodaemon=1;
219             }
220            
221             if( $ARGV[$argnum] eq '--server' ) {
222             $server=1;
223             }
224            
225             }
226            
227            
228             if($server) {
229             print "Running Server\n";
230             server();
231             }
232            
233            
234             sub server {
235             #Run as Daemon unless -nodaemon passed.
236             unless( $nodaemon ) {
237             print "Running as daemon.\n";
238             Proc::Daemon::Init;
239             }
240             my $server = K8055::Server->new();
241             $server->run;
242             }
243            
244            
245            
246             sub shutdown {
247             $server->cleanup();
248             exit;
249             }
250              
251              
252             =head1 BUGS
253              
254             Many.
255              
256             =head1 SUPPORT
257              
258              
259              
260             =head1 AUTHOR
261              
262             David Peters
263             CPAN ID: DAVIDP
264             davidp@electronf.com
265             http://www.electronf.com
266              
267             =head1 COPYRIGHT
268              
269             This program is free software; you can redistribute
270             it and/or modify it under the same terms as Perl itself.
271              
272             The full text of the license can be found in the
273             LICENSE file included with this module.
274              
275              
276             =head1 SEE ALSO
277              
278             Device::Velleman::K8055::Client, Device::Velleman::libk8055, perl(1).
279              
280             =cut
281              
282             #################### main pod documentation end ###################
283              
284              
285             1;
286              
287