Bivio::Agent::Dispatcher
# Copyright (c) 1999-2008 bivio Software, Inc. All rights reserved.
# $Id$
package Bivio::Agent::Dispatcher;
use strict;
use Bivio::Base 'Bivio::UNIVERSAL';
use Bivio::IO::Trace;
# C<Bivio::Agent::Dispatcher> is the outside entry point into the Bivio
# application. When the dispatcher receives input, it wraps it in the
# appropriate Request subclass, checks the user is authorized to
# execute a task, and excutes the Task.
my($_INITIALIZED);
use vars qw($_TRACE);
my($_F) = b_use('UI.Facade');
my($_T) = b_use('Agent.Task');
my($_R) = b_use('Agent.Request');
my($_A) = b_use('IO.Alert');
my($_D) = b_use('Bivio.Die');
my($_DC) = b_use('Bivio.DieCode');
sub MAX_SERVER_REDIRECTS {
return 4;
}
sub initialize {
my($proto, $partially) = @_;
return
if $_INITIALIZED;
$_INITIALIZED = 1;
# Ensure we don't do something stupid.
b_die('partial init not allowed in mod_perl')
if $partially && exists($ENV{MOD_PERL});
$_R->get_current_or_new;
$_T->initialize($partially);
$_F->initialize($partially);
_trace("Size of process before fork\n", `ps v $$`) if $_TRACE;
return;
}
sub internal_server_redirect_task {
my($self, $curr_task, $die, $req) = @_;
#NOTE: Coupling with Request::internal_server_redirect.
# It already has set all the state
my($attrs) = $die->get('attrs');
_trace('redirect from ', $curr_task, ' to ', $attrs->{task_id})
if $_TRACE;
#TODO: add this when thoroughly debugged
# $req->clear_nondurable_state;
if ($curr_task == $attrs->{task_id} && $curr_task->get_name =~ /ERROR/) {
b_warn($curr_task, ': not redirecting to identical ERROR task');
return;
}
return $attrs->{task_id};
}
sub process_request {
my($self, @protocol_args) = @_;
$_R->clear_current;
my($die, $req, $task_id);
my($redirect_count) = -1;
TRY: {
$die = $_D->catch(sub {
die("too many dispatcher retries")
if ++$redirect_count > $self->MAX_SERVER_REDIRECTS;
unless ($req) {
$req = $self->create_request(@protocol_args);
_trace('create_request: ', $req) if $_TRACE;
}
$req->put_durable(redirect_count => $redirect_count)
->set_task($task_id ||= $req->get('task_id'))
->execute($req);
});
if ($die
&& $die->get('code') == $_DC->SERVER_REDIRECT_TASK
&& $redirect_count <= $self->MAX_SERVER_REDIRECTS
) {
last TRY
unless $task_id
= $self->internal_server_redirect_task($task_id, $die, $req);
#TODO: Can we remove the line below?
$req->internal_redirect_realm($task_id);
redo TRY;
}
}
$req->call_process_cleanup($die)
if $req;
$_R->clear_current;
$_A->reset_warn_counter;
return $die;
}
1;