1 package Bcd
::Clients
::Listener
;
3 # This file is part of the breadcrumbs daemon (bcd).
4 # Copyright (C) 2007 Pasqualino Ferrentino
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 # Contact: lino.ferrentino@yahoo.it (in Italian, English or German).
23 #this file models a listener in our program.
24 #A listener is simply a thread
26 # this file has been possible thanks to ideas from
27 # http://www.perlmonks.org/?node_id=550235
28 # I thereby thanks the BrowserUk user
36 #use commands::CommandFactory;
37 use constant EOL
=> "\015\012";
39 use Bcd
::Data
::StatementsStash
;
41 use Log
::Log4perl
qw(:easy);
42 Log
::Log4perl
->easy_init($INFO);
44 my $TEST_DATABASE : shared
= 0;
46 sub use_test_database
{
53 my ($class, $script, $queue_files_to_delete) = @_;
58 bless ($self, $class);
60 my $queue = new Thread
::Queue
;
61 $self->{"q_streams"} = &share
($queue);
63 #this is the number of the serving clients
64 $self->{num_of_serving_clients
} = 0;
65 $self->{script
} = $script;
67 my $thread = threads
->new(\
&_listener_thread
, $self, $queue_files_to_delete);
73 #this is the thread of the listener... It is run forever
75 my ($self, $queue_files_to_delete) = @_;
77 #Ok, I create here the stash...
78 my $stash = Bcd
::Data
::StatementsStash
->new($TEST_DATABASE);
82 #ok, something happened
83 my $client_to_serve = $self->{"q_streams"}->dequeue();
87 $self->{num_of_serving_clients
} ++;
90 #print "OK... received $client_to_serve to serve\n";
91 open my $socket, "+<&=" . $client_to_serve or die $!;
93 if ($self->{script
} == 1){
94 my @time = localtime();
95 my $year = $time[5] + 1900;
96 my $month = $time[4] + 1;
97 my $name = "/tmp/${year}_${month}_$time[3]_$time[2]_$time[1]_$time[0]_bc_script";
98 open CMD_SCRIPT
, "> $name" or die "cannot open file $name";
101 local $/ = "\015\012";
102 $socket->autoflush(1);
104 #${$self->{"am_I_busy"}} = 1;
106 print $socket ">>>> ready for commands <<<<" . EOL
;
112 chomp; #the first line is the command's name
114 if ($self->{script
} == 1){
117 #this is only an "horrible hack", because the file is really never quit,
118 #as the web site does not quit the socket... So in every case I have a backdoor
119 #to force the flush of the file and have a meaningful script.
120 CMD_SCRIPT
->flush() if ($_ eq "an_get_summary");
122 print CMD_SCRIPT
"\n#### command $index_cmd \n";
123 print CMD_SCRIPT
$_ . "\n";
132 my $current_command = Bcd
::Data
::Model
->instance()->get_command($_);
134 if (!$current_command){
135 print $socket "Unknown command: $_. Type quit to exit." . EOL
;
139 #ok, let's parse the command
140 $current_command->start_parsing_command();
146 if ($self->{script
} == 1){
148 print CMD_SCRIPT
$_ . "\n";
151 #is the client transmission finished?
153 #ok, feed the command
155 #the line starts with "eot" but not finish with it, remove the eot
158 $current_command->parse_line($_);
161 last; #exit the loop, the command has finished
165 $current_command->eot();
167 #ok, now the command is prepared
169 #Bcd::Data::Model->instance()->execute_this_command($current_command);
171 #I should wait for the command execution...
172 #$current_command->wait_for_execution();
175 #####################################################################
176 ## the command is executed here...
177 get_logger
()->info($current_command->{id_cmd
}, " ",
178 $current_command->get_name(),
179 $current_command->get_parameters_for_logging());
180 $current_command->exec($stash);
182 my $output = $current_command->get_output();
184 my $dumped = Dumper
($output);
185 #ok, now I have the dumped object
186 $dumped =~ s/\012/\015\012/sg;
187 $dumped =~ s/^(\.?)/$1$1/sg; #also at the start of the string...
188 #$dumped =~ s/^(eot)/$1$1/sg; #also at the start of the string...
189 $dumped =~ s/\015?\012(\.?)/\015\012$1$1/sg;
190 #$dumped =~ s/\015?\012(eot)/\015\012$1$1/sg;
193 # foreach(@{$output}){
194 # #if the output starts with "eot" add another eot
198 # print $socket $_ . EOL;
200 print $socket $dumped;
201 print $socket "." . EOL
; #end of transmission
203 #the command is no more necessary...
204 #$current_command->finish();
208 print $socket "bye..." . EOL
;
210 close CMD_SCRIPT
if $self->{script
};
211 close $socket or print ">>>>>>>>>>>>> help : $!";
214 #this should be closed...
215 $queue_files_to_delete->enqueue($client_to_serve);
219 $self->{num_of_serving_clients
} --;
226 sub try_to_serve_this_client
{
227 my ($self, $client, $files_to_delete) = @_;
229 #let's lock the object
232 #ok, I should try to see the free state
234 my $num_of_serving_clients = $self->{num_of_serving_clients
};
236 if ($num_of_serving_clients != 0){
241 $files_to_delete->{fileno $client} = $client;
242 $self->{"q_streams"}->enqueue(fileno $client);