Subject: [clisp-list] Re: CLISP Apache module

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Mon Jan 6 01:58:06 2003

Edi Weitz wrote, quoting John K. Hinsdale:
>> well, almost ... except that it's not always allowed in my case to
>> collect up the entire output before beginning to send back to the Web
>> client.  (I have some pages that need to begin producing displayed
>> output before the request is completely processed

>Hmm, that also rules out using mod_lisp's "Keep-Socket" feature which
>is one of its highlights. You _must_ send a correct Content-Length
>header before you send the body - kind of like HTTP/1.1 Keep-alive.

What about the HTTP/1.1 chunked transfer encoding? Would that work with mod_lisp?
Or is that an enhancement request for Marc Battyani?

>>  > (let ((html (with-output-to-string (*standard-output*)
>>  >                 (my-old-script))))
>>  >     (send-data-to-mod-lisp html))
You could write a more complex with-output-to-mod-lisp using a generic or gray stream approach: *standard-output* bound to this stream object which would redirect to the mod_lisp socket as soon as output arrives (or better: in not too small chunks, e.g. 4KB pieces).

Regards,
	Jorg Hohle.

---

From: Edi Weitz <[email-masked]>
Date: Mon Jan 6 02:16:02 2003

> What about the HTTP/1.1 chunked transfer encoding? Would that work with mod_lisp?

Currently not. I think it would be a good idea, though.

I have no idea how hard this would be to implement with the Apache C
API. Maybe I'll look into this by the end of this month.

Cheers,
Edi.

PS: BTW, for those of you who are using mod_lisp - there's a bug in
    how it handles the situation where the client has aborted the
    connection prematurely. Marc will have a new release online in the
    next days. Until then here's a patch:

edi@bird:/usr/local/build > diff -u mod_lisp.c.orig mod_lisp.c
--- mod_lisp.c.orig     Thu Jan  2 20:07:23 2003
+++ mod_lisp.c  Thu Jan  2 20:35:54 2003
@@ -487,13 +487,13 @@
 #endif
 }

-int ForceGets(char *s, BUFF *BuffSocket)
+int ForceGets(char *s, BUFF *BuffSocket, int len)
 {
   int ret, i;

   for (i =0; i < 10; i++)
     {
-      ret = ap_bgets(s, HEADER_STR_LEN,  BuffSocket);
+      ret = ap_bgets(s, len,  BuffSocket);
       if (ret > 0)
        return ret;
       ap_bsetflag(BuffSocket, B_RD, 1);
@@ -699,7 +699,7 @@
   /* Receive the response from Lisp */
   ap_hard_timeout("lisp-read", r);

-  while (ForceGets(Header, (BUFF *) BuffSocket) >= 0)
+  while (ForceGets(Header, (BUFF *) BuffSocket, HEADER_STR_LEN) >= 0)
     {
       int l;
      l = strlen(Header);
@@ -775,7 +775,12 @@
   /* Send headers and data collected (if this was not a "header only" req. */
   ap_send_http_header(r);
   if (!r->header_only && ContentLength > 0)
-    ap_send_fb_length(BuffSocket, r, ContentLength);
+    if (ap_send_fb_length(BuffSocket, r, ContentLength) < ContentLength || r->connection->aborted)
+      {
+        char buffer[HUGE_STRING_LEN];
+
+        while (ForceGets(buffer, (BUFF *) BuffSocket, HUGE_STRING_LEN)  > 0);
+      }

 #ifdef WIN32
   KeepSocket = 0;

---

From: "John K. Hinsdale" <[email-masked]>
Date: Tue Jan 7 05:18:02 2003

> API. Maybe I'll look into this by the end of this month.

hi edi,

Just a note of progress on my quest for faster Web CGIs written in
CLISP.  As an alternative to mod_lisp, or a native CLISP Apache
module, I'm checking out "FastCGI", a process model and API/protocol
for persistent "application servers" that run behind a Web server.
It's similar to mod_lisp -- a separate application server process, and
a proprietary protocol for multiplexing all the HTTP traffic over a
single socket or pipe.  However, FastCGI looks very stable, widely
supported (incl. Microsoft IIS, not that I would ever use that :) and
is language independent.

Only problem is that there is no implementation of the protocol for
Common Lisp (thougt they do have one for Guile Scheme (!)).  Ah, but
there is for "C" so all I would do is have to write a FFI wrapper,
which I'm getting pretty good at.  So next step is to run some tests
using its "C" API, and if I like what I see I'll wrap CLISP bindings
around it.

It appears that Apache modules are not *that* easy to write, and a lot
of the nitty gritties have been done (and redone) by many other
modules (e.g., mod_fastcgi) that it doesn't appear worthwhile to me to
try to make a native CLISP Apache module, e.g., "mod_clisp".  Nor,
with this approach, would it be necessary to extract the CLISP engine
so that it could be linked in and embedded in some other "C" program
-- what a relief :)

will keep you posted ...

---
John Hinsdale, Alma Mater Software, Inc., Tarrytown, NY 10591-3710 USA
[email-masked] | http://www.alma.com/staff/hin | +1 914 631 4690

---

From: Edi Weitz <[email-masked]>
Date: Tue Jan 7 05:29:05 2003

"John K. Hinsdale" <[email-masked]> writes:

>  > I have no idea how hard this would be to implement with the
>  > Apache C API. Maybe I'll look into this by the end of this month.
> 
> hi edi,
> 
> It's similar to mod_lisp -- a separate application server process,
> and a proprietary protocol for multiplexing all the HTTP traffic
> over a single socket or pipe.  However, FastCGI looks very stable,
> widely supported (incl. Microsoft IIS, not that I would ever use
> that :) and is language independent.
> 

Sounds like a worthwhile task although - if I had to choose - I'd
appreciate if you'd use UFFI... :)

> It appears that Apache modules are not *that* easy to write, and a
> lot of the nitty gritties have been done (and redone) by many other
> modules (e.g., mod_fastcgi) that it doesn't appear worthwhile to me
> to try to make a native CLISP Apache module, e.g., "mod_clisp".
> Nor, with this approach, would it be necessary to extract the CLISP
> engine so that it could be linked in and embedded in some other "C"
> program -- what a relief :)

Yep, Apache modules aren't trivial to do - although from the few small
ones I wrote I think that the Apache API is quite good. However, the
main drawback of something like mod_clisp would have been that you end
up with lots of different Lisp images as opposed to one image with
mod_lisp and also (?) with FastCGI.

Good luck and keep us posted.

Cheers,
Edi.

---

From: "John K. Hinsdale" <[email-masked]>
Date: Tue Jan 7 05:39:03 2003

> appreciate if you'd use UFFI... :)

OK, I'll check that out.  I thought UFFI didn't work in CLISP.  But if
it does then I'll use it, as I think that is more portable to other CL
implementations, no?

 > However, the main drawback of something like mod_clisp would have been
 > that you end up with lots of different Lisp images as opposed to one
 > image with mod_lisp

That is correct, it would have a separate CLISP image (run
environment) embedded into each Apache subprocess.  The advantage,
though is that I wouldn't have to rely on threading support in the CL
implementation, and also my application would not have to be
thread-safe.  For example, my very own Oracle interface to CLISP
caches connections in a global Lisp variable whose access is not
serialized across multiple threads in the Lisp program -- shame on me.
I suppose I should put a warning about that in the docs.

 > and also (?) with FastCGI.

It appears you can choose w/ FastCGI to have it manage its spawned
activities as separate processes or threads-in-a-process.  I'm going
to choose the former due to my two constraints above, but there is no
reason I won't be able to easily migrate to the latter someday.

FYI, I did some pre-tests on my regular CGI-based Oracle application
in CLISP.  I compared a CGI request with one database query against
another one that executed the same query over 100 times, and I've
found that when the fixed cost of initial overhead is subtracted out,
the "variable" cost of the request is only about one tenth of the
total.  I'm not sure how much of the initial overhead is CLISP
starting up, my stuff connecting to Oracle, or what.  But whatever it
is, this means that when I get a solution working that uses a
persistent CLISP process (and databse connections, etc.), I should
expect a ten-fold improvement in my response times.  So that is why
I'm keen on it.

---

From: Edi Weitz <[email-masked]>
Date: Tue Jan 7 05:55:07 2003

"John K. Hinsdale" <[email-masked]> writes:

> OK, I'll check that out.  I thought UFFI didn't work in CLISP.  But
> if it does then I'll use it, as I think that is more portable to
> other CL implementations, no?

No, AFAIK it doesn't work with CLISP (yet) - that's why I put the
smiley there. But maybe FastCGI bindings based on UFFI would be
another incentive to make CLISP and UFFI work together... :)

Cheers,
Edi.

---

From: Sam Steingold <[email-masked]>
Date: Tue Jan 7 07:23:01 2003

> * In message <[email-masked]>
> * On the subject of "Re: [clisp-list] Re: CLISP Apache module"
> * Sent on 07 Jan 2003 14:54:30 +0100
> * Honorable Edi Weitz <[email-masked]> writes:
>

we do not need an incentive. what we do need is a volunteer. :-(

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
Don't hit a man when he's down -- kick him; it's easier.

---

From: "Johannes Grødem" <[email-masked]>
Date: Tue Jan 7 13:22:07 2003

* "John K. Hinsdale" <[email-masked]>:

> and is language independent.

mod_lisp is too, as far as I can tell, it's just called mod_lisp
because the author uses it with Lisp.

-- 
Johannes Grødem <OpenPGP: 5055654C>

---

From: "John K. Hinsdale" <[email-masked]>
Date: Thu Jan 9 07:18:02 2003

> From: Edi Weitz <[email-masked]>
 > Date: 07 Jan 2003 14:28:41 +0100

 > mod_lisp and also (?) with FastCGI.

Hi all, following up on integrating CLISP w/ Apache, I've had
excellent results using the "FastCGI" library to speed up my
CLISP-based web scripts.  I'm convinced this is a much better way to
go than writing a native Apache module just for CLISP, as the latter
would have involved re-inventing a lot of functionality already
developed and debugged by FastCGI developers over the last 5 to 6
years.

I ended up writing a CLISP FFI wrapper (sorry, no UFFI) around
FastCGI's "C" interface, and using that as a drop-in CGI replacement.
It works great.  Benchmarks show that, for my application, average
turnaround time to the Web browser has been reduced from 0.96 seconds
to 0.11 seconds, or about 8.7 times faster.  For an interactive
database-driven Web site doing queries w/ each click of the mouse, the
difference b/w a delay of 1 sec and 0.1 sec is quite noticable, and is
essentially the difference b/w a "fast" site and "slow" site.

I've GPL'd, documented and packaged up the module so it can be used by
others.  It can be downloaded at http://clisp.alma.com ...  My module
would appear to be the first Common Lisp implementation of FastCGI,
which already has interfaces for C, C++, Guile Scheme, Goanna Eiffel,
SmallEiffel, Java, Perl, Python, and Smalltalk.  A bit late to the
party, eh :)

I invite anyone using CLISP for Web CGIs to use this library and give
some feedback as to how much faster it makes things.  I'll help you
get it working.

For those wondering what happened w/ my efforts to use mod_lisp, I
found FastCGI a better choice for my particular purposes and
environment (CLISP), after considering a whole mosaic of issues.  Here
is a re-cap of my situation as to whether to use FastCGI vs. mod_lisp:

mod_lisp pros & cons (for ME, YMMV)

  PRO: uses native O/S multi-threading; more efficient concurrency
  CON: one's code must be thread safe (but mine's not)
  CON: thread support required in CL implementation (CLISP has not)
  PRO: uses one Lisp image, sharing memory
  CON: requires one to implement his own pooling of any resources not
       managed by mod_lisp (e.g., database connections)
  CON: requires one to manage separate process for application
       servers handling restart separately from Web server (this
       could be a PRO depending on who you are)
  CON: Need separate programs to use as plain old CGI (e.g., for
       interactive development) vs. in application server mode.
       This is not so huge an issue.
       
CLISP+FastCGI pros & cons (for ME, YMMV)

  CON: forks separate O/S processes for each thread, less efficient
       in highly concurrent environment (but mine's not)
  PRO: code need not be thread safe (and mine's not)
  PRO: no requirement for threads, so works with CLISP
  CON: separate CLISP images, sucking memory
  PRO: pooling of any resources cached globally in Lisp (e.g.,
       my database connections, query results) is handled automatically
       by FastCGI library
  PRO: application processes are spawned and killed off
       automatically by the Web server; restart of Web
       server also restarts application server(s).  Could
       be a CON depending on who you are
  PRO: exact same program can be use in CGI mode vs. FastCGI
       mode.  Useful to run as CGI when developing as new
       process is created every time and code changes
       are reflected immediately. This is not so huge an
       issue.

There were three FastCGI "pro's" which, for me, would in and of
themselves have tipped the scale: the "works w/ CLISP", "don't need
thread safe code" and "don't have to write one's own pool" issues.

---

---

From: Sam Steingold <[email-masked]>
Date: Thu Jan 9 11:56:01 2003

> * In message <[email-masked]>
> * On the subject of "[clisp-list] FastCGI working; library available (was: Re: CLISP Apache module)"
> * Sent on Thu, 9 Jan 2003 10:16:47 -0500
> * Honorable "John K. Hinsdale" <[email-masked]> writes:
>
> others.

Great news!

> It can be downloaded at http://clisp.alma.com ...

would you like to have your module distributed with CLISP?
please put it into the CVS!

It would also be nice if you wrote a manual for both this and your
oracle module (preferably in DocBook/XML format, please see
modules/regexp/regexp.xml for an example.)

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
You think Oedipus had a problem -- Adam was Eve's mother.

---

From: "John K. Hinsdale" <[email-masked]>
Date: Thu Jan 9 12:45:01 2003

> please put it into the CVS!

ok, done.

 > modules/regexp/regexp.xml for an example.)

OK I'll try to come up with some more "professional" than just those
README's.

---

From: Sam Steingold <[email-masked]>
Date: Thu Jan 9 15:23:02 2003

> * In message <[email-masked]>
> * On the subject of "Re: FastCGI working; library available (was: Re: CLISP Apache module)"
> * Sent on Thu, 9 Jan 2003 15:43:50 -0500

don't forget to update src/NEWS and src/ChangeLog

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
Your mouse pad is incompatible with MS Windows - your HD will be reformatted.

---

From: "John K. Hinsdale" <[email-masked]>
Date: Thu Jan 9 16:40:05 2003

> From: "John K. Hinsdale" <[email-masked]>

 > My module would appear to be the first Common Lisp implementation
 > of FastCGI, which already has interfaces for C, C++, Guile Scheme,
 > Goanna Eiffel, SmallEiffel, Java, Perl, Python, and Smalltalk.

Quick note of correction: the above is not true.  Teemu Kalvas has
written a Common Lisp FastCGI library and server for CMUCL, at:

   http://www.s2.org/~chery/projects/fastcgi-cmucl

This is different from my CLISP binding (and for the bindings to many
of the other languages that support FastCGI) in that instead of being
just wrappers that call the original FastCGI "C" library, c.a., 1995,
Teemu's is a complete implementation of the FastCGI binary packet
protocol in Lisp, from scratch.

---