On Sat, Jan 3, 2009 at 12:31 AM, Abdulaziz Ghuloum <[email protected]> wrote:
>
>
> On Jan 2, 2009, at 9:32 AM, Patrik Husfloen wrote:
>
>>
>> Hello,
>>
>> I've been working on a Fast CGI [1] library for Ikarus (and other R6
>> compliant schemes?)
>
> Have you considered using mod_lisp?  I tried it, and it seems to
> be an easier route than using fcgi.

Yeah I agree, and if all I wanted was to get it work, that's what I
would've done.
I set out to write a FastCGI library because it's a standard protocol,
supported by IIS, Apache, and Lighttpd, but mostly because it's a
challenge and an opportunity to learn something new (Scheme).
>
>> I'm currently using make-custom-binary-output-port to create ports for
>> stdout and stderr and because I want to support multiplexed
>> connections over the fcgi connection
>
> Custom ports would not give you a way to do IO multiplexing.
> In Ikarus, you can use the nonblocking sockets for that, but
> you'd be writing ikarus-specific code then.
>

Derick pretty much nailed it, fcgi (can) utilize a single connection
to send concurrent requests from the web server to the application,
each fcgi packet has the request-id, and my implementation keeps a
hashtable (I should change it to a vector because fcgi keeps the
request-ids as low as possible, and I'm guessing it would be a lot
faster.) with the request-id as the key and the state of the request
the value. It goes something like this:

(let loop ()
 (let* ([record (get-fcgi-record input)] ; input is the socket input port
        [request-id (fcgi-record-request-id record)]
        [request (hashtable-ref requests request-id '())])
   (cond [(= request-id 0)
          (printf "Management record: ~a\n" record)]
         [(null? request)
          (hashtable-set! requests request-id (make-fcgi-request record))]
         [else
           (let-values ([(state next) (request record)])
                       (cond [(eq? state 'completed)
                              (printf "Dispatch: ~a\n" next)
                              (cond [(fcgi-responder-request? next)
                                     (dispatch-fcgi-responder
responder request-id next output)]) ; TODO add authorizer & filter
support
                              (hashtable-delete! requests request-id)
                              (unless (memq 'keep-conn
(fcgi-request-flags next))
                                (escape))]
                             [(eq? state 'error)
                              (printf "Handle error ~a\n" next)
                              (hashtable-delete! requests request-id)]
                             [else
                               (printf "State: ~a\n" state)
                               (hashtable-set! requests request-id next)]))]))

 (loop)


>> the port has its own buffer that
>> it writes to, when a threshold is reached (or close is called) it's
>> written to the socket,
>
> Correct.  When you write something to a port, at some point,
> the data will be flushed.
>
>> but I would also like detect when "flush-output-buffer" is called,
>
> Well, flush-output-port means: flush the output port.  The port
> may be flushed without you explicitly saying "flush-output-port",
> so, you cannot distinguish the two reasons, and you should not
> need to.
>
>> so I can force the buffered data to be written to the fcgi connection.
>
> You should force the data when the port is flushed, e.g., when your
> custom port's "write!" procedure is called, and when the port is
> closed, if you're maintaining an additional buffer.
>
>> The R6RS spec mentions buffer-modes on ports, and says that each port
>> has one of three buffer modes: "none", "line" , "block", and it
>> mentions how to check the buffer mode on a port,
>
> Ikarus does not implement line-buffering yet; it does implement the
> "none" and "block" buffer modes for file-based ports.
>
>> but I can't see any
>> mention on how to set it, and also, if you can set it, can I implement
>> my own custom buffer mode, or would I have to set it to "none" and
>> implement the buffering in the port?
>
> I would think that you'd have to set it to "none" and implement
> your own buffering.  But as you observed, there is no way to set
> (or specify) the buffering mode of a custom port as per R6RS.
>
>> Or can you change the properties
>> of the "block" buffer mode on a per port basis?
>
> This will all have to be on a per port basis.
>
>> But the port returned by make-custom-binary-output-port has buffer
>> mode "block".  Which means that when I call flush-output-port on
>> stdout, all I get is whatever data the port buffer has buffered, and
>> not an indication that "flush" was called.
>
> Correct.
>
>> I was hoping that with
>> buffer-mode "none" I could detect a "flush" as a zero byte write and
>> write whatever I have in my buffer to the socket, but that might be
>> wishful thinking, maybe there's an easier way to accomplish what I
>> want?
>
> Can we start from the beginning.  What are you trying to accomplish?
> Forget about what's in Ikarus/R6RS/whatever at the moment.  What are
> you trying to do exactly?
>

Certainly, since fcgi multiplexes many web requests over a single tcp
connection I wrote the above code to manage all the requests, now,
when I dispatch the request to the request handler I pass it the
output port returned by accept-connection-nonblocking, it wraps it in
a custom output port so that the request handler gets a nice standard
way of writing output, binary or textual.

But since data can only be sent to the webserver (over the fcgi
connection) in length prefixed chunks I need to buffer the data before
sending it to reduce overhead from the fcgi protocol. so far there are
no problems (other than the unnecessary double buffering).

But, as a user of the fcgi-server I also want to be able to force data
to be sent, in order to "stream" something to the client.
Flush-output-port does exactly this, except when using
make-custom-binary-output-port I have no way of telling it was called.


>> Happy new year everyone!
>
> Same to you!
>
> Aziz,,,
>

I hope that makes more sense.

/Patrik

Reply via email to