Re: Avoiding runtime Session collision
Rodney Rindels [EMAIL PROTECTED] wrote on 05/02/2005 04:43:23 PM: I'm sure this is just my brain not properly doing a literal join. But I'm confused about how to properly ask the kernel what state a session is in, ie. Does a Session Exist? If so What state is the Session in? Avoiding shutdown until a Session is in state x or y ? Currently I am using sigtraps and handlers to shutdown the kernel, but It would be nice to extend that logic out if any of the Sessions I define are not in a waiting state, or don't have any wheels attached. Handle all your signals and set a global $shutdown in the signal handlers. Then have your sessions periodically check $shutdown and act appropriately. From what I've assembled thusfar, I'm guessing I'll have to alias all my sessions so I can know who to ask the kernel about. Basically every minute I have to fire an event that initiaties other sessions if those sessions are supposed to fire at that time of day. I'm assuming I'll have to keep some runtime information in a global about who fired and when as I don't see a shared kernel area for this type of data. In short I can never have two sessions of the same type running at the same time and have to avoid runtime collisions, as well as some of our customers only allow a single connection per day. I'm not sure if I understand completely. But what is the session doing? I guess you could: my $session = $kernel-alias_resolve(mysession) || start_mysession; # but... I guess I'm wondering if you are having seperate sessions be psuedo events when instead you might want to have a session that can accept postings from your scheduler? In other words why the ambiguity about whether or not a session is active? Need more info here. A design concern I have is whether I'm going to have to keep my sessions around long term because of tracking their own behaviors as opposed as to like a shared kernel $_[HEAP] that could do that for me somehow I always think of any data structure outside of the event definitions (i.e. globals) as being something like the heap of the kernel? I don't think there is anything wrong with this if that's your concern. Last question about _start. I notice that when you define a session, its _start runs immediately, is there a way to initiate a Session at daemonize time and not actually have it fire until it _start gets explicitly called. Have your session's _start call something like $kernel-yield('daemon_init') and then define a daemon_init handler. I think that will run the first chance it gets after the kernel has started. Then put everything you want in that handler. Rod
Re: Fwd: Re: POE::Component::Client::DNS woes
Untested: spawn several several PoCo::Client::DNS aliases. You could either strictly round-robin your posting to the spawned resolvers in start_next_lookup. Or, if you really want to balance things out, keep up with how many queries each resolver is currently handling by incrementing some counter at the start of start_next_lookup and decrementing it in got_answer. Then choose a resolver accordingly (don't forget to randomly pick from resolvers that are available). - Lance Braswell - + 1 469 357 6112 Lari Huttunen [EMAIL PROTECTED] tu.netTo poe@perl.org 04/28/2005 01:45 cc PM Subject Fwd: Re: Please respond to POE::Component::Client::DNS woes [EMAIL PROTECTED] tu.net Oops, sorry forgot to CC: the list. -- Original Message -- Subject: Re: POE::Component::Client::DNS woes To: Mathieu Longtin [EMAIL PROTECTED] From:Lari Huttunen [EMAIL PROTECTED] Date:Thu, 28 Apr 2005 21:39:57 +0300 On 21:00:51 28/04/2005 Mathieu Longtin [EMAIL PROTECTED] wrote: Hum, if the first DNS servers works, why should it try the other ones? To even out the query load between the different servers, but yes I see your point. :) Which means that I will probably have implement some kind of a round-robin logic for the queries, maybe? I would like to use the exisiting modules but what I was looking for is distribution of the query load between many different nameservers. -- Sincerely, Lari Huttunen
Re: Anybody did this?
Also, be careful not to get the publish/subscribe thing confused with something like a strategy. Your insert, log, and email steps are not likely to be independent from each other. Publish/subscribe make me think in terms of some independence between different subscribers. Will Lowe [EMAIL PROTECTED] wrote on 04/20/2005 12:28:26 PM: In POE, is it possible to register multiple event handlers for a single event? sort of like publish/subscribe messaging. For example, suppose I have an order event, I'd like several handlers to be invoked: one to insert into db, one to log, one to send email, etc. I could send multiple events, but that's not as nice. Just have the one handler you register call the others? Via $kernel-yield() or direct foo(); calls? -- Will
Re: Syslog child on Windows
Also, if you don't need for the DBI stuff to be threaded in with the rest of your POE app, you can just initially create another Session that is a Queue. Then write each $msg that comes in from PoCo::Server::Syslog to the Queue. The Queue itself just sets an alarm to periodically process itself in a POE::Wheel::Run or you can just fork it. The child part would then handle the database connection and writing. I do this all the time and it works really well. - Lance Braswell - + 1 469 357 6112 David Davis [EMAIL PROTECTED] l.com To Jim [EMAIL PROTECTED] 03/31/2005 11:17 cc AMpoe@perl.org Subject Re: Syslog child on Windows Please respond to David Davis [EMAIL PROTECTED] l.com There are quite a few DBI components for POE. You could use one of those. I'm partial to mine, but you should judge for yourself. http://cpan.teknikill.net/?poe*dbi -- David Davis Perl Programmer http://teknikill.net/ $7.95 per month hosting WITH ssh access http://hosting.teknikill.net/ On Thu, 31 Mar 2005 11:41:28 -0500, Jim [EMAIL PROTECTED] wrote: I have a perl Syslog server setup on a windows box because it's connected to a RAID Array. I'm using POE as the Syslog server code and I'm storing the syslog data into a DB2 database. Here is what I currently have: use warnings; use strict; use POE; use POE::Component::Server::Syslog; use DBI; # library for performing database functions use DBD::DB2; use DBD::DB2::Constants; # use Mail::SendMail; POE::Component::Server::Syslog-spawn( BindAddress = '129.37.2.201', InputState = \client_input, ErrorState = \client_error, ); my $debug = 1; $poe_kernel-run(); ## sub client_input { # Get the syslog hash my $msg = $_[ARG0]; my $databaseHandle; my $connectFailureFlag = 0; my $search; my $sth; my $dbName = vpn; # Parse the data for DB entry $msg-{'msg'} =~ /^(.*?) (\d+)\/(\d+)\/(\d+) (\d+):(\d+):(\d+)\.(\d+) SEV=. (.*?)$/; if ($debug) { print Host: .$msg-{'host'}.\n; print Severity: .$msg-{'severity'}.\n; print Msg: .$msg-{'msg'}.\n; my $databaseHandle = DBI-connect(DBI:DB2:$dbName,x,xx) or $connectFailureFlag = 1; if ($connectFailureFlag == 1){ warn Unable to establish with DB2:$dbName due to $DBI::errstr\n; } elsif ($connectFailureFlag == 0){ # connected to DB $search = INSERT INTO VPN.SYSLOG_C3K (DATE_TIME, DEVICE, SEV, MSG) values('$4-$2-$3-$5.$6.$7.$8', '.$msg-{'host'}.', .$msg-{'severity'}., '$9'); $sth = $databaseHandle-prepare($search); # prepare the statement to read from the DB $sth-execute(); # execute the query $sth-finish; $databaseHandle-disconnect or warn Disconnection failed: $DBI::errstr\n; } print $2.$3.$4.$5.$6.$7.$8 $1 $9\n\n; } # if ($debug) } sub client_error { # Something went wrong with the syslog message # Figure out what to do, if anything, in this case later warn BAD MESSAGE: $_[ARG0]; } What I'd like to do is collect the syslog data into an array while having another process pull the data out of that array and put into the database. That way, I'm not creating database connections everytime I get a syslog message. Hopefully I'm clear in what I'm asking for. :-)
Re: Why can't I retrieve this POE session's options?
I was trying to be cute by inserting a Python reference whenever possible and it masked the real change I made ;). Sorry about that. The real change was using an option key name of 'myname' as opposed to 'MyName'. The hashref that is passed as the value of 'options' in POE::Session::create is imported as is, meaing you have a $self-[SE_OPTIONS]-{MyName} = 'Tim' in your session after create. However, every invocation of POE::Session::option _lower-cases_ the key name on both setting and getting. So your program initializes options with a 'MyName' but your subsequent: my $name = $_[SESSION]-option( 'MyName' ); in handler1 is looking for a 'myname' (lower-cased) option internally which isn't defined yet hence the uninitialized value in concat. error . Doing this: $_[SESSION]-option( 'MyName', 'Mud' ); sets a lower-case 'myname' option internally which is why it works for handler2. But like you have figured out you probably are wanting something else instead. It probably still needs to be fixed in POE::Session though. - Lance Braswell - + 1 469 357 6112 Tim Klein [EMAIL PROTECTED] 03/30/2005 06:44 PM To poe@perl.org cc Subject Re: Why can't I retrieve this POE session's options? You mean you can substitute 'Tim the Enchanter' for 'Tim' in my program, and it works for you? It doesn't for me; I get the very same output as with 'Tim'. Tim I think it's a bug. In POE::Session options are stored like so: $self-[SE_OPTIONS] = $params{+CREATE_OPTIONS} However the processing in POE::Session::option is done with my $flag = lc(shift) on both getting and setting. Using 'myname' = 'Tim the Enchanter' works for instance. - Lance Braswell - + 1 469 357 6112 I expected the following short program to print My name is Tim followed by My name is Mud. Instead, this is the output: My name is Use of uninitialized value in concatenation (.) or string at opt.pl line 25. My name is Mud Apparently, the 'MyName' option isn't getting registered properly during the creation of the session. But when I later set the same option using the option() command, it works fine. Can someone spot what I'm doing wrong, most likely in my create() call? It's probably something stupid, but I just can't see it. Thanks for any help! Tim #!/usr/bin/perl use warnings; use strict; use POE; POE::Session-create ( inline_states = { _start = \startup, event1 = \handler1, event2 = \handler2, }, options = { 'MyName' = 'Tim' }, ); POE::Kernel-run(); sub startup { $_[KERNEL]-yield('event1'); } sub handler1 { my $name = $_[SESSION]-option( 'MyName' ); print My name is $name\n; $_[KERNEL]-yield('event2'); } sub handler2 { $_[SESSION]-option( 'MyName', 'Mud' ); my $name = $_[SESSION]-option( 'MyName' ); print My name is $name\n; }
Re: Setting a variable in the heap
It seems there is a handy Started argument to PoCo::Client::TCP::new. You can also do effectively the same thing by establishing a closure around $site below in one or more of your PoCo::Client::TCP event handlers. The following is untested: use POE qw(Component::Client::TCP); foreach my $site ( qw/ site1 site2 site3 / ) { POE::Component::Client::TCP-new ( RemoteAddress = $site, RemotePort = 6789, #Started = sub { $_[HEAP]-{sitename} = $site; }, # could do it with a closure Started = sub { $_[HEAP]-{sitename} = $_[ARG0]; }, # not a closure Args = [ $site ], ServerInput = sub { my ( $kernel, $heap, $input ) = @_[ KERNEL, HEAP, ARG0 ]; my $sitename = $heap-{sitename}; # print got input from $site: $input\n; # a closure gets you the same thing print got input from $sitename: $input\n; }, ); } - Lance Braswell - + 1 469 357 6112 Jeff Konz [EMAIL PROTECTED] 09/09/2004 09:17 PM Please respond to Jeff Konz [EMAIL PROTECTED] To [EMAIL PROTECTED] cc Subject Setting a variable in the heap Hello, I am a new user of POE and I have a script that creates a connection to a tcp server and am processing the data coming from that server. I have 7 different servers that I run the script against. I would like to create a single POE script that does what I need. I know that I can set up individual sessions within the script to handle this. In order to process the data, my state needs to know what system the data comes from. The easiest way I see to do this is to have a variable in the sessions heap that is something like: heap-{sitename} = site1 So my question is two fold, first is this the proper syntax to do this and second if it is, where do I put this statment within the POE script( I.E. Within the new() construct of the POE::Component::Client::TCP or somewhere else)? I have read the docs that are available, but I can not find a reference to setting vars within the heap. Thanks for any help you can provide, Jeff
using a separate session to process multiple client inputs from Component::Server::TCP
First let me say that I think POE is awesome! It's been a mind-blowing couple of weeks trying to get my brain around it. I am rewriting a Network Monitoring system where the clients periodically connect to my server and send things. Right now I am using a simple accept and forking IO::Socket::INET server. The problem is that we are at the mercy of the clients and sometimes the clients hang or take a long time while sending data. Add to this that many clients may end up connecting at nearly the same time and you have a recipe for out of memory/cannot fork conditions. Some of this is due to other design problems. But I am doing a complete rewrite of the whole thing so I will fix those as well. So on the server I know I want to do something more robust and POE seems to encapsulate that already so that's what I am going to use. Basically my server would be getting an XML document from the client. I'll only process the data from the client after it disconnects. No need to answer back to it (at least not yet). I would also like to batch up the responses and process them with POE::Wheel::Run (because processing the queue involves a lot of slow running parsing of some XML and entering it into a database). So I am building up a queue and periodically processing it. The next step would be to take the entire queue, hand it of to POE::Wheel::Run, zero the queue, and keep moving. In my mind this is a Poe Man's pre-forking server. Here (below) is a skeleton of what I have so far to demonstrate this (but w/o the POE::Wheel::Run). Here are my questions: 1) Am I on the right track to have the Server and the queue processing in separate sessions where the Server posts to the queue's session? 2) Is there any way to high-water mark the queue so that it is processed immediately if reaching that mark? Or should I just be happy with periodically processing the queue as I have done below? 3) Am I using delay_set below in the way it was intended to be used? 4) Can anyone point me to examples of timing-out a client connection gracefully after a certain period of time. 5) Am I crazy? Thanks for reading, Lance #!/usr/bin/perl # after http://poe.perl.org/?POE_Cookbook/TCP_Servers use warnings; use strict; use POE qw(Component::Server::TCP); #sub MAX_QUEUE_SIZE { 3 } sub QUEUE_FLUSH_TIME { 10 } # in seconds to wait before flushing the input queue POE::Component::Server::TCP-new( Alias = server, Port = 11211, ClientInput = sub { my ( $session, $heap, $input ) = @_[ SESSION, HEAP, ARG0 ]; print Session , $session-ID(), got input: $input\n; $heap-{client_data} .= $input; $heap-{client}-put($input); }, ClientDisconnected = sub { my ( $kernel, $session, $heap ) = @_[ KERNEL, SESSION, HEAP ]; my $client_data = $heap-{client_data}; if ( defined( $client_data ) ) { $kernel-post( queue_handler = add_client_data = $client_data ); } else { print server didn't get back any client_data\n; } }, ); POE::Session-create( inline_states = { _start = sub { my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; $heap-{queue} = []; $kernel-alias_set(queue_handler); $kernel-delay_set(process_queue, QUEUE_FLUSH_TIME); }, add_client_data = sub { my ( $kernel, $heap, $client_data ) = @_[ KERNEL, HEAP, ARG0 ]; print queue_handler session got some client_data: $client_data\n; push( @{ $heap-{queue} }, $client_data ); # I would like to process the queue immediately if it reaches MAX_QUEUE_SIZE # but the following doesn't work. I know why but I don't know how to fix it. # Maybe I should just depend on periodic processing of the queue instead since # it's being done anyway #if ( ( scalar( @{ $heap-{queue} } ) = MAX_QUEUE_SIZE ) # ! $heap-{process_queue_posted} ) { # $kernel-yield(process_queue); # $heap-{process_queue_posted} = 1; #} }, process_queue = sub { my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; print time to process queue\n; # This would eventually use a POE::Wheel::Run here to process the whole queue while( @{$heap-{queue}} ) { my $client_data = shift( @{$heap-{queue}} ); print queue_handler session\'s process_queue event processed: $client_data\n; } # see comments above in add_client_data #$heap-{process_queue_posted} = 0; $kernel-delay_set(process_queue, QUEUE_FLUSH_TIME); } } ); $poe_kernel-run(); exit 0;