From 72f644eff628eb2fbe9659e5059d77983e5cc84b Mon Sep 17 00:00:00 2001 From: spaunov Date: Mon, 16 Jan 2006 17:10:41 +0000 Subject: Mon Jan 16 17:00:26 UTC 2006 Stoyan Paunov --- ChangeLog | 20 +++++ apps/JAWS/server/HTTP_Handler.cpp | 23 +++++ apps/JAWS/server/HTTP_Handler.h | 25 ++++++ apps/JAWS/server/HTTP_Server.cpp | 61 ++++++++++---- apps/JAWS/server/HTTP_Server.h | 15 +++- apps/JAWS/server/IO.cpp | 171 ++++++++++++++++++++++++++++++++++++++ apps/JAWS/server/IO.h | 57 +++++++++++++ apps/JAWS/server/README | 27 ++++++ apps/JAWS/server/svc.conf | 5 ++ 9 files changed, 384 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index b988ae8ea2e..40d504864a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,29 @@ +Mon Jan 16 17:00:26 UTC 2006 Stoyan Paunov + + * apps/JAWS/server/HTTP_Handler.h: + * apps/JAWS/server/HTTP_Handler.cpp: + * apps/JAWS/server/HTTP_Server.h: + * apps/JAWS/server/HTTP_Server.cpp: + * apps/JAWS/server/IO.h: + * apps/JAWS/server/IO.cpp: + * apps/JAWS/server/README: + * apps/JAWS/server/svc.conf: + + Checking the some changes to JAWS. This is the code that adds the ability + to start the server without file caching. This functionality is necessary + for the proper coordination of file creations and deletions between JAWS + and the RepositoryManager in CIAO. The changes are explained in the README. + I have added a line in the svc.conf file which shows how to enable this new + functionality. + + Mon Jan 16 16:53:38 UTC 2006 Olli Savia * ace/config-lynxos.h: Removed ACE_HAS_PREDEFINED_THREAD_CANCELLED_MACRO, it is no longer used. + Mon Jan 16 14:35:10 UTC 2006 Olli Savia * ace/config-lynxos.h: diff --git a/apps/JAWS/server/HTTP_Handler.cpp b/apps/JAWS/server/HTTP_Handler.cpp index c90e7a11fa0..277cfb11f3a 100644 --- a/apps/JAWS/server/HTTP_Handler.cpp +++ b/apps/JAWS/server/HTTP_Handler.cpp @@ -261,6 +261,29 @@ Synch_HTTP_Handler_Factory::destroy_http_handler (HTTP_Handler &handler, delete &handler; } +//-------------SYNCH IO no Cache + +HTTP_Handler * +No_Cache_Synch_HTTP_Handler_Factory::create_http_handler (void) +{ + JAWS_Synch_IO_No_Cache *io; + ACE_NEW_RETURN (io, JAWS_Synch_IO_No_Cache, 0); + HTTP_Handler *handler; + ACE_NEW_RETURN (handler, HTTP_Handler (*io, *this), 0); + + return handler; +} + +void +No_Cache_Synch_HTTP_Handler_Factory::destroy_http_handler (HTTP_Handler &handler, + JAWS_IO &io) +{ + delete &io; + delete &handler; +} + +//---------------- + // This only works on Win32 #if defined (ACE_WIN32) void diff --git a/apps/JAWS/server/HTTP_Handler.h b/apps/JAWS/server/HTTP_Handler.h index 0a61ae88782..f7eb9b9a693 100644 --- a/apps/JAWS/server/HTTP_Handler.h +++ b/apps/JAWS/server/HTTP_Handler.h @@ -47,11 +47,13 @@ class HTTP_Handler : protected JAWS_IO_Handler { // Friend I/O classes. Can call protected methods. friend class JAWS_Synch_IO; + friend class JAWS_Synch_IO_No_Cache; friend class JAWS_Asynch_IO; // Factories friend class Asynch_HTTP_Handler_Factory; friend class Synch_HTTP_Handler_Factory; + friend class No_Cache_Synch_HTTP_Handler_Factory; public: virtual void open (ACE_HANDLE handle, @@ -163,6 +165,29 @@ public: // the protocol }; +//--------------Added a factory for SYNCH IO without caching + +class No_Cache_Synch_HTTP_Handler_Factory : public HTTP_Handler_Factory + // = TITLE + // + // This class is used to create new HTTP handlers that will use + // Synch IO without caching + // + // = DESCRIPTION +{ +public: + HTTP_Handler *create_http_handler (void); + // This creates a new HTTP_Handler + + void destroy_http_handler (HTTP_Handler &handler, + JAWS_IO &io); + // The HTTP handler will call this method from HTTP_Handler::done to + // tell the factory to reap up the handler as it is now done with + // the protocol +}; + +//-------------- + #if defined (ACE_WIN32) class Asynch_HTTP_Handler_Factory : public HTTP_Handler_Factory, public ACE_Service_Handler // = TITLE diff --git a/apps/JAWS/server/HTTP_Server.cpp b/apps/JAWS/server/HTTP_Server.cpp index a43575db5e3..9dad1f355b5 100644 --- a/apps/JAWS/server/HTTP_Server.cpp +++ b/apps/JAWS/server/HTTP_Server.cpp @@ -10,6 +10,7 @@ #include "ace/LOCK_SOCK_Acceptor.h" #include "ace/Proactor.h" #include "ace/Signal.h" +#include "ace/Auto_Ptr.h" #include "IO.h" #include "HTTP_Server.h" @@ -46,8 +47,9 @@ HTTP_Server::parse_args (int argc, ACE_TCHAR *argv[]) this->threads_ = 0; this->backlog_ = 0; this->throttle_ = 0; + this->caching_ = true; - ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("p:n:t:i:b:")); + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("p:n:t:i:b:c:")); while ((c = get_opt ()) != -1) switch (c) @@ -97,6 +99,12 @@ HTTP_Server::parse_args (int argc, ACE_TCHAR *argv[]) case 'b': this->backlog_ = ACE_OS::atoi (get_opt.opt_arg ()); break; + case 'c': + if (ACE_OS::strcmp (get_opt.opt_arg (), ACE_TEXT ("NO_CACHE")) == 0) + this->caching_ = false; + else + this->caching_ = true; + break; default: break; } @@ -130,6 +138,22 @@ HTTP_Server::init (int argc, ACE_TCHAR *argv[]) // Parse arguments which sets the initial state. this->parse_args (argc, argv); + //If the IO strategy is synchronous (SYNCH case), then choose a handler + //factory based on the desired caching scheme + HTTP_Handler_Factory *f = 0; + + if (this->strategy_ != (JAWS::JAWS_POOL | JAWS::JAWS_ASYNCH)) + if (this->caching_) + ACE_NEW_RETURN (f, Synch_HTTP_Handler_Factory (), -1); + else + ACE_NEW_RETURN (f, No_Cache_Synch_HTTP_Handler_Factory (), -1); + + //NOTE: At this point f better not be a NULL pointer, + //so please do not change the ACE_NEW_RETURN macros unless + //you know what you are doing + ACE_Auto_Ptr factory (f); + + // Choose what concurrency strategy to run. switch (this->strategy_) { @@ -137,11 +161,11 @@ HTTP_Server::init (int argc, ACE_TCHAR *argv[]) return this->asynch_thread_pool (); case (JAWS::JAWS_PER_REQUEST | JAWS::JAWS_SYNCH) : - return this->thread_per_request (); + return this->thread_per_request (*factory.get ()); case (JAWS::JAWS_POOL | JAWS::JAWS_SYNCH) : default: - return this->synch_thread_pool (); + return this->synch_thread_pool (*factory.get ()); } ACE_NOTREACHED (return 0); @@ -156,7 +180,7 @@ HTTP_Server::fini (void) int -HTTP_Server::synch_thread_pool (void) +HTTP_Server::synch_thread_pool (HTTP_Handler_Factory &factory) { // Main thread opens the acceptor if (this->acceptor_.open (ACE_INET_Addr (this->port_), 1, @@ -165,7 +189,7 @@ HTTP_Server::synch_thread_pool (void) ACE_TEXT ("HTTP_Acceptor::open")), -1); // Create a pool of threads to handle incoming connections. - Synch_Thread_Pool_Task t (this->acceptor_, this->tm_, this->threads_); + Synch_Thread_Pool_Task t (this->acceptor_, this->tm_, this->threads_, factory); this->tm_.wait (); return 0; @@ -173,9 +197,11 @@ HTTP_Server::synch_thread_pool (void) Synch_Thread_Pool_Task::Synch_Thread_Pool_Task (HTTP_Acceptor &acceptor, ACE_Thread_Manager &tm, - int threads) + int threads, + HTTP_Handler_Factory &factory) : ACE_Task (&tm), - acceptor_ (acceptor) + acceptor_ (acceptor), + factory_ (factory) { if (this->activate (THR_DETACHED | THR_NEW_LWP, threads) == -1) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), @@ -186,7 +212,7 @@ int Synch_Thread_Pool_Task::svc (void) { // Creates a factory of HTTP_Handlers binding to synchronous I/O strategy - Synch_HTTP_Handler_Factory factory; + //Synch_HTTP_Handler_Factory factory; for (;;) { @@ -203,7 +229,7 @@ Synch_Thread_Pool_Task::svc (void) -1); // Create an HTTP Handler to handle this request - HTTP_Handler *handler = factory.create_http_handler (); + HTTP_Handler *handler = this->factory_.create_http_handler (); handler->open (stream.get_handle (), *mb); // Handler is destroyed when the I/O puts the Handler into the // done state. @@ -217,7 +243,7 @@ Synch_Thread_Pool_Task::svc (void) } int -HTTP_Server::thread_per_request (void) +HTTP_Server::thread_per_request (HTTP_Handler_Factory &factory) { int grp_id = -1; @@ -244,7 +270,8 @@ HTTP_Server::thread_per_request (void) // Pass grp_id as a constructor param instead of into open. ACE_NEW_RETURN (t, Thread_Per_Request_Task (stream.get_handle (), this->tm_, - grp_id), + grp_id, + factory), -1); @@ -267,11 +294,13 @@ HTTP_Server::thread_per_request (void) } Thread_Per_Request_Task::Thread_Per_Request_Task (ACE_HANDLE handle, - ACE_Thread_Manager &tm, - int &grp_id) + ACE_Thread_Manager &tm, + int &grp_id, + HTTP_Handler_Factory &factory) : ACE_Task (&tm), handle_ (handle), - grp_id_ (grp_id) + grp_id_ (grp_id), + factory_ (factory) { } @@ -303,8 +332,8 @@ Thread_Per_Request_Task::svc (void) ACE_Message_Block *mb; ACE_NEW_RETURN (mb, ACE_Message_Block (HTTP_Handler::MAX_REQUEST_SIZE + 1), -1); - Synch_HTTP_Handler_Factory factory; - HTTP_Handler *handler = factory.create_http_handler (); + //Synch_HTTP_Handler_Factory factory; + HTTP_Handler *handler = this->factory_.create_http_handler (); handler->open (this->handle_, *mb); mb->release (); return 0; diff --git a/apps/JAWS/server/HTTP_Server.h b/apps/JAWS/server/HTTP_Server.h index 8d39e193642..786108f658d 100644 --- a/apps/JAWS/server/HTTP_Server.h +++ b/apps/JAWS/server/HTTP_Server.h @@ -61,13 +61,13 @@ public: // Exit hooks protected: - virtual int thread_per_request (void); + virtual int thread_per_request (HTTP_Handler_Factory &factory); // Thread Per Request implementation virtual int asynch_thread_pool (void); // Asynch Thread Pool implementation - virtual int synch_thread_pool (void); + virtual int synch_thread_pool (HTTP_Handler_Factory &factory); // Synch Thread Pool implementation private: @@ -78,6 +78,7 @@ private: int strategy_; int backlog_; int throttle_; + bool caching_; ACE_Thread_Manager tm_; HTTP_Acceptor acceptor_; }; @@ -88,15 +89,18 @@ class Synch_Thread_Pool_Task : public ACE_Task // // = DESCRIPTION // Describe this and the others below. + // NOTE: this class was modified to make caching disabling possible { public: Synch_Thread_Pool_Task (HTTP_Acceptor &acceptor, ACE_Thread_Manager &tm, - int threads); + int threads, + HTTP_Handler_Factory &factory); virtual int svc (void); private: HTTP_Acceptor &acceptor_; + HTTP_Handler_Factory &factory_; }; class Thread_Per_Request_Task : public ACE_Task @@ -106,11 +110,13 @@ class Thread_Per_Request_Task : public ACE_Task // = DESCRIPTION // Spawns a new thread for every new incoming connection. The // handle below is the socket stream of the incoming connection. + // NOTE: this class was modified to make caching disabling possible { public: Thread_Per_Request_Task (ACE_HANDLE handle, ACE_Thread_Manager &tm, - int &grp_id); + int &grp_id, + HTTP_Handler_Factory &factory); virtual int open (void *args = 0); virtual int close (u_long); virtual int svc (void); @@ -118,6 +124,7 @@ public: private: ACE_HANDLE handle_; int &grp_id_; + HTTP_Handler_Factory &factory_; }; // This only works on Win32 diff --git a/apps/JAWS/server/IO.cpp b/apps/JAWS/server/IO.cpp index 34d8ddd0acd..d746664a55e 100644 --- a/apps/JAWS/server/IO.cpp +++ b/apps/JAWS/server/IO.cpp @@ -10,6 +10,10 @@ #include "IO.h" #include "HTTP_Helpers.h" +#include "ace/OS_NS_fcntl.h" +#include "ace/OS_NS_unistd.h" +#include "ace/OS_NS_sys_stat.h" +#include "ace/Auto_Ptr.h" ACE_RCSID (server, IO, @@ -418,6 +422,173 @@ JAWS_Asynch_IO::handle_write_stream (const ACE_Asynch_Write_Stream::Result &resu #endif /* ACE_WIN32 */ +//-------------------Adding SYNCH IO no Caching + +JAWS_Synch_IO_No_Cache::JAWS_Synch_IO_No_Cache (void) + : handle_ (ACE_INVALID_HANDLE) +{ +} + +JAWS_Synch_IO_No_Cache::~JAWS_Synch_IO_No_Cache (void) +{ + ACE_OS::closesocket (this->handle_); +} + +ACE_HANDLE +JAWS_Synch_IO_No_Cache::handle (void) const +{ + return this->handle_; +} + +void +JAWS_Synch_IO_No_Cache::handle (ACE_HANDLE handle) +{ + this->handle_ = handle; +} + +void +JAWS_Synch_IO_No_Cache::read (ACE_Message_Block &mb, + int size) +{ + ACE_SOCK_Stream stream; + stream.set_handle (this->handle_); + int result = stream.recv (mb.wr_ptr (), size); + + if (result <= 0) + this->handler_->read_error (); + else + { + mb.wr_ptr (result); + this->handler_->read_complete (mb); + } +} + +void +JAWS_Synch_IO_No_Cache::receive_file (const char *filename, + void *initial_data, + int initial_data_length, + int entire_length) +{ + //ugly hack to send HTTP_Status_Code::STATUS_FORBIDDEN + this->handler_->receive_file_error (5); + + //ACE_Filecache_Handle handle (filename, entire_length); + + //int result = handle.error (); + + //if (result == ACE_Filecache_Handle::ACE_SUCCESS) + // { + // ACE_SOCK_Stream stream; + // stream.set_handle (this->handle_); + + // int bytes_to_memcpy = ACE_MIN (entire_length, initial_data_length); + // ACE_OS::memcpy (handle.address (), initial_data, bytes_to_memcpy); + + // int bytes_to_read = entire_length - bytes_to_memcpy; + + // int bytes = stream.recv_n ((char *) handle.address () + initial_data_length, + // bytes_to_read); + // if (bytes == bytes_to_read) + // this->handler_->receive_file_complete (); + // else + // result = -1; + // } + + //if (result != ACE_Filecache_Handle::ACE_SUCCESS) + // this->handler_->receive_file_error (result); + +} + +void +JAWS_Synch_IO_No_Cache::transmit_file (const char *filename, + const char *header, + int header_size, + const char *trailer, + int trailer_size) +{ + int result = 0; + + // Can we access the file? + if (ACE_OS::access (filename, R_OK) == -1) + { + //ugly hack to send in HTTP_Status_Code::STATUS_NOT_FOUND + result = ACE_Filecache_Handle::ACE_ACCESS_FAILED; + this->handler_->transmit_file_error (result); + return; + } + + ACE_stat stat; + + // Can we stat the file? + if (ACE_OS::stat (filename, &stat) == -1) + { + //ugly hack to send HTTP_Status_Code::STATUS_FORBIDDEN + result = ACE_Filecache_Handle::ACE_STAT_FAILED; + this->handler_->transmit_file_error (result); + return; + } + + size_t size = stat.st_size; + + // Can we open the file? + ACE_HANDLE handle = ACE_OS::open (filename, O_RDONLY); + if (handle == ACE_INVALID_HANDLE) + { + //ugly hack to send HTTP_Status_Code::STATUS_FORBIDDEN + result = ACE_Filecache_Handle::ACE_OPEN_FAILED; + this->handler_->transmit_file_error (result); + return; + } + + char* f = new char[size]; + auto_ptr file (f); + + ACE_OS::read_n (handle, f, size); + + ACE_SOCK_Stream stream; + stream.set_handle (this->handle_); + + if ((stream.send_n (header, header_size) == header_size) + && (stream.send_n (f, size) == size) + && (stream.send_n (trailer, trailer_size) == trailer_size)) + this->handler_->transmit_file_complete (); + else + { + //ugly hack to default to HTTP_Status_Code::STATUS_INTERNAL_SERVER_ERROR + result = -1; + this->handler_->transmit_file_error (result); + return; + } +} + +void +JAWS_Synch_IO_No_Cache::send_confirmation_message (const char *buffer, + int length) +{ + this->send_message (buffer, length); + this->handler_->confirmation_message_complete (); +} + +void +JAWS_Synch_IO_No_Cache::send_error_message (const char *buffer, + int length) +{ + this->send_message (buffer, length); + this->handler_->error_message_complete (); +} + +void +JAWS_Synch_IO_No_Cache::send_message (const char *buffer, + int length) +{ + ACE_SOCK_Stream stream; + stream.set_handle (this->handle_); + stream.send_n (buffer, length); +} + +//------------------- + + // #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) // template class ACE_Singleton; // #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) diff --git a/apps/JAWS/server/IO.h b/apps/JAWS/server/IO.h index 160553f7ee0..8249adf3582 100644 --- a/apps/JAWS/server/IO.h +++ b/apps/JAWS/server/IO.h @@ -235,5 +235,62 @@ protected: }; #endif /* ACE_WIN32 */ + + +//-------------------Adding SYNCH IO no Caching + +class JAWS_Synch_IO_No_Cache : public JAWS_IO + // = TITLE + // + // This class defines the interface for a Synchronous I/O class, + // however in this class we do not use any caching. + // + // = DESCRIPTION + // + // Wondering how this is useful? + // The ACE_Filecache ACE_NOMAP option is broken and even if it were not, there + // are other use cases in which we want to avoid caching altogether. For example, + // we use JAWS in conjunction with the CIAO Repository Manager, however the two + // do not have any explicit knowledge of each other. Therefore if the RM tried + // to remove a package and its files from disk, its operation would [partially] + // fail if JAWS still holds some of the files in its cache. + // +{ +public: + JAWS_Synch_IO_No_Cache (void); + + ~JAWS_Synch_IO_No_Cache (void); + + virtual void handle (ACE_HANDLE h); + virtual ACE_HANDLE handle (void) const; + + void read (ACE_Message_Block& mb, int size); + + void transmit_file (const char *filename, + const char *header, + int header_size, + const char *trailer, + int trailer_size); + + void receive_file (const char *filename, + void *initial_data, + int initial_data_length, + int entire_length); + + void send_confirmation_message (const char *buffer, + int length); + + void send_error_message (const char *buffer, + int length); + +protected: + virtual void send_message (const char *buffer, + int length); + + ACE_HANDLE handle_; +}; + +//------------------- + #endif /* JAWS_IO_H */ diff --git a/apps/JAWS/server/README b/apps/JAWS/server/README index 4fab66d703d..27f0a0e3a8d 100644 --- a/apps/JAWS/server/README +++ b/apps/JAWS/server/README @@ -21,6 +21,8 @@ CONTENTS 4. Acknowledgements +5. New additions + ------------ 1. Compiling ------------ @@ -199,3 +201,28 @@ James Hu Tim Harrison For his comments, advice, and help in designing the IO mechanism used by JAWS. + +----------------------- +5. Additions +----------------------- + +The need arose to have JAWS not perform any file caching. We added this +functionality and provided a new cmd line option -c with params NO_CACHE/CACHE. + +This capability is to be used with the RepositoryManager in CIAO. + +In its current design the RepositoryManager (RM) need a collocated HTTP server. +When RM istalls packages, it unpacks them so that the separate files are accessible to +ZIP unaware entities like JAWS. JAWS is used to serve the libraries in the package to the +various deamons that might be interested in them, e.g. the NodeApplicationManager. + +The problem with using file caching reveals itself during the deletePackage operation of +the RM. When the RM attempts to delete a file which was previously accessed via JAWS a +is currently in the file cache the call fails and the file remains on the filesystem +indefinitely. If the file is cached with a ACE_NOMAP option is is not stored in a file +map and it is deleted upon server termination. The OS handles that. Althoguh this might +or might not be OK (depending on how it scales) there is an additional problem because +JAWS and the ACE_Filecache_Handle class used do not provide enough functionality to deal +with the ACE_NOMAP case. I believe that ACE_NOMAP option was probably never used. + +To overcome the above problems we added the no caching functionality in JAWS. diff --git a/apps/JAWS/server/svc.conf b/apps/JAWS/server/svc.conf index 5f34c06aaa1..fdba6ab9c76 100644 --- a/apps/JAWS/server/svc.conf +++ b/apps/JAWS/server/svc.conf @@ -14,6 +14,7 @@ # = SYNCH # = ASYNCH # -b backlog value for listen () +# -c caching: NO_CACHE or CACHE # # # Thread Pool, 20 unbound threads @@ -21,6 +22,10 @@ static HTTP_Server "HTTP_Server -p 5432 -n 20 -i SYNCH -t POOL -b 50 -f THR_NEW_LWP" # # +# Start a baseline server without caching +#static HTTP_Server "HTTP_Server -p 5432 -n 20 -i SYNCH -t POOL -b 50 -f THR_NEW_LWP -c NO_CACHE" +# +# # Thread Pool, 40 threads #static HTTP_Server "HTTP_Server -p 5432 -n 40 -i SYNCH -t POOL -b 50 -f THR_NEW_LWP -f THR_BOUND" # -- cgit v1.2.1