[ANNOUNCE] Apache::Singleton 0.02 (Re: Tips tricks needed :))
On Thu, 20 Dec 2001 11:51:30 -0500 Perrin Harkins [EMAIL PROTECTED] wrote: Like this? (using register_cleanup instead of pnotes) Better to use pnotes. I started out doing this kind of thing with register_cleanup and had problems like random segfaults. I think it was because other cleanup handlers sometimes needed access to these resources. Now it uses pnotes(). Todo is to add scope configuration for each classes. The URL http://bulknews.net/lib/archives/Apache-Singleton-0.02.tar.gz has entered CPAN as file: $CPAN/authors/id/M/MI/MIYAGAWA/Apache-Singleton-0.02.tar.gz size: 1621 bytes md5: 89a86023ea672f571860e91696ff03bb 0.02 Sat Dec 22 16:58:34 JST 2001 - use pnotes instead of register_cleanup (Thanks to Perrin Harkins [EMAIL PROTECTED]) -- Tatsuhiko Miyagawa [EMAIL PROTECTED]
RE: Tips tricks needed :)
-Original Message- From: Tatsuhiko Miyagawa [mailto:[EMAIL PROTECTED]] On Wed, 19 Dec 2001 16:01:22 - Matt Sergeant [EMAIL PROTECTED] wrote: Actually I was wondering about writing an Apache::Singleton class, that works the same as Class::Singleton, but clears the singleton out on each request (by using pnotes). Would anyone be interested in that? Like this? (using register_cleanup instead of pnotes) package Apache::Singleton; use strict; use vars qw($VERSION); $VERSION = '0.01'; use Apache; sub instance { my $class = shift; # get a reference to the _instance variable in the $class package no strict 'refs'; my $instance = $class\::_instance; unless (defined $$instance) { $$instance = $class-_new_instance(@_); Apache-request-register_cleanup(sub { undef $$instance }); } return $$instance; } sub _new_instance { bless {}, shift; } Yeah, just like that. Why don't you wrap it up and stick it on CPAN? Saves me another module :-) Matt. _ This message has been checked for all known viruses by Star Internet delivered through the MessageLabs Virus Scanning Service. For further information visit http://www.star.net.uk/stats.asp or alternatively call Star Internet for details on the Virus Scanning Service.
ANNOUNCE: Apache:Singleton 0.01 (Re: Tips tricks needed :))
On Thu, 20 Dec 2001 08:57:32 - Matt Sergeant [EMAIL PROTECTED] wrote: Yeah, just like that. Why don't you wrap it up and stick it on CPAN? Saves me another module :-) Okay ;) The URL http://bulknews.net/lib/archives/Apache-Singleton-0.01.tar.gz has entered CPAN as file: $CPAN/authors/id/M/MI/MIYAGAWA/Apache-Singleton-0.01.tar.gz size: 1641 bytes md5: 57abd03817ead367287d1f5908c0143b NAME Apache::Singleton - Singleton class for mod_perl SYNOPSIS package Printer; use base qw(Apache::Singleton); # just the same as Class::Singleton DESCRIPTION Apache::Singleton works the same as Class::Singleton, but clears the singleton out on each request. This module checks $ENV{MOD_PERL}, so it just works well in non-mod_perl environment. AUTHOR Original idea by Matt Sergeant [EMAIL PROTECTED]. Code by Tatsuhiko Miyagawa [EMAIL PROTECTED] This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. SEE ALSO the Class::Singleton manpage -- Tatsuhiko Miyagawa [EMAIL PROTECTED]
Re: Tips tricks needed :)
(sorry to break threading but I'm getting this from multiple lists) that IE 6 (beta at the time) considered my cookies to be third party because I used frame-based domain redirection and by default would not accept them. You need to include a P3P header in your HTTP header that contains a Compact Policy (CP) - a geek code of what your P3P xml privacy document contains. See http://www.w3c.org/P3P/. Some research I did seems to indicate that current implementations of IE6 will accept cookies no matter what CP you use (rather than checking it against your security settings and deciding if the CP represents a privacy policy that violates your chosen level of disclosure.) I'd really appreciate it other people could check this and confirm that IE6 is not offering any actual privacy level protection and is just discriminated against people that don't have P3P headers. My (Profero's) module for automagically converting a P3P document (the xml) into a CP (the geek-code version of that xml document) is in beta here: http://twoshortplanks.com/temp/P3P-ToCP-0.02.tar.gz Please test, break and get back to me when it doesn't work. It just follows the spec and uses XML::XPath to pull the stuff out. Later Mark. -- s'' Mark Fowler London.pm Bath.pm http://www.twoshortplanks.com/ [EMAIL PROTECTED] ';use Term'Cap;$t=Tgetent Term'Cap{};print$t-Tputs(cl);for$w(split/ +/ ){for(0..30){$|=print$t-Tgoto(cm,$_,$y). $w;select$k,$k,$k,.03}$y+=2}
Re: Tips tricks needed :)
On Thu, 20 Dec 2001, Mark Fowler wrote: (sorry to break threading but I'm getting this from multiple lists) that IE 6 (beta at the time) considered my cookies to be third party because I used frame-based domain redirection and by default would not accept them. You need to include a P3P header in your HTTP header that contains a Compact Policy (CP) - a geek code of what your P3P xml privacy document contains. See http://www.w3c.org/P3P/. Some research I did seems to indicate that current implementations of IE6 will accept cookies no matter what CP you use (rather than checking it against your security settings and deciding if the CP represents a privacy policy that violates your chosen level of disclosure.) I'd really appreciate it other people could check this and confirm that IE6 is not offering any actual privacy level protection and is just discriminated against people that don't have P3P headers. I found that IE6 require P3P header with medium and higher security settings but CP content doesn't matter - it need simply P3P: CP='anything'. Igor Sysoev
Re: Tips tricks needed :)
Like this? (using register_cleanup instead of pnotes) Better to use pnotes. I started out doing this kind of thing with register_cleanup and had problems like random segfaults. I think it was because other cleanup handlers sometimes needed access to these resources. - Perrin
Re: Tips tricks needed :)
At 10:50 19.12.01 +0200, you wrote: 4. [...] Ok, let's say we even somehow make these formulas general enough to use, but where shall the calculation take place? Postgres stored procs or in perl code/module (i think this) or even in TT? Constans will be in db. I tend to do calculations involving money in the database to avoid floating point rounding headaches. By the way, is there a perl module to do calculations with money? Joachim -- ... ein Geschlecht erfinderischer Zwerge, die fuer alles gemietet werden koennen.- Bertolt Brecht - Leben des Galilei
Re: Tips tricks needed :)
By the way, is there a perl module to do calculations with money? We use Math::BigInt to do fixed point. We couldn't get the other math modules to work a few years back. Our wrapper (Bivio::Type::Number) normalizes the rounding and allows subclasses to specify precision, decimals, min, max, etc. It's not fast, but fast enough. :-) It's part of bOP, which is available under the Artistic license from http://www.bivio.biz/hm/download-bOP We don't do too much math in the database, i.e. with PL/SQL and such. One thing we have done which has really helped is to define the sign of all amounts/quantities so that we can use SQL's SUM() function. Our database is normalized, which speeds development and reduces bugs. Using SUM() keeps queries fast (100MS) even processing ~1K rows to produce a portfolio. Cheers, Rob
Re: Tips tricks needed :)
By the way, is there a perl module to do calculations with money? There's Math::Currency. - Perrin
Re: Tips tricks needed :)
On Thu, 20 Dec 2001 11:51:30 -0500 Perrin Harkins [EMAIL PROTECTED] wrote: Like this? (using register_cleanup instead of pnotes) Better to use pnotes. I started out doing this kind of thing with register_cleanup and had problems like random segfaults. I think it was because other cleanup handlers sometimes needed access to these resources. I'll take care of it. Thanks for the input. -- Tatsuhiko Miyagawa [EMAIL PROTECTED]
Re: Tips tricks needed :)
Viljo Marrandi [EMAIL PROTECTED] writes: I'm answering what I can... :-) 3. Authorization. Is cookie based auth most reasonable or are there some other ways too? .htaccess will not do, I think, because all data is in the same directory and authorized access/login is needed only on some parts of site. Which data should I send with cookie? Only some random key which is also stored in dbase and this key is used to find real data from dbase? (I guess I must read again this thread about cookies). First of all, why putting everything at the same place? It would be easier to maintain things if only the generic things are at the same place and specific things are in their own directories. Depending on how much data you're going to store, I'd use a cookie that is a hash (e.g. MD5) to some index at the database. Don't send confidential information on them (people might use some public internet to view their information) and try not sending plain text (people might be tempted to change values). 4. How is most reasonable to store(and use too) complex formulas and coefficients? Problem is that there are 4 companies and each of them has different way to calculate same thing eg. insurance for travelling, car insurance etc. Unfortunately they are all quite different, because every company uses even different things to calculate final result. So if we use different formula for every company and insurance type we end up with ~50 formulas and none understands afterwards which is which. Are there any guidelines to generalize formulas? Ok, let's say we even somehow make these formulas general enough to use, but where shall the calculation take place? Postgres stored procs or in perl code/module (i think this) or even in TT? Constans will be in db. Create modules for each company. This way you'll have each company's functions on her own module. They will be differentiated by namespace. (And you can use references to select the appropriated module, the information on which company that client belongs to might be in a record at the database ;-)) By using references, your only thing to worry will be naming the same things with the same names. You should also pass values by reference. Using modules will also make it possible to change formulae without worring about which of them are common to other companies or which are not common. And, since you're already going to use OO Perl... ;-) P.S. I hope that in about few months I can write about this project to success stories ;-) Me too! :-) Be seeing you, -- Godoy. [EMAIL PROTECTED] Solutions Developer - Conectiva Inc. - http://en.conectiva.com Desenvolvedor de Soluções - Conectiva S.A. - http://www.conectiva.com.br msg23683/pgp0.pgp Description: PGP signature
Re: Tips tricks needed :)
1. Regarding the switch to postgresql, I think that's a good choice. Just pay attention to postgresql's data types, and try to get your fields types and lengths correct the first time if possible. It doesn't completely support the ALTER TABLE command, so changing column types can be a pain, although it's still possible. The other thing is that SQL syntax might be slightly different in a few cases, though it's been too long since I used MySQL to remember any examples. Postgresql's web site has some tips for switching, I think at http://techdocs.postgresql.org. 2. Have them read some articles on the whole MVC approach, since it sounds like you'll be using that. And of course read Damian's book several times for OO perl. 4. You might put the formulas in a perl superclass, with one method per formula. Then create a subclass for each different company that has that company's algorithm. All the calling code has to worry about is which company it's dealing with when it instantiates the object; after that all the right formulas will get used automatically. This should make it easy to add more companies, too. I guess the general principle is that when you're faced with tons of complexity, try breaking it down into smaller pieces and add an abstraction layer or two, so you and the program can deal with it. Hope this helps. I'll be watching for the success story! -- Wes Sheldahl Viljo Marrandi [EMAIL PROTECTED] on 12/19/2001 03:50:49 AM To: modperl list [EMAIL PROTECTED], templates list [EMAIL PROTECTED] cc:(bcc: Wesley Sheldahl/Lex/Lexmark) Subject: Tips tricks needed :) Hello, We're going to make a web-site for insurance company (err, more like portal for several companies) and the problem is that ( I think ) it's going to be our biggest and most complex site we've ever done AND we're going to use some new stuff we've never used. So I'd be very happy if you can give me some points what to look at, what are real no-no's and what are go-go's. 1. We're going to switch from mysql to postgresql, because we need transactions, triggers and all other stuff that mysql doesn't support. What could be possible problems going from mysql to postgres, if any? 2. We will use Template-Toolkit and Apache/mod_perl. Problem is that 2 out of 3 people have never used TT or programmed mod_perl and OO Perl. Only I've made sites this way, they've used Embperl til now. How can I make this switch for them a little easier? I know I must spend a lot of time teaching them, but may-be there are some kinda switchover tutorials or something? 3. Authorization. Is cookie based auth most reasonable or are there some other ways too? .htaccess will not do, I think, because all data is in the same directory and authorized access/login is needed only on some parts of site. Which data should I send with cookie? Only some random key which is also stored in dbase and this key is used to find real data from dbase? (I guess I must read again this thread about cookies). 4. How is most reasonable to store(and use too) complex formulas and coefficients? Problem is that there are 4 companies and each of them has different way to calculate same thing eg. insurance for travelling, car insurance etc. Unfortunately they are all quite different, because every company uses even different things to calculate final result. So if we use different formula for every company and insurance type we end up with ~50 formulas and none understands afterwards which is which. Are there any guidelines to generalize formulas? Ok, let's say we even somehow make these formulas general enough to use, but where shall the calculation take place? Postgres stored procs or in perl code/module (i think this) or even in TT? Constans will be in db. 5. Any other things to look out when creating large site and/or running it over SSL and/or using above described configuration? P.S. I hope that in about few months I can write about this project to success stories ;-) Thanks for your attention, Viljo
Re: Tips tricks needed :)
[EMAIL PROTECTED] wrote: 1. Regarding the switch to postgresql, I think that's a good choice. Just pay attention to postgresql's data types, and try to get your fields types and lengths correct the first time if possible. It doesn't completely support the ALTER TABLE command, so changing column types can be a pain, although it's still possible. The other thing is that SQL syntax might be slightly different in a few cases, though it's been too long since I used MySQL to remember any examples. Postgresql's web site has some tips for switching, I think at http://techdocs.postgresql.org. something i'll add to that - if your new postgresql db will have foreign keys, and you previously didn't have any code written to guarantee your data's integrity in mysql, then you probably won't be able to import all your data without some massaging (unless you're sure your data's integrity is ok). i wholeheartedly second wes' statement that switching to postgresql is a good choice.
Re: Tips tricks needed :)
If you're developing a complex application, you'll probably want to split it in a horde of specialized modules. Few things to remember: == You will probably feel the need to use static variables (i.e. variables shared with all instances of a given class) at some point. For example if you have a singleton object you might have something like that: package Your::Singleton; use strict; use 5.6; use our $ETERNAL = undef; sub instance { my $class = shift; return $ETERNAL if (defined $ETERNAL); $ETERNAL = $class-new (@_); return $ETERNAL; } sub new { ... blah blah code ... } 1; ALWAYS reinitialize $Your::Singleton::ETERNAL on each query! mod_perl will *NOT* do it for you. You might think 'ah yeah but it would be nice if $Your::Singleton::ETERNAL could be persistent across queries...' which is sometimes desirable, but remember that if you have multiple instances of your application running on the same apache, $Your::Singleton::ETERNAL will be common to ALL of them. == Cyclic memory references are dangerous, try to avoid them as much as possible! Perl garbage collector does miserably fails in the case of cyclic refs. If you have a cycling references that keep going out of scope, they will never be garbage collected and your server might have some trouble :-) == Beware of regular expressions /o modifier! The application I'm working on has a cool feature heavily using regular expressions: automagic hyperlinking of text / html data when appropriate. I used to use the /o modifier and got a few nasty surprises (until I discovered the mod_perl guide traps page) == Other than that, more generally speaking: Always hide classes implementation with method calls! Not so long ago I did tend to write using less method calls and directly accessing object's attributes and now this is my #1 source of maintenance problem and headaches. It you think it's too slow then consider it's better to buy a bigger CPU than 3 tons of aspirin. Also avoid using packages names inside functions as much as possible, as it tends to screw inheritance. Finally my biggest piece of advice: ENFORCE a coding style. ENFORCE using english for variable, function names and comments (for example although I'm French I really can't stand code written with french variable names and comments! The Perl language is using English keywords after all. Be consistent FFS) . ENFORCE commenting what every single method does. Having said that I do naturally tend to write awful code that only I can understand, but at least everything is properly commented :) Cheers, -- IT'S TIME FOR A DIFFERENT KIND OF WEB Jean-Michel Hiver - Software Director [EMAIL PROTECTED] +44 (0)114 221 4968 VISIT HTTP://WWW.MKDOC.COM
Re: Tips tricks needed :)
2. We will use Template-Toolkit and Apache/mod_perl. Problem is that 2 out of 3 people have never used TT or programmed mod_perl and OO Perl. Only I've made sites this way, they've used Embperl til now. How can I make this switch for them a little easier? Get them all copies of the Eagle book and Damian's OO book (or the Advanced Perl Programming book, which I also like for OO). Have them read at least the porting and traps documentation that comes with mod_perl, if not the whole Guide. Decide if you will be using a framework like OpenInteract or OpenFrame. If not, decide on a basic structure for request handling, error handling, and parameter parsing, and document it. We made this same transition at eToys, and you can do it. Learning to use TT is pretty quick, but OO and mod_perl require more hand-holding and are much easier if you have someone around with some confidence in how to use them. I'm including a brief outline that I used when I gave a talk about mod_perl. It's slightly out of date, but it shows what I considered to be the highlights for mod_perl newbies. Which data should I send with cookie? Only some random key which is also stored in dbase and this key is used to find real data from dbase? Yes, use a unique key with some kind of MAC so you can be sure it isn't forged when it's sent back to you. See the recent thread and the AuthCookie module. Note that some things still have to passed as query args or hidden fields. This would be anything that could be happening in multiple windows, like search terms (if you tied them to the cookie, searches in multiple windows would interfere with each other). 4. How is most reasonable to store(and use too) complex formulas and coefficients? I would use an OO approach with polymorphism, like others have described. - Perrin What is mod_perl? An Apache module. An embedded Perl interpreter. Fast. Flexible. What's wrong with CGI? Forking Perl on every request. Compiling the script every time. Opening a new database connection every time. Apache::DBI. The Apache request lifecycle. See diagram. The Apache API. See code listing. $r $r->headers_in->{'User-Agent'} $r->parsed_uri $r->args The config file. How mod_perl emulates CGI. Apache::Registry Apache::PerlRun What do you need to know as a programmer? Memory management. use strict! use strict! use strict! Pre-loading and copy-on-write. See diagram. startup.pl Imported symbols and use vars. Traps Global settings: $/, $^T, $^W, $| Using them safely with local. -M test implications. use, require, do, and %INC Compiled regular expressions. See the guide or Perl Cookbook. BEGIN and END blocks. Performance tweaks. Apache::Request for query string. See listing. Apache::Cookie for cookies. See listing. Apache::Util for escaping HTML and URIs See benchmark. DBI: prepare_cached and finish Reloading your code changes. Restart the server. Apache::StatINC. Stonehenge::Reload. PerlFreshRestart. Memory considerations for live servers. Profiling Debugging Tricks to use in production. Apache::SizeLimit. Proxy server setup. Resources Read the guide! - http://perl.apache.org/guide/ PerlMonth - http://perlmonth.com/ perldoc everything The Eagle Book and http://www.modperl.com the mailing list Comparison to other systems?
RE: Tips tricks needed :)
-Original Message- From: Perrin Harkins [mailto:[EMAIL PROTECTED]] ALWAYS reinitialize $Your::Singleton::ETERNAL on each query! mod_perl will *NOT* do it for you. If you want a per-request global, use $r-pnotes() instead of a standard perl global. Then mod_perl *WILL* do it for you. Actually I was wondering about writing an Apache::Singleton class, that works the same as Class::Singleton, but clears the singleton out on each request (by using pnotes). Would anyone be interested in that? Matt. _ This message has been checked for all known viruses by Star Internet delivered through the MessageLabs Virus Scanning Service. For further information visit http://www.star.net.uk/stats.asp or alternatively call Star Internet for details on the Virus Scanning Service.
Re: Tips tricks needed :)
Actually I was wondering about writing an Apache::Singleton class, that works the same as Class::Singleton, but clears the singleton out on each request (by using pnotes). Would anyone be interested in that? This sounds a bit like Object::Registrar. If you do it, I'd suggest giving it a scope option for each variable that determines if it's process or request scope. In fact you could add support for some kind of data-sharing and offer a server scope as well. - Perrin
Re: Tips tricks needed :)
ALWAYS reinitialize $Your::Singleton::ETERNAL on each query! mod_perl will *NOT* do it for you. If you want a per-request global, use $r-pnotes() instead of a standard perl global. Then mod_perl *WILL* do it for you. You might think 'ah yeah but it would be nice if $Your::Singleton::ETERNAL could be persistent across queries...' which is sometimes desirable, but remember that if you have multiple instances of your application running on the same apache, $Your::Singleton::ETERNAL will be common to ALL of them. It will be common to all requests in that particular process, but not shared between multiple Apache processes. If you take requests for different applications that need different singletons on the same Apache process, you should separate them by namespace so they don't collide. - Perrin
RE: Tips tricks needed :)
-Original Message- From: Perrin Harkins [mailto:[EMAIL PROTECTED]] Actually I was wondering about writing an Apache::Singleton class, that works the same as Class::Singleton, but clears the singleton out on each request (by using pnotes). Would anyone be interested in that? This sounds a bit like Object::Registrar. No, it's nothing like Object::Registrar. It's like Class::Singleton. Matt. _ This message has been checked for all known viruses by Star Internet delivered through the MessageLabs Virus Scanning Service. For further information visit http://www.star.net.uk/stats.asp or alternatively call Star Internet for details on the Virus Scanning Service.
Re: Tips tricks needed :)
No, it's nothing like Object::Registrar. It's like Class::Singleton. Okay, wishful thinking. I don't use Class::Singleton, but I have written my own versions of Object::Registrar a few times to accomplish the same goal. I don't like to make my core classes dependent on running in a mod_perl environment if I can avoid it, so I prefer to use a separate registry approach that keeps $r-pnotes() out of my classes. It's also nice to be able to quickly adapt other people's classes in this way without changing their code to use Class::Singleton. - Perrin
Re: Tips tricks needed :)
Perrin Harkins writes: Okay, wishful thinking. I don't use Class::Singleton, but I have written my own versions of Object::Registrar a few times to accomplish the same goal. Ditto. We use a registry mechanism, too. One thing I don't quite understand is the need to clear out a singleton. Why would a singleton need to hold transient state? Rob
Re: Tips tricks needed :)
One thing I don't quite understand is the need to clear out a singleton. Why would a singleton need to hold transient state? It's good for holding something request-specific, like a user session.
Re: Tips tricks needed :)
On Wed 19-Dec-2001 at 10:43:34AM -0500, Perrin Harkins wrote: ALWAYS reinitialize $Your::Singleton::ETERNAL on each query! mod_perl will *NOT* do it for you. If you want a per-request global, use $r-pnotes() instead of a standard perl global. Then mod_perl *WILL* do it for you. True. But then you are using the Apache object and you're program doesn't work as a standard CGI anymore :( You might think 'ah yeah but it would be nice if $Your::Singleton::ETERNAL could be persistent across queries...' which is sometimes desirable, but remember that if you have multiple instances of your application running on the same apache, $Your::Singleton::ETERNAL will be common to ALL of them. It will be common to all requests in that particular process, but not shared between multiple Apache processes. If you take requests for different applications that need different singletons on the same Apache process, you should separate them by namespace so they don't collide. Yup, that's what I meant. Separating by namespace is not very convenient though. What I have been doing to get around this is that I wrote a simple module that can be used as a global scalar and that uses tie to return appropriate variable (FYI I've attached the module, if that interests anyone). Cheers, -- IT'S TIME FOR A DIFFERENT KIND OF WEB Jean-Michel Hiver - Software Director [EMAIL PROTECTED] +44 (0)114 221 4968 VISIT HTTP://WWW.MKDOC.COM MPH.pm Description: Perl program
Re: Tips tricks needed :)
If you want a per-request global, use $r-pnotes() instead of a standard perl global. Then mod_perl *WILL* do it for you. True. But then you are using the Apache object and you're program doesn't work as a standard CGI anymore :( I handle this by chekcing for $ENV{MOD_PERL} and just using a global for storage if it isn't defined. Separating by namespace is not very convenient though. What I have been doing to get around this is that I wrote a simple module that can be used as a global scalar and that uses tie to return appropriate variable (FYI I've attached the module, if that interests anyone). That's a good idea. I've done similar things with accessor methods instead of tied scalars. - Perrin
Re: Tips tricks needed :)
On Wed, 19 Dec 2001 16:01:22 - Matt Sergeant [EMAIL PROTECTED] wrote: Actually I was wondering about writing an Apache::Singleton class, that works the same as Class::Singleton, but clears the singleton out on each request (by using pnotes). Would anyone be interested in that? Like this? (using register_cleanup instead of pnotes) package Apache::Singleton; use strict; use vars qw($VERSION); $VERSION = '0.01'; use Apache; sub instance { my $class = shift; # get a reference to the _instance variable in the $class package no strict 'refs'; my $instance = $class\::_instance; unless (defined $$instance) { $$instance = $class-_new_instance(@_); Apache-request-register_cleanup(sub { undef $$instance }); } return $$instance; } sub _new_instance { bless {}, shift; } -- Tatsuhiko Miyagawa [EMAIL PROTECTED]