r5233: *** empty log message ***
[cl-modlisp.git] / base.lisp
1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: modlisp -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
5 ;;;; Name:          base.lisp
6 ;;;; Purpose:       Utility functions for modlisp package
7 ;;;; Programmer:    Kevin M. Rosenberg
8 ;;;; Date Started:  Dec 2002
9 ;;;;
10 ;;;; $Id: base.lisp,v 1.3 2003/07/05 00:51:04 kevin Exp $
11 ;;;; *************************************************************************
12
13 (in-package #:modlisp)
14
15
16 (let ((*listener-socket* nil)
17       (*listener-process* nil))
18
19   (defun modlisp-start (&key (port +default-apache-port+)
20                              (function 'demo-apache-command-processor))
21     (handler-case
22         (make-socket-server (next-server-name) function port
23                             :format :text :wait nil)
24       (error (e)
25         (format t "~&Error while trying to start modlisp server~&  ~A" e)
26         (decf *listener-count*)
27         nil)
28       (:no-error (process socket)
29         (setq *listener-socket* socket)
30         (setq *listener-process* process)
31         process)))
32   
33   (defun modlisp-stop ()
34     (when *listener-process*
35       (format t "~&; killing modlisp server process ~A~%" *listener-process*)
36       (handler-case
37           (progn
38             #+sbcl (sb-thread:destroy-thread *listener-process*)
39             #+cmucl (mp:destroy-process *listener-process*)
40             #+allegro (mp:process-kill *listener-process*)
41             #+allegro (mp:process-allow-schedule)
42             #+lispworks (mp:process-kill *listener-process*))
43         (error (e)
44           (format t "~&Error while trying to kill modlisp server~&  ~A" e))
45         (:no-error (res)
46           (declare (ignore res))
47           (setq *listener-process* nil))))
48     (when *listener-socket*
49       (ignore-errors (close *listener-socket*))
50       (setq *listener-socket* nil)))
51   
52  ) ;; closure
53     
54 (defun next-server-name ()
55   (format nil "modlisp-socket-server-~d" (incf *listener-count*))) 
56
57 (defun next-worker-name ()
58   (format nil "modlisp-worker-~d" (incf *worker-count*)))
59
60 (let ((*number-server-requests* 0)
61       (*number-worker-requests* 0)
62       (*close-apache-socket* t))
63   
64   (defun apache-command-issuer (*apache-socket* processor-fun)
65     "generates commands from apache, issues commands to processor-fun"
66     (unwind-protect
67          (progn
68            (setq *number-worker-requests* 0)
69            (do ((command (read-apache-command) (read-apache-command)))
70                ((null command) 'done)
71              (funcall processor-fun command)
72              (force-output *apache-socket*)
73              (incf *number-worker-requests*)
74              (incf *number-server-requests*)
75              (when *close-apache-socket*
76                (return))))
77       (close *apache-socket*)))
78
79   (defun get-number-worker-requests ()
80     *number-worker-requests*)
81
82   (defun get-number-server-requests ()
83     *number-server-requests*)
84   
85   (defun set-close-apache-socket (close?)
86     (setq *close-apache-socket* close?))
87   
88   ) ;; closure
89
90 (defun read-apache-command ()
91   (ignore-errors
92     (let* ((header (read-apache-header))
93           (content-length (cdr (assoc "content-length" header :test #'equal)))
94           (content (when content-length 
95                      (make-string
96                       (parse-integer content-length :junk-allowed t)))))
97      (when content
98        (read-sequence content *apache-socket*)
99        (push (cons "posted-content" content) header))
100      header)))
101
102 (defun read-apache-header ()
103   (loop for key = (read-line *apache-socket* nil nil)
104                         while (and key
105                                    (string-not-equal key "end")
106                                    (> (length key) 1))
107                       for value = (read-line *apache-socket* nil nil)
108                       collect (cons key value)))
109
110 (defun write-header-line (key value)
111   (write-string key *apache-socket*)
112   (write-char #\NewLine *apache-socket*)
113   (write-string value *apache-socket*)
114   (write-char #\NewLine *apache-socket*))
115
116 (defun header-value (command key)
117   (cdr (assoc key command :test #'string=)))
118