Boost logo

Boost-Commit :

From: lists.drrngrvy_at_[hidden]
Date: 2008-03-29 14:35:26


Author: drrngrvy
Date: 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
New Revision: 43934
URL: http://svn.boost.org/trac/boost/changeset/43934

Log:
Added documentation to the examples.
Added:
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/
      - copied from r43866, /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/
      - copied from r43912, /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/main.cpp
      - copied, changed from r43917, /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/main.cpp
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/
      - copied from r43917, /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/
Removed:
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/servers/
Text files modified:
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/main.cpp | 40 ++++++----
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp | 48 +++++++----
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/main.cpp | 4 +
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/main.cpp | 16 ++--
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/Jamfile.v2 | 7 -
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/main.cpp | 15 ++-
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/main.cpp | 6 +
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/main.cpp | 71 +++++------------
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/Jamfile.v2 | 6
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/main.cpp | 83 ++++----------------
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/Jamfile.v2 | 6
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/main.cpp | 154 +++++++++++++++------------------------
   12 files changed, 186 insertions(+), 270 deletions(-)

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,13 @@
+
+[section Amortization]
+
+This example uses Google.cTemplate to move HTML out of the program and into HTML template files, which would be easily editable by anyone familiar with HTML.
+
+[import main.cpp]
+
+[acgi_amort]
+
+See the [@../../example/acgi/amortization/main.cpp full source listing].
+
+[endsect][/ echo]
+

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/amortization/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -7,6 +7,8 @@
 //
 ////////////////////////////////////////////////////////////////
 //
+//[acgi_amort
+//
 // Amortization Calculator
 // -----------------------
 //
@@ -116,7 +118,8 @@
     // header - followed by a blank line - first though!).
     std::string output;
     tmpl->Expand(&output, &dict);
- std::cout<< output;
+ std::cout<< "Content-type: text/html\r\n\r\n"
+ << output;
   }else
   if (arg == "2")
   {
@@ -124,32 +127,37 @@
     // Should be expensive, but doesn't seem to impact performance hugely...
     std::string output;
     tmpl->Expand(&output, &dict);
- resp<< output;
+ resp<< content_type("text/html")
+ << output;
   }else
-// if (arg == "3")
-// {
-// // Expand the string to a vector<const_buffer>, which should minimise any
-// // copying of data. This requires a modified version of Google.cTemplate, but
-// // doesn't seem to add anything to performance. Will have to check if there's a
-// // better way to do it.
-// std::string s;
-// std::vector<boost::asio::const_buffer> out;
-//
-// tmpl->Expand(&s, &out, &dict);
-// write(req.client(), out);
-// }else
+ // if (arg == "3")
+ // {
+ // // Expand the string to a vector<const_buffer>, which should minimise any
+ // // copying of data. This requires a modified version of Google.cTemplate, but
+ // // doesn't seem to add anything to performance. Will have to check if there's a
+ // // better way to do it.
+ // std::string s;
+ // std::vector<boost::asio::const_buffer> out;
+ //
+ // tmpl->Expand(&s, &out, &dict);
+ // write(req.client(), out);
+ // }else
   if (arg == "4")
   {
     // Write the output directly to the request's client.
+ std::string headers("Content-type: text/html\r\n\r\n");
+ write(req.client(), buffer(headers));
     std::string output;
     tmpl->Expand(&output, &dict);
     write(req.client(), buffer(output));
   }else
- if (arg == "5")
+ if (arg == "5")
   {
     // An alternative to { arg == "1" }, which seems to be slightly faster.
     std::string output;
     tmpl->Expand(&output, &dict);
+ const char* headers = "Content-type: text/html\r\n\r\n";
+ std::cout.write(headers, strlen(headers));
     std::cout.write(output.c_str(), output.size());
   }else
   {
@@ -160,7 +168,6 @@
 int main()
 {
   try{
- std::cout<< "Content-type: text/html\r\n\r\n"; // just for debugging
     service s;
     request req(s);
     req.load(true);
@@ -174,4 +181,5 @@
       << "ERROR!! BOOM!";
   }
 }
+//]
 

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,11 @@
+
+[section aCGI Examples]
+
+[include hello_world/doc.qbk]
+
+[include echo/doc.qbk]
+
+[include amortization/doc.qbk]
+
+[endsect][/ cgi_examples]
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,11 @@
+
+[section Echo]
+
+[import main.cpp]
+
+[acgi_echo]
+
+See the [@../../example/acgi/echo/main.cpp full source listing].
+
+[endsect][/ echo]
+

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/echo/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -7,6 +7,8 @@
 //
 ////////////////////////////////////////////////////////////////
 //
+//[acgi_echo
+//
 // This example simply echoes all variables back to the user. ie.
 // the environment and the parsed GET, POST and cookie variables.
 // Note that GET and cookie variables come from the environment
@@ -15,15 +17,14 @@
 
 #include <boost/cgi/acgi.hpp>
 #include <fstream>
-//#include <google/template.h>
 
 using namespace std;
 using namespace boost::acgi;
 
 // This function writes the title and map contents to the ostream in an
 // HTML-encoded format (to make them easier on the eye).
-template<typename MapT, typename OStreamT>
-void show_map_contents(MapT& m, OStreamT& os, const std::string& title)
+template<typename OStream, Ttypename MapT>
+void show_map_contents(OStreamT& os, MapT& m, const std::string& title)
 {
   os<< "<h3>" << title << "</h3>";
   if (m.empty()) os<< "NONE<br />";
@@ -52,7 +53,7 @@
       {
         response resp;
         resp
- << content_type("text/plain")
+ << content_type("text/html")
         << "Error " << ec.value() << ": " << ec.message() << "<p />"
            "--Original message follows--"
            "<p />";
@@ -73,34 +74,43 @@
              "</form><p />"
              "boundary marker = " << req.boundary_marker() << "<p />";
 
- show_map_contents(req.GET(), resp, "GET Variables");
- show_map_contents(req.POST(), resp, "POST Variables");
- show_map_contents(req.cookie(), resp, "Cookie Variables");
- show_map_contents(req.env(), resp, "Environment Variables");
+ show_map_contents(resp, req[get_data], "GET Variables");
+ show_map_contents(resp, req[post_data], "POST Variables");
+ show_map_contents(resp, req[cookie_data], "Cookie Variables");
+ show_map_contents(resp, req[env_data], "Environment Variables");
 
- //resp<< content_type("text/html");
- resp.send(req.client());
+ return_(resp, req, 0); // All ok.
 
- }catch(boost::system::error_code& ec){
+ }
+ catch(boost::system::system_error& ec)
+ { // This is the type of error this library throws.
       response resp;
- resp<< content_type("text/plain") << "Error " << ec.value() << ": "
- << ec.message();
- }catch(std::exception& e){
+ resp<< content_type("text/plain") << "Error " << ec.code() << ": "
+ << ec.what()
+ << http::internal_server_error; // note the status_code
+ return_(resp, req, 1);
+ }
+ catch(std::exception* e)
+ {
       response resp;
- resp<< content_type("text/plain") << "Error: " << e.what();
+ resp<< content_type("text/plain") << "Error: " << e->what()
+ << http::internal_server_error;
       return_(resp, req, 2);
     }
 
+ // The request object will be destroyed before the next exception handlers
+ // are reached.
+
   }catch(std::exception* e){
- std::cout
+ std::cerr
     << content_type("text/plain").content
     << "Exception: " << e->what();
- //resp.send(req.client());
     return 3;
   }catch(...){
- std::cout<< content_type("text/plain").content
+ std::cerr<< content_type("text/plain").content
              << "Unknown error.";
     return 4;
   }
- return 0;
 }
+//]
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,11 @@
+
+[section Hello world]
+
+[import main.cpp]
+
+[acgi_hello_world]
+
+See the [@../../example/acgi/hello_world/main.cpp full source listing].
+
+[endsect][/ hello_world]
+

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -7,6 +7,8 @@
 //
 ////////////////////////////////////////////////////////////////
 //
+//[acgi_hello_world
+//
 // The simplest CGI program, outputs only "Hello there, universe."
 //
 
@@ -30,3 +32,5 @@
   // Leave this function, after sending the response and closing the request.
   return_(resp, req, 0); // Note the underscore: returns "0" to the OS.
 }
+//]
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,9 @@
+
+[section CGI Examples]
+
+[include hello_world/doc.qbk]
+
+[include echo/doc.qbk]
+
+[endsect][/ cgi_examples]
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,11 @@
+
+[section Echo]
+
+[import main.cpp]
+
+[cgi_echo]
+
+See the [@../../example/cgi/echo/main.cpp full source listing].
+
+[endsect][/ echo]
+

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/echo/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -7,22 +7,22 @@
 //
 ////////////////////////////////////////////////////////////////
 //
+//[cgi_echo
+//
 // This example simply echoes all variables back to the user. ie.
 // the environment and the parsed GET, POST and cookie variables.
 // Note that GET and cookie variables come from the environment
 // variables QUERY_STRING and HTTP_COOKIE respectively.
 //
 
-//[file
 #include <boost/cgi/cgi.hpp>
 
-using namespace std;
 using namespace boost::cgi;
 
 // This function writes the title and map contents to the ostream in an
 // HTML-encoded format (to make them easier on the eye).
-template<typename MapT, typename OStreamT>
-void show_map_contents(MapT& m, OStreamT& os, const std::string& title)
+template<typename OStreamT, typename MapT>
+void show_map_contents(OStreamT& os, MapT& m, const std::string& title)
 {
   os<< "<h3>" << title << "</h3>";
   if (m.empty()) os<< "NONE<br />";
@@ -40,10 +40,10 @@
 
   response resp;
 
- show_map_contents(req.env(), resp, "Environment Variables");
- show_map_contents(req.GET(), resp, "GET Variables");
- show_map_contents(req.POST(), resp, "POST Variables");
- show_map_contents(req.cookie(), resp, "Cookie Variables");
+ show_map_contents(resp, req[env_data], "Environment Variables");
+ show_map_contents(resp, req[get_data], "GET Variables");
+ show_map_contents(resp, req[post_data], "POST Variables");
+ show_map_contents(resp, req[cookie_data], "Cookie Variables");
 
   // Note that this (and any other) HTTP header can go either before or after
   // the response contents.

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/Jamfile.v2
==============================================================================
--- /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/Jamfile.v2 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -4,14 +4,13 @@
 # (See accompanying file LICENSE_1_0.txt or copy
 # at http://www.boost.org/LICENSE_1_0.txt)
 
-project boost.cgi.examples.acgi.hello_world
- ;
+project boost.cgi.examples.cgi.hello_world ;
 
-exe acgi_hello_world : main.cpp /boost/regex/ ;
+exe cgi_hello_world : main.cpp /boost/regex/ ;
 
 # Our install rule (builds binaries and copies them to <location>)
 install install
- : acgi_hello_world
+ : cgi_hello_world
  : <location>$(cgi-bin)
  ;
 

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,11 @@
+
+[section Hello world]
+
+[import main.cpp]
+
+[cgi_hello_world]
+
+See the [@../../example/cgi/hello_world/main.cpp full source listing].
+
+[endsect][/ hello_world]
+

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/main.cpp
==============================================================================
--- /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/acgi/hello_world/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/cgi/hello_world/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -7,26 +7,27 @@
 //
 ////////////////////////////////////////////////////////////////
 //
+//[cgi_hello_world
+//
 // The simplest CGI program, outputs only "Hello there, universe."
 //
 
-#include <boost/cgi/acgi.hpp>
-#include <boost/cgi/return.hpp>
+#include <boost/cgi/cgi.hpp>
 
-using namespace std;
-using namespace boost::acgi;
+using namespace boost::cgi;
 
 int main()
 {
- service s; // This becomes useful with async operations.
- request req(s); // Our request (POST data won't be parsed yet).
+ request req; // Our request (POST data won't be parsed yet).
   response resp; // A response object to make our lives easier.
 
   // This is a minimal response. The content_type(...) may go before or after
   // the response text.
- resp<< content_type("text/html")
+ resp<< content_type("text/plain")
       << "Hello there, universe.";
 
   // Leave this function, after sending the response and closing the request.
   return_(resp, req, 0); // Note the underscore: returns "0" to the OS.
 }
+//]
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,31 @@
+
+[section Examples]
+
+The examples can be built by going into their directory and typing `bjam`. If you have a server set up and wish to test the applications behind them, you can automatically copy them to your server's cgi-bin (or fcgi-bin or scgi-bin) one of two ways:
+
+[h4 Command Line]
+
+``$ bjam install --cgi-bin=/usr/lib/cgi-bin``
+
+Installs the CGI program (or set of programs) into `/usr/lib/cgi-bin`. If you want to install FastCGI examples from the `/libs/cgi/example/fcgi/` directory, for instance, type the above but replace `--cgi-bin=...` with `--fcgi-bin=...`.
+
+[h4 Environment Variables]
+
+Set the environment variable(s) `BOOST_CGI_BIN_PATH` (or `BOOST_FCGI_BIN_PATH`/`BOOST_SCGI_BIN_PATH`), then type:
+
+``$ bjam install``
+
+The example(s) will be installed into the relevant directory.
+
+[note
+ The command line option will override the environment variable, so you can use the environment variables for default installation.
+]
+
+[include cgi/doc.qbk]
+
+[include acgi/doc.qbk]
+
+[include fcgi/doc.qbk]
+
+[endsect]
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,13 @@
+
+[section Amortization]
+
+This example uses Google.cTemplate to move HTML out of the program and into HTML template files, which would be easily editable by anyone familiar with HTML.
+
+[import main.cpp]
+
+[fcgi_amort]
+
+See the [@../../example/fcgi/amortization/main.cpp full source listing].
+
+[endsect][/ echo]
+

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/amortization/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -7,6 +7,8 @@
 //
 ////////////////////////////////////////////////////////////////
 //
+//[fcgi_amort
+//
 // Amortization Calculator
 // -----------------------
 //
@@ -185,7 +187,8 @@
   try{
 
     service s;
- acceptor a(s, true);
+ acceptor a(s, true); // The true means default-initialise.
+ // Unfortunately this only works on linux w. apache for now.
 
     accept_requests(a);
     
@@ -199,4 +202,5 @@
     std::cerr<< "ERROR!! BOOM!" << std::endl;
   }
 }
+//]
 

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,18 @@
+
+[section FastCGI Examples]
+
+[include echo/doc.qbk]
+
+[include amortization/doc.qbk]
+
+[section Servers]
+
+[include server1/doc.qbk]
+
+[include server2/doc.qbk]
+
+[include server3/doc.qbk]
+
+[endsect]
+
+[endsect]

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/echo/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,11 @@
+
+[section Echo]
+
+[import main.cpp]
+
+[fcgi_echo]
+
+See the [@../../example/fcgi/echo/main.cpp full source listing].
+
+[endsect][/ echo]
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,12 @@
+
+[section Server 1]
+
+This is a basic example demonstrating how using a `Server` can make your programs less dependent on a specific protocol.
+
+[import main.cpp]
+
+[fcgi_server1]
+
+[endsect][/ server_1]
+
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,14 @@
+
+[section Server 2]
+
+This is a very slight step up from the Server 1 example. It accepts new requests asynchronously, loads them synchronously and then handles them in a background thread while repeating the accept cycle.
+
+The asynchronous functions are run in ten background threads (see `server::run`).
+
+[import main.cpp]
+
+[fcgi_server2]
+
+[endsect][/ server_2]
+
+

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -34,13 +34,11 @@
 using namespace std;
 using namespace boost::fcgi;
 
-// This is a file to put internal logging info into
-#define LOG_FILE "/var/www/log/fcgi_server2.txt"
 
 // This function writes the title and map contents to the ostream in an
 // HTML-encoded format (to make them easier on the eye).
-template<typename Map, typename OStream>
-void format_map(Map& m, OStream& os, const std::string& title)
+template<typename OStream, typename Map>
+void format_map(OStream& os, Map& m, const std::string& title)
 {
   os<< "<h2>" << title << "</h2>";
   if (m.empty()) os<< "NONE<br />";
@@ -51,32 +49,13 @@
   }
 }
 
-/// The handle_request member function is used to handle requests.
+/// Handle one request and return.
 /**
- * A struct is used here just so a single log file can be shared between
- * requests. Note that access to the log file isn't synchronised (this doesn't
- * matter with this example).
+ * If it returns != 0 then an error has occurred. Sets ec to the error_code
+ * corresponding to the error.
  */
-struct request_handler
-{
- request_handler(const std::string& file_name)
- : log_(file_name.c_str())
- {
- if (!log_)
- {
- std::cerr<< "[fcgi] Couldn't open file: \"" LOG_FILE "\"." << endl;
- throw std::runtime_error("Couldn't open log file");
- }
-
- log_<< boost::posix_time::second_clock::local_time() << endl;
- }
-
- int handle_request(fcgi::request& req, boost::system::error_code& ec)
+int handle_request(fcgi::request& req, boost::system::error_code& ec)
   {
- std::ofstream log_(LOG_FILE, std::ios::app);
- //log_<< "Handling request" << endl
- // << "QUERY_STRING := " << req.query_string() << std::endl;
-
     // Construct a `response` object (makes writing/sending responses easier).
     response resp;
 
@@ -87,13 +66,9 @@
         << "Hello there, universe!<p />";
 
     // Use the function defined above to show some of the request data.
- format_map(req.env(), resp, "Environment Variables");
- format_map(req.GET(), resp, "GET Variables");
- format_map(req.cookie(), resp, "Cookie Variables");
-
- // Response headers can be added at any time before send/flushing it:
- resp<< "<content-length == " << content_length(resp.content_length())
- << content_length(resp.content_length());
+ format_map(resp, req[env_data], "Environment Variables");
+ format_map(resp, req[get_data], "GET Variables");
+ format_map(resp, req[cookie_data], "Cookie Variables");
 
     //log_<< "Handled request, handling another." << std::endl;
 
@@ -109,10 +84,6 @@
     // Note: in this case `program_status == 0`.
   }
 
-private:
- std::ofstream log_;
-};
-
 
 /// The server is used to abstract away protocol-specific setup of requests.
 /**
@@ -126,6 +97,8 @@
 class server
 {
 public:
+ typedef fcgi::service service_type;
+ typedef fcgi::acceptor acceptor_type;
   typedef fcgi::request request_type;
   typedef boost::function<
             int ( request_type&
@@ -138,7 +111,7 @@
     , acceptor_(service_)
   {}
 
- void run()
+ void run(int num_threads = 0)
   {
     // Create a new request (on the heap - uses boost::shared_ptr<>).
     request_type::pointer new_request = request_type::create(service_);
@@ -146,7 +119,12 @@
     requests_.insert(new_request);
 
     start_accept(new_request);
- service_.run();
+ boost::thread_group tgroup;
+ for(int i(num_threads); i != 0; --i)
+ {
+ tgroup.create_thread(boost::bind(&service_type::run, &service_));
+ }
+ tgroup.join_all();
   }
 
   void start_accept(request_type::pointer& new_request)
@@ -196,21 +174,18 @@
 
 private:
   function_type handler_;
- fcgi::service service_;
- fcgi::acceptor acceptor_;
+ service_type service_;
+ acceptor_type acceptor_;
   std::set<request_type::pointer> requests_;
 };
 
 int main()
 try
 {
- request_handler rh(LOG_FILE);
-
- server s(boost::bind(&request_handler::handle_request
- , &rh, _1, _2)
- );
+ server s(&handle_request);
 
- s.run();
+ // Run the server with 10 threads handling the asynchronous functions.
+ s.run(10);
 
   return 0;
   

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/Jamfile.v2
==============================================================================
--- /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/Jamfile.v2 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -1,11 +1,11 @@
 
-project cgi.examples.fcgi.sync_server ;
+project cgi.examples.fcgi.server3 ;
 
-exe fcgi_server1 : main.cpp ;
+exe fcgi_server3 : main.cpp ;
 
 install install
   :
- fcgi_server1
+ fcgi_server3
   :
     <location>$(fcgi-bin)
   ;

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/doc.qbk 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -0,0 +1,12 @@
+
+[section Server 3]
+
+This is essentially the same as the Server 1 example, but it runs handles mutiple requests ['simultaneously] by calling `server::run` in a number of threads.
+
+[import main.cpp]
+
+[fcgi_server3]
+
+[endsect][/ server_3]
+
+

Copied: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/main.cpp (from r43917, /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/main.cpp)
==============================================================================
--- /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server1/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server3/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -1,4 +1,4 @@
-// -- server1/main.hpp --
+// -- server3/main.hpp --
 //
 // Copyright (c) Darren Garvey 2007.
 // Distributed under the Boost Software License, Version 1.0.
@@ -7,7 +7,7 @@
 //
 ////////////////////////////////////////////////////////////////
 //
-//[fcgi_server1
+//[fcgi_server3
 //
 // This example simply echoes all variables back to the user. ie.
 // the environment and the parsed GET, POST and cookie variables.
@@ -21,7 +21,7 @@
 //
 
 #include <fstream>
-#include <boost/bind.hpp>
+#include <boost/thread.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
 #include <boost/program_options/environment_iterator.hpp>
 
@@ -30,66 +30,21 @@
 using namespace std;
 using namespace boost::fcgi;
 
-// This is a file to put internal logging info into
-#define LOG_FILE "/var/www/log/fcgi_server1.txt"
-
-// This function writes the title and map contents to the ostream in an
-// HTML-encoded format (to make them easier on the eye).
-template<typename Map, typename OStream>
-void format_map(Map& m, OStream& os, const std::string& title)
-{
- os<< "<h2>" << title << "</h2>";
- if (m.empty()) os<< "NONE<br />";
- for (typename Map::const_iterator i = m.begin(), end = m.end()
- ; i != end; ++i)
- {
- os<< "<b>" << i->first << "</b> = <i>" << i->second << "</i><br />";
- }
-}
-
-/// The handle_request member function is used to handle requests.
+/// Handle one request and return.
 /**
- * A struct is used here just so a single log file can be shared between
- * requests. Note that access to the log file isn't synchronised (this doesn't
- * matter with this example).
+ * If it returns != 0 then an error has occurred. Sets ec to the error_code
+ * corresponding to the error.
  */
-struct request_handler
-{
- request_handler(const std::string& file_name)
- : log_(file_name.c_str())
- {
- if (!log_)
- {
- std::cerr<< "[fcgi] Couldn't open file: \"" LOG_FILE "\"." << endl;
- throw std::runtime_error("Couldn't open log file");
- }
-
- log_<< boost::posix_time::second_clock::local_time() << endl;
- }
-
- int handle_request(fcgi::request& req, boost::system::error_code& ec)
+int handle_request(fcgi::request& req, boost::system::error_code& ec)
   {
- std::ofstream log_(LOG_FILE, std::ios::app);
- //log_<< "Handling request" << endl
- // << "QUERY_STRING := " << req.query_string() << std::endl;
-
     // Construct a `response` object (makes writing/sending responses easier).
     response resp;
 
     // Responses in CGI programs require at least a 'Content-type' header. The
     // library provides helpers for several common headers:
- resp<< content_type("text/html")
+ resp<< content_type("text/plain")
     // You can also stream text to a response object.
- << "Hello there, universe!<p />";
-
- // Use the function defined above to show some of the request data.
- format_map(req.env(), resp, "Environment Variables");
- format_map(req.GET(), resp, "GET Variables");
- format_map(req.cookie(), resp, "Cookie Variables");
-
- // Response headers can be added at any time before send/flushing it:
- resp<< "<content-length == " << content_length(resp.content_length())
- << content_length(resp.content_length());
+ << "Hello there, universe!";
 
     //log_<< "Handled request, handling another." << std::endl;
 
@@ -105,11 +60,6 @@
     // Note: in this case `program_status == 0`.
   }
 
-private:
- std::ofstream log_;
-};
-
-
 /// The server is used to abstract away protocol-specific setup of requests.
 /**
  * This server only works with FastCGI, but as you can see in the
@@ -175,13 +125,16 @@
 int main()
 try
 {
- request_handler rh(LOG_FILE);
-
- server s(boost::bind(&request_handler::handle_request
- , &rh, _1, _2)
- );
+ server s(&handle_request);
 
- return s.run();
+ // Run the server in ten threads.
+ // => Handle ten requests simultaneously
+ boost::thread_group tgroup;
+ for(int i(10); i != 0; --i)
+ {
+ tgroup.create_thread(boost::bind(&server::run, &s));
+ }
+ tgroup.join_all();
   
 }catch(boost::system::system_error& se){
   cerr<< "[fcgi] System error: " << se.what() << endl;

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/Jamfile.v2
==============================================================================
--- /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/Jamfile.v2 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -1,11 +1,11 @@
 
-project cgi.examples.fcgi.server2 ;
+project cgi.examples.fcgi.server4 ;
 
-exe fcgi_server2 : main.cpp ;
+exe fcgi_server4 : main.cpp ;
 
 install install
   :
- fcgi_server2
+ fcgi_server4
   :
     <location>$(fcgi-bin)
   ;

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/main.cpp
==============================================================================
--- /sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server2/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/server4/main.cpp 2008-03-29 14:35:24 EDT (Sat, 29 Mar 2008)
@@ -1,4 +1,4 @@
-// -- server2/main.hpp --
+// -- server4/main.hpp --
 //
 // Copyright (c) Darren Garvey 2007.
 // Distributed under the Boost Software License, Version 1.0.
@@ -7,7 +7,7 @@
 //
 ////////////////////////////////////////////////////////////////
 //
-//[fcgi_server2
+//[fcgi_server4
 //
 // This example simply echoes all variables back to the user. ie.
 // the environment and the parsed GET, POST and cookie variables.
@@ -21,9 +21,6 @@
 // Unlike in the server1 example, the server class in this example uses
 // asynchronous functions, to increase throughput.
 //
-//
-// **FIXME**
-// This is slower than the server1 example, which is stupid.
 
 #include <fstream>
 #include <boost/date_time/posix_time/posix_time.hpp>
@@ -34,85 +31,33 @@
 using namespace std;
 using namespace boost::fcgi;
 
-// This is a file to put internal logging info into
-#define LOG_FILE "/var/www/log/fcgi_server2.txt"
-
-// This function writes the title and map contents to the ostream in an
-// HTML-encoded format (to make them easier on the eye).
-template<typename Map, typename OStream>
-void format_map(Map& m, OStream& os, const std::string& title)
-{
- os<< "<h2>" << title << "</h2>";
- if (m.empty()) os<< "NONE<br />";
- for (typename Map::const_iterator i = m.begin(), end = m.end()
- ; i != end; ++i)
- {
- os<< "<b>" << i->first << "</b> = <i>" << i->second << "</i><br />";
- }
-}
-
-/// The handle_request member function is used to handle requests.
+/// Handle one request and return.
 /**
- * A struct is used here just so a single log file can be shared between
- * requests. Note that access to the log file isn't synchronised (this doesn't
- * matter with this example).
+ * If it returns != 0 then an error has occurred. Sets ec to the error_code
+ * corresponding to the error.
  */
-struct request_handler
+int handle_request(fcgi::request& req, fcgi::response& resp
+ , boost::system::error_code& ec)
 {
- request_handler(const std::string& file_name)
- : log_(file_name.c_str())
- {
- if (!log_)
- {
- std::cerr<< "[fcgi] Couldn't open file: \"" LOG_FILE "\"." << endl;
- throw std::runtime_error("Couldn't open log file");
- }
-
- log_<< boost::posix_time::second_clock::local_time() << endl;
- }
-
- int handle_request(fcgi::request& req, boost::system::error_code& ec)
- {
- std::ofstream log_(LOG_FILE, std::ios::app);
- //log_<< "Handling request" << endl
- // << "QUERY_STRING := " << req.query_string() << std::endl;
-
- // Construct a `response` object (makes writing/sending responses easier).
- response resp;
-
- // Responses in CGI programs require at least a 'Content-type' header. The
- // library provides helpers for several common headers:
- resp<< content_type("text/html")
- // You can also stream text to a response object.
- << "Hello there, universe!<p />";
-
- // Use the function defined above to show some of the request data.
- format_map(req.env(), resp, "Environment Variables");
- format_map(req.GET(), resp, "GET Variables");
- format_map(req.cookie(), resp, "Cookie Variables");
-
- // Response headers can be added at any time before send/flushing it:
- resp<< "<content-length == " << content_length(resp.content_length())
- << content_length(resp.content_length());
-
- //log_<< "Handled request, handling another." << std::endl;
-
- // This funky macro finishes up:
- return_(resp, req, 0);
- // It is equivalent to the below, where the third argument is represented by
- // `program_status`:
- //
- // resp.send(req.client());
- // req.close(resp.status(), program_status);
- // return program_status;
- //
- // Note: in this case `program_status == 0`.
- }
-
-private:
- std::ofstream log_;
-};
+ // Responses in CGI programs require at least a 'Content-type' header. The
+ // library provides helpers for several common headers:
+ resp<< content_type("text/html")
+ // You can also stream text to a response object.
+ << "Hello there, universe!<p />";
+
+ // Use the function defined above to show some of the request data.
+ //format_map(req.env(), resp, "Environment Variables");
+ //format_map(req.GET(), resp, "GET Variables");
+ //format_map(req.cookie(), resp, "Cookie Variables");
+
+ // Response headers can be added at any time before send/flushing it:
+ resp<< "content-length == " << content_length(resp.content_length())
+ << content_length(resp.content_length());
 
+ //log_<< "Handled request, handling another." << std::endl;
+ //
+ return 0;
+}
 
 /// The server is used to abstract away protocol-specific setup of requests.
 /**
@@ -126,9 +71,12 @@
 class server
 {
 public:
+ typedef fcgi::service service_type;
+ typedef fcgi::acceptor acceptor_type;
   typedef fcgi::request request_type;
+ typedef fcgi::response response_type;
   typedef boost::function<
- int ( request_type&
+ int ( request_type&, response_type&
                 , boost::system::error_code&)
> function_type;
 
@@ -138,7 +86,7 @@
     , acceptor_(service_)
   {}
 
- void run()
+ void run(int num_threads = 1)
   {
     // Create a new request (on the heap - uses boost::shared_ptr<>).
     request_type::pointer new_request = request_type::create(service_);
@@ -146,7 +94,15 @@
     requests_.insert(new_request);
 
     start_accept(new_request);
- service_.run();
+
+ // Run all asynchronous functions in `num_threads` threads.
+ boost::thread_group tgroup;
+ for(int i(num_threads); i != 0; --i)
+ {
+ tgroup.create_thread(boost::bind(&service_type::run, &service_));
+ }
+ // Make sure we don't leave this function until all threads have exited.
+ tgroup.join_all();
   }
 
   void start_accept(request_type::pointer& new_request)
@@ -168,11 +124,16 @@
 
     req->load(ec, true);
 
+ boost::shared_ptr<response_type> new_response(new response_type);
+ responses_.insert(new_response);
+
     //req->async_load(boost::bind(&server::handle_request, this
     // , req, boost::asio::placeholders::error)
     // , true);
 
- service_.post(boost::bind(&server::handle_request, this, req, ec));
+ service_.post(boost::bind(&server::handle_request, this
+ , req, new_response, ec)
+ );
 
     // Create a new request (on the heap - uses boost::shared_ptr<>).
     request_type::pointer new_request = request_type::create(service_);
@@ -183,33 +144,34 @@
   }
 
   void handle_request(request_type::pointer req
+ , boost::shared_ptr<response_type> resp
                      , boost::system::error_code ec)
   {
- handler_(*req, ec);
- if (ec)
+ int program_status( handler_(*req, *resp, ec) );
+ if (ec
+ || resp->send(*req, ec)
+ || req->close(resp->status(), program_status, ec))
     {
- //std::cerr<< "Request handled, but ended in error: " << ec.message()
- // << std::endl;
+ std::cerr<< "Couldn't send response/close request." << std::endl;
     }
- start_accept(req);
+ else
+ start_accept(req);
   }
 
 private:
   function_type handler_;
- fcgi::service service_;
- fcgi::acceptor acceptor_;
+ service_type service_;
+ acceptor_type acceptor_;
   std::set<request_type::pointer> requests_;
+ std::set<boost::shared_ptr<response_type> > responses_;
 };
 
 int main()
 try
 {
- request_handler rh(LOG_FILE);
-
- server s(boost::bind(&request_handler::handle_request
- , &rh, _1, _2)
- );
+ server s(&handle_request);
 
+ // Run the server.
   s.run();
 
   return 0;


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk