From 94b356f837b9f4753de1a5cdd515966a74d95800 Mon Sep 17 00:00:00 2001 From: Sears Russell Date: Tue, 19 Jan 2010 02:11:04 +0000 Subject: [PATCH] sample stasis web services for apache modperl and fastcgi. Both are multithreaded. However, the modperl one is racy. FastCGI is currently the recommended approach --- lang/perl/README.cgi-bin | 22 ++++++++ lang/perl/README.modperl | 25 +++++++++ lang/perl/apache/StasisWeb/Web.pm | 34 ++++++++++++ lang/perl/apache/inc/startup.pl | 51 +++++++++++++++++ lang/perl/cgi-bin/test.fcgi | 92 +++++++++++++++++++++++++++++++ 5 files changed, 224 insertions(+) create mode 100644 lang/perl/README.cgi-bin create mode 100644 lang/perl/README.modperl create mode 100644 lang/perl/apache/StasisWeb/Web.pm create mode 100755 lang/perl/apache/inc/startup.pl create mode 100755 lang/perl/cgi-bin/test.fcgi diff --git a/lang/perl/README.cgi-bin b/lang/perl/README.cgi-bin new file mode 100644 index 0000000..1d04076 --- /dev/null +++ b/lang/perl/README.cgi-bin @@ -0,0 +1,22 @@ +This should go in a sites-enabled file, inside a VirtualHost: + + ScriptAlias /stasis-cgi/ /home/sears/stasis/lang/perl/cgi-bin/ + + AllowOverride None + Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch + Order allow,deny + Allow from all + + + + +This is the contents of my /etc/apache2/mods-enabled/fastcgi.conf + + + AddHandler fastcgi-script .fcgi + #FastCgiWrapper /usr/lib/apache2/suexec + FastCgiIpcDir /var/lib/apache2/fastcgi + FastCgiConfig -maxClassProcesses 1 -maxProcesses 1 -processSlack 1 + + +Note that the fastcgi scripts are currently hardcoded to run in ~sears/stasis/www-data2 diff --git a/lang/perl/README.modperl b/lang/perl/README.modperl new file mode 100644 index 0000000..65d6621 --- /dev/null +++ b/lang/perl/README.modperl @@ -0,0 +1,25 @@ +This goes in apache.conf: + + + StartServers 1 +# Only want 1 server; this is a correctness constraint for stasis. + ServerLimit 1 + MinSpareThreads 25 + MaxSpareThreads 75 + ThreadLimit 150 + ThreadsPerChild 150 + MaxClients 150 + MaxRequestsPerChild 0 + + + +This goes in the sites-enabled/???: + + PerlRequire /home/sears/stasis/lang/perl/apache/inc/startup.pl + + + SetHandler perl-script + PerlResponseHandler StasisWeb::Web + + +Note that the modapache scripts are currently hardcoded to look in ~sears/stasis/www-data diff --git a/lang/perl/apache/StasisWeb/Web.pm b/lang/perl/apache/StasisWeb/Web.pm new file mode 100644 index 0000000..cccff37 --- /dev/null +++ b/lang/perl/apache/StasisWeb/Web.pm @@ -0,0 +1,34 @@ +#file:Stasis/Web.pm +#---------------------- +package StasisWeb::Web; + +use threads::shared; +my $thelock :shared; + +use strict; +use warnings; +use Apache2::RequestRec (); +use Apache2::RequestIO (); +use Apache2::Const -compile => qw(OK); + +sub handler { + my $r = shift; + $r->content_type('text/html'); + print "

Stasis

" . `pwd`; + my $xid = Stasis::Tbegin(); + warn "a\n"; + my %h; + tie %h, 'Stasis::Hash', $xid, Stasis::ROOT_RID(); + + $h{foo}++; + + print ("$xid $h{foo}\n"); + + Stasis::Tcommit($xid); + warn "b\n"; $| = 1; + + print "\n"; + + return Apache2::Const::OK; +} +1; diff --git a/lang/perl/apache/inc/startup.pl b/lang/perl/apache/inc/startup.pl new file mode 100755 index 0000000..ac70559 --- /dev/null +++ b/lang/perl/apache/inc/startup.pl @@ -0,0 +1,51 @@ +use threads; +use threads::shared; + +use strict; +BEGIN { + my $thelock :shared; + + $ENV{STASIS_DIR} = '/home/sears/stasis'; + + $ENV{STASIS_LOCK} = $thelock; +} +use lib ($ENV{STASIS_DIR}."/lang/perl/apache/"); +push @INC, "$ENV{STASIS_DIR}/lang/perl/"; + +use Inline (Config => + DIRECTORY => "$ENV{STASIS_DIR}/www-data/", + ); +use Stasis; + +# XXX Ideally, the rest of this would go in a post_config handler, but +# I can't get that to work... + +my $data_dir = "$ENV{STASIS_DIR}/www-data/"; + +{ + my $d = `date`; + chomp $d; + warn "$d: Starting Stasis in $data_dir\n"; + chdir $data_dir + || die "Could not chdir to $data_dir, which I must own!"; + + Stasis::Tinit(); + $d = `date`; + chomp $d; + warn "$d: Stasis recovery complete\n"; + my $xid = Stasis::Tbegin(); + if(Stasis::TrecordType($xid, Stasis::ROOT_RID()) == Stasis::INVALID_SLOT()) { + $d = `date`; + chomp $d; + warn "$d: Bootstrapping new Stasis store.\n"; + + Stasis::ThashCreate($xid); + } + Stasis::Tcommit($xid); + + $d = `date`; + chomp $d; + warn "$d: Stasis initialization complete.\n"; +} + +1; diff --git a/lang/perl/cgi-bin/test.fcgi b/lang/perl/cgi-bin/test.fcgi new file mode 100755 index 0000000..36a9530 --- /dev/null +++ b/lang/perl/cgi-bin/test.fcgi @@ -0,0 +1,92 @@ +#!/usr/bin/perl -w + +use strict; + +BEGIN { + $ENV{STASIS_DIR} = '/home/sears/stasis'; + $ENV{STASIS_INLINE_DIRECTORY} = '/home/sears/stasis/www-data2'; + $ENV{PATH} = '/usr/local/bin:/usr/bin:/bin'; +# $ENV{LANG} = 'en_US.UTF-8'; +# $ENV{SHELL} = '/bin/sh'; + +# warn `env`; + chdir "$ENV{STASIS_DIR}/www-data2" || die; +# warn "begin succeeded"; + push @INC, "$ENV{STASIS_DIR}/lang/perl"; +} + +use threads; +use threads::shared; + +use Stasis; + +use IO::Handle; +use FCGI; + +my $count = 0; +my $tot :shared = 0; +my $concurrent :shared = 0; + +my $in = new IO::Handle; +my $out = new IO::Handle; +my $err = new IO::Handle; + +my $num_procs = 25; + + +Stasis::Tinit(); +my $xid = Stasis::Tbegin(); +if(Stasis::TrecordType($xid, Stasis::ROOT_RID()) == Stasis::INVALID_SLOT()) { + warn "Creating new database\n"; + Stasis::ThashCreate($xid); +} +Stasis::Tcommit($xid); +warn "Stasis bootstrap completed; accepting FastCGI requests\n"; + +my @thrs; +for(my $i = 0; $i < $num_procs; $i++) { + push @thrs, threads->create(\&event_loop, $i); +} +sub event_loop { + my $i = shift; +# warn "Event loop $i started\n"; + my $request = FCGI::Request($in, $out, $err); + while($request->Accept() >= 0) { + my $s; + my $tot2; + { lock $concurrent; $concurrent ++; } + { + lock($tot); + $tot ++; + $s = $tot; + my $xid = Stasis::Tbegin(); + + my %h; + tie %h, 'Stasis::Hash', $xid, Stasis::ROOT_RID(); + + $h{foo}++; + + $tot2 = $h{foo}; + + Stasis::TsoftCommit($xid); + } + # Release lock before waiting for disk force. + Stasis::TforceCommits(); + + print $out "Content-type: text/html\r\n\r\n" . "$count of $s ($tot2) concurrent: $concurrent"; + $count ++; + { lock $concurrent; warn "concurr: $concurrent\n"; $concurrent --; } +# print $err "Event loop $i accepted request\n"; + } +# warn "Event loop $i done\n"; +} + +warn "Done spawning worker threads\n"; + +foreach my $t (@thrs) { + $t->join(); +} + +Stasis::Tdeinit(); + +warn "Stasis cleanly shut down\n";