Apache Rivet devolves to the Multi-Processing Module (MPM) the task of managing the agents responding to network requests. An MPM is responsible for creating such agents during the start-up, and is in charge for terminating existing ones and recreating new agents when the workload is requiring it.
Apache Rivet 2.0,2.1,2.2,2.3 supported only the prefork MPM which creates child processes as independent agents responding to network requests. Starting with 3.0 also the worker and event MPM are supported. The worker MPM is an hybrid model where forked child processes in turn create threads as real network agents. Also Apache on Windows© is now supported and tested with the winnt MPM, where a single process creates and manages a large number of thread agents.
Configuration parameters about this critical point can be read in the Apache documentation.
There are 4 stages in the lifetime of an Apache webserver that are relevant to Rivet:
Note | |
---|---|
GlobalInitScript has no effect to working interpreters when SeparateVirtualInterps is set. |
Note | |
---|---|
The lazy MPM bridge implements a model where every worker thread has exactly one interpreter and belongs to a single virtual host, therefore SeparateVirtualInterps is ignored and you can't share the same interpreter among virtual host |
Note | |
---|---|
This section explain the default request handling procedure which was written to let Rivet 3.0 work as a drop in replacement of any 2.x module. For a in-depth understanding of the new request processing mechanics please read the request processing section of the manual |
Rivet is highly configurable and each of the webserver lifecycle stages can be exploited to control a web application. Not only the orderly sequence of stages in a child lifecycle can be controlled with Tcl scripts, but also Tcl error or abnormal conditions taking place during the execution can be caught and handled with specific scripts.
Tcl errors (conditions generated when a command exits with code TCL_ERROR) usually result in the printing of a backtrace of the code fragment relevant to the error. Rivet can set up scripts to trap these errors and run instead an ErrorScript to handle it and conceal details that usually have no interest for the end user and it may show lines of code that ought to remain private. The ErrorScript handler might create a polite error page where things can be explained in human readable form, thus enabling the end user to provide meaningful feedback information.
In other cases an unmanageable conditions might take place in the data and this could demand an immediate interruption of the content generation. These abort conditions can be fired by the abort_page command, which in turn fires the execution of an AbortScript to handle the abnormal condition. Starting with Rivet 2.1.0 abort_page accepts a free form parameter that can be retrieved later with the command abort_code
Note | |
---|---|
This section explain the default request handling procedure which was written to let Rivet 3.0 work as a drop in replacement of any 2.x module. For a in-depth understanding of the new request processing mechanics please read the request processing section of the manual |
With the sole exception of .rvt templates, mod_rivet runs pure Tcl scripts at the global namespace. That means that every variable or procedure created in Tcl scripts resides by default in the "::" namespace (just like in traditional Tcl scripting) and they are persistent across different requests until explicitly unset or until the interpreter is deleted. You can create your own application namespaces to store data but it is important to remember that subsequent requests will in general be served by different child processes. Your application can rely on the fact that certain application data will be in the interpreter, but you shouldn't assume the state of a transaction spanning several pages can be stored in this way and be safely kept available to a specific client. Sessions exist for this purpose and Rivet ships its own session package with support for most of popular DBMS. Nonetheless storing data in the global namespace can be useful, even though scoping data in a namespace is recommended. I/O channels and database connections are examples of information usually specific to a process for which you don't want to pay the overhead of creating them at every request, probably causing a dramatic loss in the application performance.
A special role in the interpreter is played by the ::request namespace. The ::request namespace is deleted and recreated at every request and Rivet templates (.rvt files) are executed within it.
Unless you're fully qualifying variable names outside the ::request namespace, every variable and procedure created in .rvt files is by default placed in it and deleted before any other requests gets processed. It is therefore safe to create variables or object instances in template files and foresake about them: Rivet will take care of cleaning the namespace up and everything created inside the namespace will be destroyed.
Stage | Script | Namespace |
Apache Initialization | ServerInitScript | :: |
Child Initialization | GlobalInitScript | :: |
ChildInitScript | :: | |
Request Processing | BeforeScript | :: |
.rvt | ::request | |
.tcl | :: | |
AfterScript | :: | |
AbortScript | :: | |
AfterEveryScript | :: | |
Child Termination | ChildExitScript | :: |
Error Handling | ErrorScript | :: |