summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ace/Filecache.cpp155
-rw-r--r--ace/Filecache.h109
-rw-r--r--apps/JAWS/ChangeLog8
-rw-r--r--apps/JAWS/clients/Caching/Makefile49
-rw-r--r--apps/JAWS/clients/Caching/http_client.cpp66
-rw-r--r--apps/JAWS/clients/Caching/http_handler.cpp248
-rw-r--r--apps/JAWS/clients/Caching/http_handler.h39
7 files changed, 568 insertions, 106 deletions
diff --git a/ace/Filecache.cpp b/ace/Filecache.cpp
index 94b9747dd2f..6a2412e3b93 100644
--- a/ace/Filecache.cpp
+++ b/ace/Filecache.cpp
@@ -27,7 +27,7 @@ static const int WCOPY_FLAGS = O_RDWR | O_CREAT | O_TRUNC;
ACE_Filecache *ACE_Filecache::cvf_ = 0;
ACE_SYNCH_RW_MUTEX ACE_Filecache::lock_;
-// This is how you make data opaque in C++ I'd like to do this with
+// This is how you make data opaque in C++. I'd like to do this with
// ACE_Filecache_Object too, but Doug would pro'ly kill me.
class ACE_Filecache_Singleton
{
@@ -51,6 +51,111 @@ private:
// needed in the future when we remove reliance on copying files.
static ACE_Filecache_Singleton cvf_singleton;
+class ACE_Filecache_Object
+ // = TITLE
+ // Abstraction over a real file. This is what the Virtual
+ // Filesystem contains. This class is not intended for general
+ // consumption. Please consult a physician before attempting to
+ // use this class.
+{
+public:
+ ACE_Filecache_Object (const char *filename);
+ // Creates a file for reading.
+
+ ACE_Filecache_Object (const char *filename,
+ int size);
+ // Creates a file for writing.
+
+ ~ACE_Filecache_Object (void);
+ // Only if reference count is zero should this be called.
+
+ int acquire (void);
+ // Increment the reference_count_.
+
+ int release (void);
+ // Decrement the reference_count_.
+
+ // = action_ accessors
+ int action (void) const;
+ int action (int action_value);
+
+ // = error_ accessors
+ int error (void) const;
+ int error (int error_value,
+ const char *s = "ACE_Filecache_Object");
+
+ const char *filename (void) const;
+ // filename_ accessor
+
+ ACE_HANDLE handle (void) const;
+ // handle_ accessor.
+
+ void *address (void) const;
+ // Base memory address for memory mapped file.
+
+ size_t size (void) const;
+ // size_ accessor.
+
+ int update (void) const;
+ // True if file on disk is newer than cached file.
+
+protected:
+ ACE_Filecache_Object (void);
+ // Prevent from being called.
+
+ void init (void);
+ // Common initialization code,
+
+private:
+ int error_i (int error_value,
+ const char *s = "ACE_Filecache_Object");
+ // Internal error logging method, no locking.
+
+public:
+
+ enum
+ {
+ READING = 1,
+ WRITING = 2
+ };
+
+ enum
+ {
+ SUCCESS = 0,
+ ACCESS_FAILED,
+ OPEN_FAILED,
+ COPY_FAILED,
+ STAT_FAILED,
+ MEMMAP_FAILED,
+ WRITE_FAILED
+ };
+
+private:
+ char *tempname_;
+ char filename_[MAXPATHLEN + 1];
+ // The temporary file name and the real file name. The real file is
+ // copied into the temporary file for safety reasons.
+
+ ACE_Mem_Map mmap_;
+ ACE_HANDLE handle_;
+ // mmap_ holds the memory mapped version of the temporary file.
+ // handle_ is the descriptor to the temporary file.
+
+ struct stat stat_;
+ size_t size_;
+ // Used to compare against the real file to test if an update is needed.
+
+ int action_;
+ int error_;
+ // Status indicators.
+
+ int reference_count_;
+ ACE_SYNCH_RW_MUTEX lock_;
+ // reference_count_ counts how many users of the file there are.
+ // lock_ provides a synchronization mechanism for critical sections
+ // of code.
+};
+
void
ACE_Filecache_Handle::init (void)
{
@@ -177,6 +282,51 @@ ACE_Filecache::~ACE_Filecache (void)
}
ACE_Filecache_Object *
+ACE_Filecache::find (const char * filename)
+{
+ int i;
+ ACE_Filecache_Object *handle = 0;
+
+ {
+ ACE_Read_Guard<ACE_SYNCH_RW_MUTEX> m (ACE_Filecache::lock_);
+
+ i = this->fetch_i (filename);
+
+ if (i != -1 && ! this->table_[i]->update ())
+ handle = this->table_[i];
+ }
+
+ // Considerably slower on misses, but should be faster on hits.
+ // This is actually the double check locking pattern.
+
+ if (handle == 0)
+ {
+ ACE_Write_Guard<ACE_SYNCH_RW_MUTEX> m (ACE_Filecache::lock_);
+
+ i = this->fetch_i (filename);
+
+ if (i == -1)
+ {
+ ACE_DEBUG ((LM_DEBUG, " (%t) CVF: missed %s\n", filename));
+ }
+ else if (this->table_[i]->update ())
+ {
+ ACE_DEBUG ((LM_DEBUG, " (%t) CVF: updating %s\n", filename));
+ this->remove_i (i);
+ handle = this->table_[i] = new ACE_Filecache_Object (filename);
+ handle->acquire ();
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, " (%t) CVF: found %s\n", filename));
+ handle = this->table_[i];
+ }
+ }
+
+ return handle;
+}
+
+ACE_Filecache_Object *
ACE_Filecache::fetch (const char * filename)
{
int i;
@@ -194,6 +344,9 @@ ACE_Filecache::fetch (const char * filename)
// Considerably slower on misses, but should be faster on hits.
// This is actually the double check locking pattern.
+ // Nearly equivalent to this->find (), except a miss causes the CVF
+ // to insert the file into the cache.
+
if (handle == 0)
{
ACE_Write_Guard<ACE_SYNCH_RW_MUTEX> m (ACE_Filecache::lock_);
diff --git a/ace/Filecache.h b/ace/Filecache.h
index 499a121174b..86a0eb493c5 100644
--- a/ace/Filecache.h
+++ b/ace/Filecache.h
@@ -134,6 +134,10 @@ public:
~ACE_Filecache (void);
+ ACE_Filecache_Object *find (const char *filename);
+ // Return the file associated with ``filename'' if it is in the cache,
+ // or NULL if not.
+
ACE_Filecache_Object *fetch (const char *filename);
// Return the file associated with ``filename'' if it is in the cache,
// or create if not.
@@ -181,109 +185,4 @@ private:
static ACE_SYNCH_RW_MUTEX lock_;
};
-class ACE_Export ACE_Filecache_Object
- // = TITLE
- // Abstraction over a real file. This is what the Virtual
- // Filesystem contains. This class is not intended for general
- // consumption. Please consult a physician before attempting to
- // use this class.
-{
-public:
- ACE_Filecache_Object (const char *filename);
- // Creates a file for reading.
-
- ACE_Filecache_Object (const char *filename,
- int size);
- // Creates a file for writing.
-
- ~ACE_Filecache_Object (void);
- // Only if reference count is zero should this be called.
-
- int acquire (void);
- // Increment the reference_count_.
-
- int release (void);
- // Decrement the reference_count_.
-
- // = action_ accessors
- int action (void) const;
- int action (int action_value);
-
- // = error_ accessors
- int error (void) const;
- int error (int error_value,
- const char *s = "ACE_Filecache_Object");
-
- const char *filename (void) const;
- // filename_ accessor
-
- ACE_HANDLE handle (void) const;
- // handle_ accessor.
-
- void *address (void) const;
- // Base memory address for memory mapped file.
-
- size_t size (void) const;
- // size_ accessor.
-
- int update (void) const;
- // True if file on disk is newer than cached file.
-
-protected:
- ACE_Filecache_Object (void);
- // Prevent from being called.
-
- void init (void);
- // Common initialization code,
-
-private:
- int error_i (int error_value,
- const char *s = "ACE_Filecache_Object");
- // Internal error logging method, no locking.
-
-public:
-
- enum
- {
- READING = 1,
- WRITING = 2
- };
-
- enum
- {
- SUCCESS = 0,
- ACCESS_FAILED,
- OPEN_FAILED,
- COPY_FAILED,
- STAT_FAILED,
- MEMMAP_FAILED,
- WRITE_FAILED
- };
-
-private:
- char *tempname_;
- char filename_[MAXPATHLEN + 1];
- // The temporary file name and the real file name. The real file is
- // copied into the temporary file for safety reasons.
-
- ACE_Mem_Map mmap_;
- ACE_HANDLE handle_;
- // mmap_ holds the memory mapped version of the temporary file.
- // handle_ is the descriptor to the temporary file.
-
- struct stat stat_;
- size_t size_;
- // Used to compare against the real file to test if an update is needed.
-
- int action_;
- int error_;
- // Status indicators.
-
- int reference_count_;
- ACE_SYNCH_RW_MUTEX lock_;
- // reference_count_ counts how many users of the file there are.
- // lock_ provides a synchronization mechanism for critical sections
- // of code.
-};
-
#endif /* ACE_FILECACHE_H */
diff --git a/apps/JAWS/ChangeLog b/apps/JAWS/ChangeLog
index 2a1872dae2b..d2df4eb20ca 100644
--- a/apps/JAWS/ChangeLog
+++ b/apps/JAWS/ChangeLog
@@ -1,3 +1,11 @@
+Wed Jul 9 13:08:00 1997 James C Hu <jxh@lambada.cs.wustl.edu>
+
+ * clients/Caching/http_handler.cpp (svc): Added code to check to
+ see if the file is already cached before trying to cache it.
+
+ * clients/Caching/http_client.cpp (main): Added a comment block at
+ the top of the file.
+
Mon Jul 7 23:40:13 1997 Nanbor Wang <nw1@cumbia.cs.wustl.edu>
* clients/WebSTONE/src/webclient.c: Removed a bunch of THREAD
diff --git a/apps/JAWS/clients/Caching/Makefile b/apps/JAWS/clients/Caching/Makefile
new file mode 100644
index 00000000000..cc1b7f30a7b
--- /dev/null
+++ b/apps/JAWS/clients/Caching/Makefile
@@ -0,0 +1,49 @@
+#----------------------------------------------------------------------------
+# %W% %G%
+#
+# Makefile for the ACE Adapter Web Server (JAWS) client
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Local macros
+#----------------------------------------------------------------------------
+
+BIN = http_client
+
+FILES = http_handler
+
+LSRC = $(addsuffix .cpp,$(FILES))
+LOBJ = $(addsuffix .o,$(FILES))
+SHOBJ = $(addsuffix .so,$(FILES))
+
+LDLIBS = $(addprefix .shobj/,$(SHOBJ))
+
+VLDLIBS = $(LDLIBS:%=%$(VAR))
+
+BUILD = $(VBIN)
+
+#----------------------------------------------------------------------------
+# Include macros and targets
+#----------------------------------------------------------------------------
+
+include $(WRAPPER_ROOT)/include/makeinclude/wrapper_macros.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/macros.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.common.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.nonested.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.lib.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.bin.GNU
+include $(WRAPPER_ROOT)/include/makeinclude/rules.local.GNU
+
+#----------------------------------------------------------------------------
+# Local targets
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Dependencies
+#----------------------------------------------------------------------------
+# DO NOT DELETE THIS LINE -- g++dep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff --git a/apps/JAWS/clients/Caching/http_client.cpp b/apps/JAWS/clients/Caching/http_client.cpp
new file mode 100644
index 00000000000..6390bd230ab
--- /dev/null
+++ b/apps/JAWS/clients/Caching/http_client.cpp
@@ -0,0 +1,66 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// apps/JAWS/clients/Caching
+//
+// = FILENAME
+// http_client.cpp
+//
+// = AUTHOR
+// James Hu
+//
+// ============================================================================
+
+// = DESCRIPTION
+// This is a very simple client. It accepts URLs from a prompt, and
+// will try to fetch them. Also accepts shell escapes.
+
+#include "http_handler.h"
+
+int
+main (int argc, char *argv[])
+{
+ argc = argc;
+ argv = argv;
+
+ // Present a command line.
+ // * Accept a URL.
+ // Pass it to the HTTP_Connector.
+ // Connect.
+ // Report status.
+ // * Accept shell escape character.
+
+ char buf[BUFSIZ];
+
+ ACE_OS::fprintf (stderr, "* ");
+ while (ACE_OS::fgets (buf, sizeof (buf), stdin) != NULL)
+ {
+ char * s = buf;
+ while (*s == ' ' || *s == '\t')
+ s++;
+
+ if (*s == '!')
+ {
+ // Shell command
+ do s++; while (*s == ' ' || *s == '\t');
+ if (ACE_OS::system (s) == -1)
+ ACE_OS::fprintf (stderr, " ! Error executing: %s\n", s);
+ }
+ else if (ACE_OS::strncmp (s, "http://", 7) == 0)
+ {
+ // URL
+ HTTP_Connector connector;
+ connector.connect (s);
+ }
+ else
+ ACE_OS::fprintf (stderr, " ? I don't understand: %s\n", s);
+
+ ACE_OS::fprintf (stderr, "* ");
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "\nBye!\n"));
+
+ return 0;
+}
diff --git a/apps/JAWS/clients/Caching/http_handler.cpp b/apps/JAWS/clients/Caching/http_handler.cpp
new file mode 100644
index 00000000000..72bc1760d8d
--- /dev/null
+++ b/apps/JAWS/clients/Caching/http_handler.cpp
@@ -0,0 +1,248 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// apps/JAWS/clients/Caching
+//
+// = FILENAME
+// http_handler.cpp
+//
+// = AUTHOR
+// James Hu
+//
+// ============================================================================
+
+#include "http_handler.h"
+#include "ace/Filecache.h"
+
+HTTP_Handler::HTTP_Handler (void)
+{
+}
+
+HTTP_Handler::HTTP_Handler (const char * path)
+{
+ // How long is the request going to be?
+ this->request_[0] = '\0';
+ this->request_size_ =
+ ACE_OS::strlen ("GET ")
+ + ACE_OS::strlen (path)
+ + ACE_OS::strlen (" HTTP/1.0\r\nAccept: HTTP/1.0\r\n\r\n");
+
+ // Make the request.
+ if ((unsigned int) this->request_size_ < sizeof (this->request_))
+ ACE_OS::sprintf(this->request_,
+ "GET %s HTTP/1.0\r\nAccept: HTTP/1.0\r\n\r\n",
+ path);
+
+ // Find the filename.
+ const char * last = ACE_OS::strrchr (path, '/');
+ if (last == 0) last = path;
+ else if (last[1] == '\0') last = "index.html";
+ else last = last+1;
+
+ ACE_OS::sprintf(this->filename_, "%s", last);
+}
+
+int
+HTTP_Handler::open (void *)
+{
+ // If you want threads, use the activate stuff.
+#if 0
+ if (this->activate () != 0)
+ {
+ ACE_ERROR_RETURN((LM_ERROR, "HTTP_Handler::open, whups!\n"), -1);
+ }
+#else
+ return this->svc ();
+#endif /* 0 */
+
+ return 0;
+}
+
+int
+HTTP_Handler::svc (void)
+{
+ static char buf[BUFSIZ];
+ int count = 0;
+
+ // First check the cache.
+ if (ACE_Filecache::instance ()->find (this->filename_))
+ {
+ ACE_OS::fprintf (stdout, " ``%s'' is already cached.\n",
+ this->filename_);
+ return 0;
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "[%t] sending request --\n%s", this->request_));
+
+ this->send_n (this->request_, this->request_size_);
+
+ // Read in characters until encounter \r\n\r\n
+ int done = 0;
+ char * contentlength;
+ do
+ {
+ while (((count += this->recv_n (buf+count, 1)) > 0)
+ && ((unsigned int) count < sizeof (buf)))
+ {
+ buf[count] = '\0';
+ if (count < 2) continue;
+ done = (strcmp (buf+count-4, "\n\n") == 0);
+ if (done) break;
+ if (count < 4) continue;
+ done = (strcmp (buf+count-4, "\r\n\r\n") == 0);
+ if (done) break;
+ }
+
+ if (!done)
+ {
+ char * last = ACE_OS::strrchr (buf, '\n');
+ last[0] = '\0';
+ if ((contentlength = ACE_OS::strstr (buf, "\nContent-length:"))
+ || (contentlength = ACE_OS::strstr (buf, "\nContent-Length:")))
+ done = 1;
+ else
+ {
+ last[0] = '\n';
+ count = ACE_OS::strlen (last);
+ ACE_OS::memmove (buf, last, count + 1);
+ }
+ }
+ else
+ {
+ if (!(contentlength = ACE_OS::strstr (buf, "\nContent-length:")))
+ contentlength = ACE_OS::strstr (buf, "\nContent-Length:");
+ }
+
+ }
+ while (!done);
+
+ // ASSERT (contentlength != 0)
+ if (contentlength
+ && (::sscanf (contentlength, "\nContent-%*[lL]ength: %d ",
+ &(this->response_size_)) == 1))
+ {
+ ACE_Filecache_Handle afh(this->filename_, this->response_size_);
+
+ this->recv_n (afh.address (), this->response_size_);
+
+ ACE_OS::fprintf (stdout, " ``%s'' is now cached.\n",
+ this->filename_);
+ }
+ else
+ {
+ // Maybe we should do something more clever here, such as
+ // extend ACE_Filecache_Handle to allow the creation of cache
+ // objects whose size is unknown?
+
+ // Another possibility is to write the contents out to a file,
+ // and then cache it.
+
+ // Perhaps make ACE_Filecache_Handle more savvy, and allow a
+ // constructor which accepts a PEER as a parameter.
+ ACE_DEBUG ((LM_DEBUG, "HTTP_Handler, no content-length header!\n"));
+ }
+
+ return 0;
+}
+
+int
+HTTP_Handler::send_n (const void *buf, size_t n)
+{
+ int count = 0;
+ const char *p = (const char *) buf;
+ do
+ {
+ int result = this->peer ().send (p+count, n - count);
+ if (result <= 0)
+ {
+ if (result < 0)
+ ACE_DEBUG ((LM_DEBUG, "HTTP_Handler::send_n, error %p\n"));
+ break;
+ }
+ count += result;
+ }
+ while ((unsigned int) count < n);
+
+ return count;
+}
+
+int
+HTTP_Handler::recv_n (void *buf, size_t n)
+{
+ int count = 0;
+ char *p = (char *) buf;
+
+ do
+ {
+ int result = this->peer ().recv (p+count, n - count);
+ if (result <= 0)
+ {
+ if (result < 0)
+ ACE_DEBUG ((LM_DEBUG, "HTTP_Handler::recv_n, error %p\n"));
+ break;
+ }
+ count += result;
+ }
+ while ((unsigned int) count < n);
+
+ return count;
+}
+
+int
+HTTP_Connector::connect (const char * url)
+{
+ char host[BUFSIZ];
+ unsigned short port;
+ char path[BUFSIZ];
+
+ if (this->parseurl (url, host, &port, path) == -1)
+ {
+ ACE_DEBUG ((LM_DEBUG, "HTTP_Connector, error parsing url: %s\n", url));
+ return -1;
+ }
+
+ HTTP_Handler hh (path);
+ HTTP_Handler *hhptr = &hh;
+ return this->connector_.connect (hhptr, ACE_INET_Addr (port, host));
+}
+
+#define DEFAULT_SERVER_PORT 80
+
+// extract the main components of a URL
+int
+HTTP_Connector::parseurl(const char *url,
+ char *host, unsigned short *port, char *path)
+{
+ int status = 0;
+
+ // hackish, but useful
+ if (3 != ::sscanf(url, "http://%[^:/]:%hu%s", host, port, path)) {
+ if (2 != ::sscanf(url, "http://%[^:/]:%hu", host, port)) {
+ if (2 != ::sscanf(url, "http://%[^:/]%s", host, path)) {
+ if (1 != ::sscanf(url, "http://%[^:/]", host)) {
+ status = -1;
+ }
+ else { *port = DEFAULT_SERVER_PORT; ACE_OS::strcpy(path, "/"); }
+ }
+ else *port = DEFAULT_SERVER_PORT;
+ }
+ else ACE_OS::strcpy(path, "/");
+ }
+
+ // 0 => success
+ // -1 => error
+ return status;
+}
+
+#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION)
+template class ACE_Connector<HTTP_Handler,ACE_SOCK_CONNECTOR>;
+
+template class ACE_Svc_Tuple<HTTP_Handler>;
+template class ACE_Svc_Handler<ACE_SOCK_STREAM,ACE_NULL_SYNCH>;
+
+template class ACE_Map_Entry<ACE_HANDLE,ACE_Svc_Tuple<HTTP_Handler>*>;
+template class ACE_Map_Manager<ACE_HANDLE,ACE_Svc_Tuple<HTTP_Handler>*,ACE_SYNCH_RW_MUTEX>;
+template class ACE_Map_Iterator<ACE_HANDLE,ACE_Svc_Tuple<HTTP_Handler>*,ACE_SYNCH_RW_MUTEX>;
+#endif /* ACE_TEMPLATES_REQUIRE_SPECIALIZATION */
diff --git a/apps/JAWS/clients/Caching/http_handler.h b/apps/JAWS/clients/Caching/http_handler.h
new file mode 100644
index 00000000000..68559323501
--- /dev/null
+++ b/apps/JAWS/clients/Caching/http_handler.h
@@ -0,0 +1,39 @@
+/* -*- c++ -*- */
+
+#include "ace/Connector.h"
+#include "ace/SOCK_Connector.h"
+
+class HTTP_Handler
+ : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+{
+public:
+ HTTP_Handler (void);
+ HTTP_Handler (const char * path);
+
+ virtual int open (void *);
+ virtual int svc (void);
+
+private:
+ int send_n (const void *, size_t);
+ int recv_n (void *, size_t);
+
+private:
+ char request_[BUFSIZ];
+ int request_size_;
+
+ char filename_[BUFSIZ];
+ int response_size_;
+};
+
+class HTTP_Connector
+{
+public:
+ int connect (const char * url);
+
+private:
+ int parseurl (const char *url, char *host, unsigned short *port, char *path);
+
+private:
+ ACE_Connector<HTTP_Handler, ACE_SOCK_CONNECTOR> connector_;
+};
+