summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorjxh <jxh@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1997-09-10 03:08:20 +0000
committerjxh <jxh@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1997-09-10 03:08:20 +0000
commit7a2ae5dd39f386b16dcbd6ff444bae8d7e68e1d5 (patch)
tree90acf7dbd0dab603a29fc9a4b206cca6dee6a6d7 /apps
parentd4e3cf7d35e3e840fcc6806dbbcd0c7a3fcd77f0 (diff)
downloadATCD-7a2ae5dd39f386b16dcbd6ff444bae8d7e68e1d5.tar.gz
Changes which answer questions brought up in design review. Mostly
additional comments. Also changes to have a task spawn a number of threads rather than iterating through calls to the activate method.
Diffstat (limited to 'apps')
-rw-r--r--apps/JAWS/server/HTTP_Server.cpp133
-rw-r--r--apps/JAWS/server/HTTP_Server.h24
-rw-r--r--apps/JAWS/server/main.cpp10
3 files changed, 86 insertions, 81 deletions
diff --git a/apps/JAWS/server/HTTP_Server.cpp b/apps/JAWS/server/HTTP_Server.cpp
index f8e389d62ba..c525737c1e3 100644
--- a/apps/JAWS/server/HTTP_Server.cpp
+++ b/apps/JAWS/server/HTTP_Server.cpp
@@ -7,6 +7,7 @@
#include "IO.h"
#include "HTTP_Server.h"
+// class is overkill
class HTTP_Server_Anchor
{
public:
@@ -30,7 +31,7 @@ HTTP_Server::parse_args (int argc,
int c;
int thr_strategy = 0;
int io_strategy = 0;
- char *prog = argc > 0 ? argv[0] : "Sock_Server";
+ char *prog = argc > 0 ? argv[0] : "HTTP_Server";
// Set some defaults
this->port_ = 0;
@@ -69,6 +70,7 @@ HTTP_Server::parse_args (int argc,
case 'f':
if (ACE_OS::strcmp (get_opt.optarg, "THR_BOUND") == 0)
{
+ // What happened here?
}
else if (ACE_OS::strcmp (get_opt.optarg, "THR_DAEMON") == 0)
{
@@ -91,16 +93,18 @@ HTTP_Server::parse_args (int argc,
break;
}
- if (this->port_ == 0)
+ // No magic numbers.
+ if (this->port_ <= 0)
this->port_ = 5432;
- if (this->threads_ == 0)
+ if (this->threads_ <= 0)
this->threads_ = 5;
- if (this->backlog_ == 0)
+ // Don't use number of threads as default
+ if (this->backlog_ <= 0)
this->backlog_ = this->threads_;
- this->strategy_ = thr_strategy + io_strategy;
+ this->strategy_ = thr_strategy | io_strategy;
- prog = prog;
+ ACE_UNUSED_ARG (prog);
ACE_DEBUG ((LM_DEBUG,
"in HTTP_Server::init, %s port = %d, number of threads = %d\n",
prog, this->port_, this->threads_));
@@ -108,25 +112,30 @@ HTTP_Server::parse_args (int argc,
int
HTTP_Server::init (int argc, char *argv[])
+ // Document this function
{
+ // Ignore signals generated when a connection is broken unexpectedly.
ACE_Sig_Action sig (ACE_SignalHandler (SIG_IGN), SIGPIPE);
ACE_UNUSED_ARG (sig);
+ // Parse arguments which sets the initial state.
this->parse_args (argc, argv);
+ // Choose what concurrency strategy to run.
switch (this->strategy_)
{
- case 2:
+ case (JAWS::POOL | JAWS::ASYNCH) :
return this->asynch_thread_pool ();
- case 1:
+ case (JAWS::PER_REQUEST | JAWS::SYNCH) :
return this->thread_per_request ();
- case 0:
+ case (JAWS::POOL | JAWS::SYNCH) :
default:
return this->synch_thread_pool ();
}
- ACE_NOTREACHED(return 0);
+
+ ACE_NOTREACHED (return 0);
}
int
@@ -136,57 +145,43 @@ HTTP_Server::fini (void)
return 0;
}
+
int
HTTP_Server::synch_thread_pool (void)
{
+ // Main thread opens the acceptor
if (this->acceptor_.open (ACE_INET_Addr (this->port_), 1,
PF_INET, this->backlog_) == -1)
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "HTTP_Acceptor::open"), -1);
- for (int i = 0; i < this->threads_; i++)
- {
- Synch_Thread_Pool_Task *t;
-
- ACE_NEW_RETURN (t,
- Synch_Thread_Pool_Task (this->acceptor_, this->tm_),
- -1);
-
- if (t->open () != 0)
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Thread_Pool_Task::open"), -1);
- }
+ // Create a pool of threads to handle incoming connections.
+ Synch_Thread_Pool_Task t (this->acceptor_, this->tm_, this->threads_);
this->tm_.wait ();
return 0;
}
Synch_Thread_Pool_Task::Synch_Thread_Pool_Task (HTTP_Acceptor &acceptor,
- ACE_Thread_Manager &tm)
+ ACE_Thread_Manager &tm,
+ int threads)
: ACE_Task<ACE_NULL_SYNCH> (&tm),
acceptor_ (acceptor)
{
-}
-
-int
-Synch_Thread_Pool_Task::open (void *args)
-{
- ACE_UNUSED_ARG (args);
-
- if (this->activate (THR_DETACHED | THR_NEW_LWP) == -1)
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Synch_Thread_Pool_Task::open"),
- -1);
-
- return 0;
+ if (this->activate (THR_DETACHED | THR_NEW_LWP, threads) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "Synch_Thread_Pool_Task::open"));
}
int
Synch_Thread_Pool_Task::svc (void)
{
+ // Creates a factory of HTTP_Handlers binding to synchronous I/O strategy
Synch_HTTP_Handler_Factory factory;
for (;;)
{
ACE_SOCK_Stream stream;
+ // Lock in this accept. When it returns, we have a connection.
if (this->acceptor_.accept (stream) == -1)
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "HTTP_Acceptor::accept"), -1);
@@ -195,8 +190,12 @@ Synch_Thread_Pool_Task::svc (void)
ACE_Message_Block (HTTP_Handler::MAX_REQUEST_SIZE + 1),
-1);
+ // Create an HTTP Handler to handle this request
HTTP_Handler *handler = factory.create_http_handler ();
handler->open (stream.get_handle (), *mb);
+ // Handler is destroyed when the I/O puts the Handler into the
+ // done state.
+
mb->release ();
ACE_DEBUG ((LM_DEBUG,
" (%t) in Synch_Thread_Pool_Task::svc, recycling\n"));
@@ -211,12 +210,16 @@ HTTP_Server::thread_per_request (void)
int grp_id = -1;
// thread per request
+ // Main thread opens the acceptor
if (this->acceptor_.open (ACE_INET_Addr (this->port_), 1,
PF_INET, this->backlog_) == -1)
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "HTTP_Acceptor::open"), -1);
ACE_SOCK_Stream stream;
- const ACE_Time_Value wait_time (0,10);
+
+ // When we are throttling, this is the amount of time to wait before
+ // checking for runnability again.
+ const ACE_Time_Value wait_time (0, 10);
for (;;)
{
@@ -224,12 +227,14 @@ HTTP_Server::thread_per_request (void)
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "HTTP_Acceptor::accept"), -1);
Thread_Per_Request_Task *t;
+ // Pass grp_id as a constructor param instead of into open.
ACE_NEW_RETURN (t, Thread_Per_Request_Task (stream.get_handle (),
- this->tm_),
+ this->tm_,
+ grp_id),
-1);
- if (t->open (&grp_id) != 0)
+ if (t->open () != 0)
ACE_ERROR_RETURN ((LM_ERROR,
"%p\n", "Thread_Per_Request_Task::open"),
-1);
@@ -248,25 +253,28 @@ HTTP_Server::thread_per_request (void)
}
Thread_Per_Request_Task::Thread_Per_Request_Task (ACE_HANDLE handle,
- ACE_Thread_Manager &tm)
+ ACE_Thread_Manager &tm,
+ int &grp_id)
: ACE_Task<ACE_NULL_SYNCH> (&tm),
- handle_ (handle)
+ handle_ (handle),
+ grp_id_ (grp_id)
{
}
+
+// HEY! Add a method to the thread_manager to return total number of
+// threads managed in all the tasks.
+
int
-Thread_Per_Request_Task::open (void *args)
+Thread_Per_Request_Task::open (void *)
{
int status = -1;
- int *grp_id = &status;
- if (args != 0)
- grp_id = (int *) args;
-
- if (*grp_id == -1)
- status = *grp_id = this->activate (THR_DETACHED | THR_NEW_LWP);
+ if (this->grp_id_ == -1)
+ status = this->grp_id_ = this->activate (THR_DETACHED | THR_NEW_LWP);
else
- status = this->activate (THR_DETACHED | THR_NEW_LWP, 1, 0, -1, *grp_id, 0);
+ status = this->activate (THR_DETACHED | THR_NEW_LWP,
+ 1, 0, -1, this->grp_id_, 0);
if (status == -1)
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Thread_Per_Request_Task::open"),
@@ -297,7 +305,8 @@ Thread_Per_Request_Task::close (u_long)
}
// Understanding the code below requires understanding of the
-// WindowsNT asynchronous completion notification mechanism.
+// WindowsNT asynchronous completion notification mechanism and the
+// Proactor Pattern.
// (1) The application submits an asynchronous I/O request to the
// operating system and a special handle with it (Asynchronous
@@ -328,19 +337,12 @@ HTTP_Server::asynch_thread_pool (void)
"ACE_Asynch_Acceptor::open"), -1);
// Create the thread pool.
- for (int i = 0; i < this->threads_; i++)
- {
- // Register threads with the proactor and thread manager.
- Asynch_Thread_Pool_Task *t;
- ACE_NEW_RETURN (t,
- Asynch_Thread_Pool_Task (*ACE_Proactor::instance (),
- this->tm_),
- -1);
- if (t->open () != 0)
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
- "Thread_Pool_Task::open"), -1);
- // The proactor threads are waiting on the I/O Completion Port.
- }
+ // Register threads with the proactor and thread manager.
+ Asynch_Thread_Pool_Task t (*ACE_Proactor::instance (),
+ this->tm_,
+ this->threads_);
+
+ // The proactor threads are waiting on the I/O Completion Port.
// Wait for the threads to finish.
return this->tm_.wait ();
@@ -356,16 +358,9 @@ Asynch_Thread_Pool_Task::Asynch_Thread_Pool_Task (ACE_Proactor &proactor,
: ACE_Task<ACE_NULL_SYNCH> (&tm),
proactor_ (proactor)
{
-}
-
-int
-Asynch_Thread_Pool_Task::open (void *args)
-{
if (this->activate () == -1)
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Asynch_Thread_Pool_Task::open"),
- -1);
-
- return 0;
+ );
}
int
diff --git a/apps/JAWS/server/HTTP_Server.h b/apps/JAWS/server/HTTP_Server.h
index 6868b549de1..30241be77c9 100644
--- a/apps/JAWS/server/HTTP_Server.h
+++ b/apps/JAWS/server/HTTP_Server.h
@@ -63,9 +63,8 @@ protected:
virtual int synch_thread_pool (void);
// Synch Thread Pool implementation
- void setup_signal_handler (void);
-
private:
+ // James, comment these data members.
void parse_args (int argc, char **argv);
int port_;
int threads_;
@@ -81,10 +80,12 @@ class Synch_Thread_Pool_Task : public ACE_Task<ACE_NULL_SYNCH>
// Used to implement Synch Thread Pool
//
// = DESCRIPTION
+ // Describe this and the others below.
{
public:
- Synch_Thread_Pool_Task (HTTP_Acceptor &acceptor, ACE_Thread_Manager &tm);
- virtual int open (void *args = 0);
+ Synch_Thread_Pool_Task (HTTP_Acceptor &acceptor,
+ ACE_Thread_Manager &tm,
+ int threads);
virtual int svc (void);
private:
@@ -93,18 +94,23 @@ private:
class Thread_Per_Request_Task : public ACE_Task<ACE_NULL_SYNCH>
// = TITLE
- // Used to implement Thread Per Request
+ // Used to implement Thread Per Request.
//
// = DESCRIPTION
+ // Spawns a new thread for every new incoming connection. The
+ // handle below is the socket stream of the incoming connection.
{
public:
- Thread_Per_Request_Task (ACE_HANDLE handle, ACE_Thread_Manager &tm);
+ Thread_Per_Request_Task (ACE_HANDLE handle,
+ ACE_Thread_Manager &tm
+ int &grp_id);
virtual int open (void *args = 0);
virtual int close (u_long);
virtual int svc (void);
private:
ACE_HANDLE handle_;
+ int &grp_id_;
};
// This only works on Win32
@@ -114,10 +120,12 @@ class Asynch_Thread_Pool_Task : public ACE_Task<ACE_NULL_SYNCH>
// Used to implement Asynch Thread Pool
//
// = DESCRIPTION
+ // The proactor below utilizes WaitForMultipleObjects.
{
public:
- Asynch_Thread_Pool_Task (ACE_Proactor &proactor, ACE_Thread_Manager &tm);
- virtual int open (void *args = 0);
+ Asynch_Thread_Pool_Task (ACE_Proactor &proactor,
+ ACE_Thread_Manager &tm,
+ int threads);
virtual int svc (void);
private:
diff --git a/apps/JAWS/server/main.cpp b/apps/JAWS/server/main.cpp
index e7d2e1e34f8..70bb360c5c0 100644
--- a/apps/JAWS/server/main.cpp
+++ b/apps/JAWS/server/main.cpp
@@ -28,20 +28,22 @@ int
main (int argc, char *argv[])
{
ACE_Service_Config daemon;
- ACE_Reactor::instance ();
- // ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);
+
ACE_OS::signal (SIGCHLD, SIG_IGN);
+
+ // SigAction not needed since the handler will shutdown the server.
ACE_OS::signal (SIGINT, (ACE_SignalHandler) handler);
ACE_OS::signal (SIGUSR1, (ACE_SignalHandler) handler);
- // ACE_UNUSED_ARG (sa);
if (daemon.open (argc, argv) != 0)
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), 1);
+ // The configured service creates threads, and the
+ // server won't exit until the threads die.
+
// Run forever, performing the configured services until we receive
// a SIGINT.
- // ACE_Reactor::run_event_loop ();
return 0;
}