sample stasis web services for apache modperl and fastcgi. Both are multithreaded. However, the modperl one is racy. FastCGI is currently the recommended approach
This commit is contained in:
parent
417eec45c4
commit
94b356f837
5 changed files with 224 additions and 0 deletions
22
lang/perl/README.cgi-bin
Normal file
22
lang/perl/README.cgi-bin
Normal file
|
@ -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/
|
||||||
|
<Directory "/home/sears/stasis/lang/perl/cgi-bin">
|
||||||
|
AllowOverride None
|
||||||
|
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
|
||||||
|
Order allow,deny
|
||||||
|
Allow from all
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
This is the contents of my /etc/apache2/mods-enabled/fastcgi.conf
|
||||||
|
|
||||||
|
<IfModule mod_fastcgi.c>
|
||||||
|
AddHandler fastcgi-script .fcgi
|
||||||
|
#FastCgiWrapper /usr/lib/apache2/suexec
|
||||||
|
FastCgiIpcDir /var/lib/apache2/fastcgi
|
||||||
|
FastCgiConfig -maxClassProcesses 1 -maxProcesses 1 -processSlack 1
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
Note that the fastcgi scripts are currently hardcoded to run in ~sears/stasis/www-data2
|
25
lang/perl/README.modperl
Normal file
25
lang/perl/README.modperl
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
This goes in apache.conf:
|
||||||
|
|
||||||
|
<IfModule mpm_worker_module>
|
||||||
|
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
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
|
||||||
|
This goes in the sites-enabled/???:
|
||||||
|
|
||||||
|
PerlRequire /home/sears/stasis/lang/perl/apache/inc/startup.pl
|
||||||
|
|
||||||
|
<Location /stasis>
|
||||||
|
SetHandler perl-script
|
||||||
|
PerlResponseHandler StasisWeb::Web
|
||||||
|
</Location>
|
||||||
|
|
||||||
|
Note that the modapache scripts are currently hardcoded to look in ~sears/stasis/www-data
|
34
lang/perl/apache/StasisWeb/Web.pm
Normal file
34
lang/perl/apache/StasisWeb/Web.pm
Normal file
|
@ -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 "<html><head></head><body><h1>Stasis</h1>" . `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 "</body></html>\n";
|
||||||
|
|
||||||
|
return Apache2::Const::OK;
|
||||||
|
}
|
||||||
|
1;
|
51
lang/perl/apache/inc/startup.pl
Executable file
51
lang/perl/apache/inc/startup.pl
Executable file
|
@ -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;
|
92
lang/perl/cgi-bin/test.fcgi
Executable file
92
lang/perl/cgi-bin/test.fcgi
Executable file
|
@ -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";
|
Loading…
Reference in a new issue