Kyle R . Burton on Thu, 12 Apr 2001 22:07:57 -0400 |
I'm working on a website where we do real time contract based pricing and availability. The interface to the pricing system is currently RPC based - we were originaly provided with a command line binary that we could call to obtain pricing information. It read it's input from stdin, and wrote it's output to stdout (sounds familliar eh?). The site is Apache+mod_perl based, and connects to an Oracle database. So in genral, it performs well. The pricing call has been a thorn in our side since the beginning - as we have to create a pair of pipes, and do a fork+exec to safely run the pricing program and pass data to/from it (we've managed to keep taint checking on). The busier the site gets, the more forking for pricing takes place - and we've recently been told that for performance reasons (since traffic has risen) we shouldn't price more than 15 products at a time (we sometimes have to price more than 40 for a single page), so this forces even more forking on the web servers. To obviate all of the forking, I've decided to just wrap the RPC call in an XS module. This is the first time I've written an XS module and had Perl calling C code, so I wanted advice/confirmation on the approach that I'm using. There are 3 basic C (RPC) calls that need to be made: clnt_create Which makes the RPC connection, and returns a pointer to an RPC CLIENT struct. the_pricing_call which basicly takes a string, and returns a string clnt_destroy to disconnect, and free the client struct The approach I've taken so far is to wrap each of these in an XS function. For clnt_create, I'm casting the CLIENT* to an I32 and storing it inside the calling object by using call_method to call a get/set that is implemented in native Perl. The man pages [perlcall, perlguts, perlxs] recommended this approach (casting the pointer to an I32 and back). For the pricing call, on success, I'm storing the resulting returned buffer in an SV* inside the calling object [native Perl code]. It is getting it's arguments by using call_method on get/sets, and storing the results (or errors) in the same manner. clnt_destroy uses call_method to obtain the I32 value from a get/set implemented in Perl. So far, this has worked out well - we even have an advantage over the command line program - we can keep the RPC connection open and make multiple pricing calls before closing it. I've seen a few other approaches. One where you use a C structure and bless it to make it an object. This worked for the first prototype, though it ended up being a scalar reference, and I couldn't figure out how to successfuly have it be derived from another base class - especially since our universal base class is implemented as a hash ref. Has anyone done anything similar? Does anyone know if there is a better way to accomplish this? Any general advice/gotchas? thanks, Kyle -- ------------------------------------------------------------------------------ Of course power tools and alcohol don't mix. Everyone knows power tools aren't soluble in alcohol... -- Crazy Nigel mortis@voicenet.com http://www.voicenet.com/~mortis ------------------------------------------------------------------------------ **Majordomo list services provided by PANIX <URL:http://www.panix.com>** **To Unsubscribe, send "unsubscribe phl" to majordomo@lists.pm.org**
|
|