Creating and shutting down POE::Sessions

2011-05-18 Thread Gabor Szabo
Hi,

my baby steps in the land of POE:

I have tried to setup a small application that would listen on a TCP
port and get commands 'start' and 'stop',
When receiving start it should create a new POE::Session to count.
When receiving stop it should stop the counting and destroy that
POE::Session. It seems I managed to do it but I'd be glad to receive
comments about the code:

#!/usr/bin/perl
use warnings;
use strict;
use 5.010;

use POE qw(Component::Server::TCP);

my $port = 12345;
print "telnet to $port\n";

my $session_id;

POE::Component::Server::TCP->new(
  Port=> $port,
  ClientInput => \&client_input,
  ClientConnected => \&client_connected,
);

POE::Kernel->run();
exit;


sub counter {
#print "counter\n";
return if not $_[HEAP]{run};
$_[HEAP]{count}++;
#$_[HEAP]{client}->put("Count: $_[HEAP]");
print "Count: $_[HEAP]{count}\n";
$_[KERNEL]->delay('counter' => 1);
}

sub session_start {
print "session_start\n";
print "session kernel: $_[KERNEL]\n";
$_[HEAP]{count} = 0;
$_[HEAP]{run} = 1;
$_[KERNEL]->yield('counter');
print "after calling yield\n";
}
sub session_stop {
print "session_stop\n";
}

sub stop_session {
 $_[HEAP]{run} = 0;
}



sub client_input {
  my ($heap, $input) = @_[HEAP, ARG0];

  if ($input eq 'start') {
  $session_id = POE::Session->create(
inline_states => {
_start => \&session_start,
_stop  => \&session_stop,
counter  => \&counter,
stop_session  => \&stop_session,
}
  )->ID;
  print "kernel: $_[KERNEL]\n";
  print "SID: $session_id\n";

  } elsif ($input eq 'stop') {
  print "stop received\n";
  if ($session_id) {
  $_[KERNEL]->post( $_[KERNEL]->ID_id_to_session($session_id),
'stop_session' );
  $session_id = undef;
  }
  print "stop done\n";
  } else {
  $_[HEAP]{client}->put("Invalid command '$input'");
  }

  return;
}

sub client_connected {
print "connected\n";
$_[HEAP]{client}->put("type 'start' or 'stop':");
};



-- 
Gabor Szabo
http://szabgab.com/


Re: Creating and shutting down POE::Sessions

2011-05-18 Thread Rocco Caputo
On May 18, 2011, at 09:30, Gabor Szabo wrote:

> Hi,
> 
> my baby steps in the land of POE:
> 
> I have tried to setup a small application that would listen on a TCP
> port and get commands 'start' and 'stop',
> When receiving start it should create a new POE::Session to count.
> When receiving stop it should stop the counting and destroy that
> POE::Session. It seems I managed to do it but I'd be glad to receive
> comments about the code:


[code removed]

Hi, Gabor.  Please see the revised code below.  The major change was to 
eliminate the counting session.  They didn't seem necessary, and their presence 
just complicated things.

#!/usr/bin/perl

use warnings;
use strict;
use 5.010;

use POE qw(Component::Server::TCP);

my $port = 12345;
print "telnet to $port\n";

my $session_id;

POE::Component::Server::TCP->new(
  Port=> $port,
  ClientInput => \&client_input,
  ClientConnected => \&client_connected,

  # These event handlers are registered for each client connection.
  # Each client connection has its own session, heap, etc.
  InlineStates => {
count => \&client_count,
  },
);

POE::Kernel->run();
exit;

sub client_input {
  my ($kernel, $heap, $input) = @_[KERNEL, HEAP, ARG0];

  print "client input: $input\n";

  if ($input eq 'start') {
$heap->{counter} = 0;
$kernel->yield('count');
return;
  }

  if ($input eq 'stop') {
delete $heap->{counter};
return;
  }

  $heap->{client}->put("Invalid command '$input'");
  return;
}

sub client_connected {
  $_[HEAP]{client}->put("type 'start' or 'stop':");
}

sub client_count {
  my ($kernel, $heap) = @_[KERNEL, HEAP];

  # Deleted when the counter stops.
  return unless exists $heap->{counter};

  # Set when this connection is shutting down.
  return if $heap->{shutdown};

  print "Counter: ", ++$heap->{counter}, "\n";
  $kernel->delay(count => 1);
}


-- 
Rocco Caputo 



Re: Creating and shutting down POE::Sessions

2011-05-19 Thread Gabor Szabo
On Thu, May 19, 2011 at 5:28 AM, Rocco Caputo  wrote:
> On May 18, 2011, at 09:30, Gabor Szabo wrote:
>
>> Hi,
>>
>> my baby steps in the land of POE:
>>
>> I have tried to setup a small application that would listen on a TCP
>> port and get commands 'start' and 'stop',
>> When receiving start it should create a new POE::Session to count.
>> When receiving stop it should stop the counting and destroy that
>> POE::Session. It seems I managed to do it but I'd be glad to receive
>> comments about the code:
>
>
> [code removed]
>
> Hi, Gabor.  Please see the revised code below.  The major change was to 
> eliminate the counting session.  They didn't seem necessary, and their 
> presence just complicated things.
>

Hi Rocco,

thanks for your reply. That looks indeed more simple. Reading again
the documentation,
do I understand correctly that already the ClientConnected and
ClientInput are callbacks of
the individual, connection related POE::Session?


Further working on the application I am writing, I'll need to have
several counters
and keep the counters work even after the original requester disconnected.
Trying with one, in my example it worked as the counter Session was not related
to the connection.
I wonder if in your solution, can I tell the session to remain active
even after
the user disconnected? Can I also remove it from the concurrency counter?

Would in this case the separate POE::Session work better?

regards
   Gabor


Re: Creating and shutting down POE::Sessions

2011-05-21 Thread Rocco Caputo
On May 19, 2011, at 03:18, Gabor Szabo wrote:

> On Thu, May 19, 2011 at 5:28 AM, Rocco Caputo  wrote:
>> On May 18, 2011, at 09:30, Gabor Szabo wrote:
>> 
>>> I have tried to setup a small application that would listen on a TCP
>>> port and get commands 'start' and 'stop',
>>> When receiving start it should create a new POE::Session to count.
>>> When receiving stop it should stop the counting and destroy that
>>> POE::Session. It seems I managed to do it but I'd be glad to receive
>>> comments about the code:
>> 
>> [code removed]
>> 
>> Hi, Gabor.  Please see the revised code below.  The major change was to 
>> eliminate the counting session.  They didn't seem necessary, and their 
>> presence just complicated things.
> 
> thanks for your reply. That looks indeed more simple. Reading again
> the documentation,
> do I understand correctly that already the ClientConnected and
> ClientInput are callbacks of
> the individual, connection related POE::Session?

Yes, all the /^Client/ callbacks are for individual connection related 
POE::Session instances.

> Further working on the application I am writing, I'll need to have
> several counters
> and keep the counters work even after the original requester disconnected.
> Trying with one, in my example it worked as the counter Session was not 
> related
> to the connection.
> I wonder if in your solution, can I tell the session to remain active
> even after
> the user disconnected? Can I also remove it from the concurrency counter?
> 
> Would in this case the separate POE::Session work better?

Yes.  I assume your independent counters have names.  I've attached a revised 
design to account for multiple named timers.  Since the code's getting larger, 
I modularized it a bit, making it even larger still.  Sample output:

1) macbookpoe:~% nc localhost 12345
Type 'start', 'stop', or 'list':
list
No known counters.
start aaa
Starting counter aaa...
start bbb
Starting counter bbb...
start ccc
Starting counter ccc...
list
Known counters at Sun May 22 01:56:51 2011: aaa:30152, bbb:13406, ccc:3525
stop bbb
Stopping counter bbb...
list
Known counters at Sun May 22 01:56:54 2011: aaa:50326, ccc:23699
^C
1) macbookpoe:~% nc localhost 12345
Type 'start', 'stop', or 'list':
list
Known counters at Sun May 22 01:56:57 2011: aaa:70739, ccc:44112
^C

-- 
Rocco Caputo 

#!/usr/bin/perl

use warnings;
use strict;
use 5.010;

use POE qw(Component::Server::TCP);

{
  package Counter;

  use warnings;
  use strict;
  use POE;  # For KERNEL, HEAP, ARG0, etc.

  my %counter;

  # Spawn the Counter session.

  # There may be only one due to the scoping of %counter.
  #
  # A design incorporating multiple Counter sessions would imply each
  # had its own counter namespace.  I'd use $_[HEAP]{counter} in that
  # case.
  #
  # But for now I'm using %counter in closures to simplify the code.

  sub spawn {
POE::Session->create(
  inline_states => {
_start => sub {
  # The alias is sufficient to keep this session
  # around as long as other sessions exist.
  $_[KERNEL]->alias_set("counter");
},
count => sub {
  my ($kernel, $counter_name) = @_[KERNEL, ARG0];

  # The counter was deleted in stop_counter?
  # By returning here, we stop perpetuating the recursive
  # yield() that drives this counter.

  return unless exists $counter{$counter_name};

  print "Counter $counter_name = ", ++$counter{$counter_name}, "\n";

  # The yield() here perpetuates the counter.
  $kernel->yield( count => $counter_name );
},
start_counter => sub {
  my ($kernel, $counter_name) = @_[KERNEL, ARG0];

  # Don't start a counter that's already running.
  return if exists $counter{$counter_name};

  $counter{$counter_name} = 0;
  $kernel->yield( count => $counter_name );
},
stop_counter => sub {
  my ($kernel, $counter_name) = @_[KERNEL, ARG0];

  # Don't stop a counter that's not running.
  return unless exists $counter{$counter_name};

  # Deleting the counter stops it.
  delete $counter{$counter_name};
},
  },
);
  }

  # These subs that follow are plain class methods.
  #
  # I've put the POE callbacks into anonymous coderefs above to keep
  # them visually distinct from plain methods.  I often also use
  # prefixes like _poe_foo() to indicate private POE callbacks.

  sub start {
my ($class, $counter_name) = @_;

# start() passes a message from the client connection session to
# the counter session.  The counters run in a dedicated session
# separate from each connection, so connections can come and go
# independently from counters.

$poe_kernel->post( counter => start_counter => $counter_name );
  }

  sub stop {
my ($class, $counter_name) = @_;
delete $counter{$counter_name};
  }

  sub list {
return %counter;
  }
}

### Abstract t