Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Handling asynchronous events with Perl

by njcodewarrior (Pilgrim)
on Jul 10, 2005 at 19:51 UTC ( #473783=perlquestion: print w/replies, xml ) Need Help??

njcodewarrior has asked for the wisdom of the Perl Monks concerning the following question:

I work for a operational ocean observatory and we have been deploying autonomous underwater vehicles (AUV) which patrol the world's oceans and periodically call in to a central server in our lab over a satellite communication link to transfer data files. I've been running a variety of scripts on my crontab at roughly 5 minute intervals to process this data and display it on the web; however, the AUV calls in about once every 6 hours, so the cronjob spacing is a bit of overkill, but required to minimize the time between file transfer and processing.

Each time the AUV calls in, a new log file is created and written to, so what I'd like to do is set up a kind of event handler that will watch the log directory and trigger a set of callbacks to perform a variety of tasks.

While I have not used them, I'm aware of the following to handle asynchronous events:

Event.pm
Event::Lib
POE

As a relative newbie to Perl, what I'd like are some suggestions that allow me to accomplish the following:

1. Get something up and running quickly.
2. The flexibility to expand once I become familiar with the module.

All suggestions appreciated.

UPDATE: Sorry, I was a bit unclear here and left something out:
1. We do have a number of AUVs that could be simultaneously deployed.
2. The AUV can be programmed to surface and call in at a number of preset intervals. Currently, we are using 6hrs as the interval, but this definetely can vary. For example, if the satellite link is down, the AUV is also programmed to call in when it gets a good link.

I should rephrase and say that I'm not sure when the AUVs will call in, which is what I mean by asynchronous.
The processing does NOT take more than 6hours, but, in the future, I'd like to have the ability to retask the AUV depending on the data that comes in. Since the satellite comm link can only occur when the glider is on the surface, the retasking needs to occur immediately when the AUV connects.

Also, the AUVs are deployed for upto 2 months at a time, so the application needs to run for the duration without interfering with other processes.
Sorry for the confusion.

Replies are listed 'Best First'.
Re: Handling asynchronous events with Perl
by BrowserUk (Patriarch) on Jul 11, 2005 at 00:14 UTC

    Your program could be as simple as:

    #! perl -slw use strict; use threads; my $FILEPATH = './AUV*.dat'; my $file; while( 1 ) { sleep( 1 ) until defined( $file = glob $FILEPATH ); async{ process( $file ) }->detach; } sub process { my $file = shift; return unless $file =~ m[AUV(\d+)\.dat$]; my $AUVNO = $1; eval "use AUV::$AUVNO"; warn "No processing module found for AUV no: $AUVNO" and return if + $@; AUVProcess( $file ); return; }

    This assumes that the inbound files are named AUVnnn.dat, with nnn representing each AUV.

    You then create a separate package to process each AUV's data, that exports a single entrypoint that takes the filename to process as it's only arguement. The modules would have a consistant naming AUV::nnn, and would look something like this:

    package AUV::123; use strict; our @ISA = 'Exporter'; our @EXPORT = 'AUVProcess'; sub AUVProcess{ my $file = shift; open DATA, '<', $file or warn "Couldn't open $file : $!\n"; ## Process data from file here print while <DATA>; close DATA; unlink $file; return; } print "AUV::123 loaded";

    All this does it print the data to the terminal for testing.

    This allows you to add and modify the processing modules without stopping the main dispather. The dispatcher will use negligable cpu while no files need processing. A file will be dispatched for processing within 1 second of it arrival. If a file arrives and it's module is unavailable, it will simply wait until the module becomes available, at which point it will be processed. The dispatcher should easily run unattended for mpnths without problems as the dispatcher uses minimal memory or processor and no memory growth. All the memory used to process the data is immediately freed back to the runtime for reuse when the thread terminates.

    Add error checking, logging etc. as required.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
Re: Handling asynchronous events with Perl
by Ultra (Hermit) on Jul 10, 2005 at 20:45 UTC

    I am a little bit biased, but I think POE is the way to go, especially when it comes to expand your application as you can use the POE::Components already out there.

    I guess the alternatives are simpler, but they haven't such great support.

    Update: you may find POE::Component::DirWatch useful.

    Dodge This!
Re: Handling asynchronous events with Perl
by perrin (Chancellor) on Jul 10, 2005 at 22:43 UTC
    What exactly is wrong with the approach you have now? Using a cron job is a pretty robust approach, since you don't have to worry about creating your own daemon that is reliable enough to run for months. I don't think any of the approaches discussed here will prevent you from needing to check if the directory has been updated, so it's really just a question of how often you check. If a 1 minute lag is acceptable, use cron and keep it simple.
      When the AUV surfaces and connects to the onshore server, it displays some basic information (ie: GPS position and some ocean measurements such as temperature, currents, etc.). The only real problem with using a cron is that I'd like to immediately begin parsing this information and (possibly) retask to the AUV to a new location or modify it's behavior some other way. While 1 minute might be acceptable, I'd really like to know as soon as the vehicle surfaces. I will definitely consider this, however....thanks for the suggestion.
Re: Handling asynchronous events with Perl
by BrowserUk (Patriarch) on Jul 10, 2005 at 20:21 UTC

    It's not clear to me from your description where the need for asynchronicity comes in?

    It sounds like all you need a script that runs in a loop, monitor a directory looking for a file to appear, and then process that file before going back to monitoring for ~ 6 hrs - processing time.

    Unless there are more that one AUV, or the processing could take more than 6 hours, there seems no need for anything complicated here?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
Re: Handling asynchronous events with Perl
by fmerges (Chaplain) on Jul 10, 2005 at 22:22 UTC

    Hi,

    As Ultra stated I also think that a good approach would be using POE

    I don't know if every AUV have one file associated, if it put the data into a database or whatever, but for the normal thinks, like asynchronus DBI connection, POE has components.

    If every AUV writes on a file, you can easily create a POE Session which use the POE::Wheel::FollowTail so that an Event is called everytime the file has a new line/record.

    Have some practise with POE, so if you have questions don't hesitate to get in touch, but first take a look at the webpage because there you find example code and also read the 2 documents on perl.com, results of searching here.

    Update: just read that it transfers files, so ::DirWatch would be a good solution; you can assign every AUV a directory where it upload its data and having POE Sessions that control each directory.

    Update: I'm agree with perrin's comment about cron and absolutely with KISS. Cron do a nice job and of course, if a 1 minute lag is not too long... take the simple option, but anyway you can make your daemon supervised, so when it exits it gets relaunched again, this is also simple.

    Regards,

    |fire| at irc.freenode.net
Re: Handling asynchronous events with Perl
by jhourcle (Prior) on Jul 11, 2005 at 01:50 UTC

    How is the file being transfered?

    One of the biggest problems in using cron for this sort of thing is in making sure that the file that you're reading from is complete -- this was discussed a few months ago in Combining Data Files

    If you can, the easiest thing to do is to piggyback something onto the data transfer process. (we have daemons listening for similar processes at my current job, so we can react as soon as a packet is complete, but we have requirements to get them processed and available for download within 5 minutes of receipt).

    Now, if you're using FTP or something similar, you don't actually need to hack the daemon directly -- you can have a process tail the log file, so it knows when something's come in.

Re: Handling asynchronous events with Perl
by zentara (Archbishop) on Jul 11, 2005 at 11:17 UTC
    In addition to using POE or threads, I would ask what is your "long-term-vision" for the monitoring program? Wouldn't you ultimately want a GUI to watch these things. The reason I say this, is that Tk, Gtk2, or Wx have "built-in event loops" to make this job easy, plus you can have a GUI to display "when and where" an AUV has surfaced, assign mouse menus to the icons you use, so you can adjust things like resurfacing times. Depending on how the files come in, you can setup individual "fileevents" to watch for changes to the filehandles which each AUV prints to, or you could just monitor a single file, and regex the input to detect which AUV it comes from.

    You could setup HoH (a hash of hashes) to track the AUV's, and with a menuing system, you could save changes to each AUV configuration, to be sent when a surface-event is detected.

    The only drawback to using a GUI, is that you need to run it on a machine running an X server, or Windows.


    I'm not really a human, but I play one on earth. flash japh
      Yes, this is exactly what I would like to be able to do. Currently, I'm using Matlab for data visualization and have created a GUI that tracks the progress of the AUV once deployed; however, it is limited to tracking the AUV using available data.

      My 'long-term-vision' is to have an application capable of visualizing position information and data from the vehicle as well as doing the things you describe.

      Where's a good place to start for building GUIs using Perl?

      Thanks.
        I would use Tk. You can read "perldoc Tk" then "perldoc Tk::UserGuide". You can ask questions here, google for sample code at groups.google.com, and ask questions in the friendly newsgroup, comp.lang.perl.tk

        I was thinking about your problem, and thought how nice it would be to actually make each AUV an object, then just make a big Tk canvas, put an gridded ocean map on it, and have little icons for each AUV object. You could have a little red indicator to blink when they are surfaced, and when submerged, plot their approximate position based on last readings, etc. You could work out a "coordinate translation" between GPS coordinates and your "gridded-ocean map". It sounds like a doable and fun project.

        Of course, as always, the devil is in the details, like error handling, restarting crashed servers, etc. You will probably need to store your AUV object data in a simple database, with backup, in case your monitoring computer crashes and needs to be rebuilt and restarted.

        I have posted a few examples which may "stimulate" ideas for you. Like this is a possible way to setup grid patterns -> Tk ImageMap-color-zones.

        And here is a nice little intro to how to make independent objects and display them on the screen. I call them bubbles. Anyways, don't get confused by the all the effects. My main purpose was to find a way to make alot of objects, and reuse them so as not ot get memory increases in a long running program. I also used Zinc, because it makes rotations and translations alot easier than the plain Canvas. But this could all be done on a plain Tk::Canvas.....you don't need fancy rotations, just translations, and the plain Canvas does them just fine. Also the package bubble, could be put into it's own .pm, I just make this monolithic for ease of testing the script. This is mostly to show how to make objects which "update their own display". So............


        I'm not really a human, but I play one on earth. flash japh

      Hi,

      I would make a Tier based Perl solution.

      I mean, having a Polling System (cron, POE, threads, maybe...), a Data Backend (some DBMS could be PostgreSQL) and a Consumer GUI which gets the info from the DB.

      This way the entire program acquisition, which is the very important thing is something small and stable which doesn't depend in any way with the user interaction, or gui libs or X server. And the GUI is only a consumer from the data stored in the DB. Why a DB? Because that way you have all the data in one place, and can get the data out in some different way, more flexibility to use other custom app that would use the data for further displaying or calculations.

      This schema ilustrate it:

      ---------------------- | data adquisition | Something small and robust. ---------------------- | / ---------------------- | db storage of data | DB backend, later you can use ---------------------- any software/language to / retrieve data, analisys, etc. | This way you're solution is ---------------------- very flexible. | GUI, consumer, etc | ----------------------

      Of course only a idea... ;-)

      Regards,

      |fire| at irc.freenode.net

      I like merlyn's disclaimer

        Sounds like a good plan. I have noticed that big projects like the one described go through different "growth phases". First is the "proof of concept", just showing it CAN be done. Then comes the "error and exception handling" which is usually discovered during testing of the "proof-of-concept" code. It sure does pay to sit down and think a bit, before making big coding descisions.

        I'm not really a human, but I play one on earth. flash japh
Re: Handling asynchronous events with Perl
by garyberi (Initiate) on Jul 11, 2005 at 22:52 UTC
    It seems that the transfer should be initiated by each AUV rather than by the server.

    Perhaps the AUVs could contact a (secure) web server via HTTPS and initiate the file download?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://473783]
Approved by neniro
Front-paged by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (5)
As of 2023-03-22 13:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Which type of climate do you prefer to live in?






    Results (60 votes). Check out past polls.

    Notices?