thread specific execution context
svn: r3983
This commit is contained in:
parent
8b60b3202c
commit
27e7ddad4f
|
@ -15,6 +15,7 @@
|
||||||
"../managers/manager.ss"
|
"../managers/manager.ss"
|
||||||
"../managers/timeouts.ss"
|
"../managers/timeouts.ss"
|
||||||
"../managers/lru.ss"
|
"../managers/lru.ss"
|
||||||
|
"../managers/none.ss"
|
||||||
"../private/url.ss"
|
"../private/url.ss"
|
||||||
"../private/servlet.ss"
|
"../private/servlet.ss"
|
||||||
"../private/cache-table.ss")
|
"../private/cache-table.ss")
|
||||||
|
@ -76,69 +77,71 @@
|
||||||
(lambda (the-exn)
|
(lambda (the-exn)
|
||||||
(output-response/method conn (responders-servlet-loading uri the-exn) (request-method req)))])
|
(output-response/method conn (responders-servlet-loading uri the-exn) (request-method req)))])
|
||||||
(define servlet-mutex (make-semaphore 0))
|
(define servlet-mutex (make-semaphore 0))
|
||||||
(define last-servlet (thread-cell-ref current-servlet))
|
(define response
|
||||||
(define last-servlet-instance-id (thread-cell-ref current-servlet-instance-id))
|
(let/cc suspend
|
||||||
(let/cc suspend
|
; Create the session frame
|
||||||
; Create the session frame
|
(with-frame
|
||||||
(with-frame
|
(define instance-custodian (make-servlet-custodian))
|
||||||
(define instance-custodian (make-servlet-custodian))
|
(define servlet-path
|
||||||
(define servlet-path
|
(with-handlers
|
||||||
(with-handlers
|
([void (lambda (e)
|
||||||
([void (lambda (e)
|
(raise (make-exn:fail:filesystem:exists:servlet
|
||||||
(raise (make-exn:fail:filesystem:exists:servlet
|
(exn-message e)
|
||||||
(exn-message e)
|
(exn-continuation-marks e))))])
|
||||||
(exn-continuation-marks e))))])
|
(url-path->path
|
||||||
(url-path->path
|
servlet-root
|
||||||
servlet-root
|
(url-path->string (url-path uri)))))
|
||||||
(url-path->string (url-path uri)))))
|
(parameterize ([current-directory (get-servlet-base-dir servlet-path)]
|
||||||
(parameterize ([current-directory (get-servlet-base-dir servlet-path)]
|
[current-custodian instance-custodian]
|
||||||
[current-custodian instance-custodian]
|
[exit-handler
|
||||||
[exit-handler
|
(lambda _
|
||||||
(lambda _
|
(kill-connection! conn)
|
||||||
(kill-connection! conn)
|
(custodian-shutdown-all instance-custodian))])
|
||||||
(custodian-shutdown-all instance-custodian))])
|
;; any resources (e.g. threads) created when the
|
||||||
;; any resources (e.g. threads) created when the
|
;; servlet is loaded should be within the dynamic
|
||||||
;; servlet is loaded should be within the dynamic
|
;; extent of the servlet custodian
|
||||||
;; extent of the servlet custodian
|
(define the-servlet (cached-load servlet-path))
|
||||||
(define the-servlet (cached-load servlet-path))
|
(thread-cell-set! current-servlet the-servlet)
|
||||||
(thread-cell-set! current-servlet the-servlet)
|
(parameterize ([current-namespace (servlet-namespace the-servlet)])
|
||||||
(parameterize ([current-namespace (servlet-namespace the-servlet)])
|
(define manager (servlet-manager the-servlet))
|
||||||
(define manager (servlet-manager the-servlet))
|
(define ctxt
|
||||||
(define data
|
(make-execution-context
|
||||||
(make-servlet-instance-data
|
conn req suspend))
|
||||||
servlet-mutex
|
(define data
|
||||||
(make-execution-context
|
(make-servlet-instance-data
|
||||||
conn req (lambda () (suspend #t)))))
|
servlet-mutex))
|
||||||
(define the-exit-handler
|
(define the-exit-handler
|
||||||
(lambda _
|
(lambda _
|
||||||
(kill-connection!
|
(kill-connection!
|
||||||
(execution-context-connection
|
(execution-context-connection
|
||||||
(servlet-instance-data-context
|
(thread-cell-ref current-execution-context)))
|
||||||
data)))
|
(custodian-shutdown-all instance-custodian)))
|
||||||
(custodian-shutdown-all instance-custodian)))
|
(thread-cell-set! current-execution-context ctxt)
|
||||||
(parameterize ([exit-handler the-exit-handler])
|
(parameterize ([exit-handler the-exit-handler])
|
||||||
(define instance-id ((manager-create-instance manager) data the-exit-handler))
|
(define instance-id ((manager-create-instance manager) data the-exit-handler))
|
||||||
(parameterize ([exit-handler (lambda x
|
(parameterize ([exit-handler (lambda x
|
||||||
((manager-instance-unlock! manager) instance-id)
|
((manager-instance-unlock! manager) instance-id)
|
||||||
(the-exit-handler x))])
|
(the-exit-handler x))])
|
||||||
(thread-cell-set! current-servlet-instance-id instance-id)
|
(thread-cell-set! current-servlet-instance-id instance-id)
|
||||||
((manager-instance-lock! manager) instance-id)
|
((manager-instance-lock! manager) instance-id)
|
||||||
(with-handlers ([(lambda (x) #t)
|
(with-handlers ([(lambda (x) #t)
|
||||||
(make-servlet-exception-handler data)])
|
(make-servlet-exception-handler data)])
|
||||||
;; Two possibilities:
|
;; Two possibilities:
|
||||||
;; - module servlet. start : Request -> Void handles
|
;; - module servlet. start : Request -> Void handles
|
||||||
;; output-response via send/finish, etc.
|
;; output-response via send/finish, etc.
|
||||||
;; - unit/sig or simple xexpr servlet. These must produce a
|
;; - unit/sig or simple xexpr servlet. These must produce a
|
||||||
;; response, which is then output by the server.
|
;; response, which is then output by the server.
|
||||||
;; Here, we do not know if the servlet was a module,
|
;; Here, we do not know if the servlet was a module,
|
||||||
;; unit/sig, or Xexpr; we do know whether it produces a
|
;; unit/sig, or Xexpr; we do know whether it produces a
|
||||||
;; response.
|
;; response.
|
||||||
(define r ((servlet-handler the-servlet) req))
|
(define r ((servlet-handler the-servlet) req))
|
||||||
(when (response? r)
|
(when (response? r)
|
||||||
(send/back r)))
|
(send/back r)))
|
||||||
((manager-instance-unlock! manager) instance-id)))))))
|
((manager-instance-unlock! manager) instance-id))))))))
|
||||||
(thread-cell-set! current-servlet last-servlet)
|
(output-response conn response)
|
||||||
(thread-cell-set! current-servlet-instance-id last-servlet-instance-id)
|
(thread-cell-set! current-execution-context #f)
|
||||||
|
(thread-cell-set! current-servlet #f)
|
||||||
|
(thread-cell-set! current-servlet-instance-id #f)
|
||||||
(semaphore-post servlet-mutex)))
|
(semaphore-post servlet-mutex)))
|
||||||
|
|
||||||
;; default-server-instance-expiration-handler : (request -> response)
|
;; default-server-instance-expiration-handler : (request -> response)
|
||||||
|
@ -160,18 +163,13 @@
|
||||||
;; requests won't be blocked.
|
;; requests won't be blocked.
|
||||||
;; * This fixes PR# 7066
|
;; * This fixes PR# 7066
|
||||||
(define ((make-servlet-exception-handler inst-data) the-exn)
|
(define ((make-servlet-exception-handler inst-data) the-exn)
|
||||||
(define context (servlet-instance-data-context inst-data))
|
(define context (thread-cell-ref current-execution-context))
|
||||||
(define request (execution-context-request context))
|
(define request (execution-context-request context))
|
||||||
(define resp
|
(define resp
|
||||||
(responders-servlet
|
(responders-servlet
|
||||||
(request-uri request)
|
(request-uri request)
|
||||||
the-exn))
|
the-exn))
|
||||||
;; Don't handle twice
|
((execution-context-suspend context) resp))
|
||||||
(with-handlers ([exn:fail? (lambda (exn) (void))])
|
|
||||||
(output-response/method
|
|
||||||
(execution-context-connection context)
|
|
||||||
resp (request-method request)))
|
|
||||||
((execution-context-suspend context)))
|
|
||||||
|
|
||||||
;; path -> path
|
;; path -> path
|
||||||
;; The actual servlet's parent directory.
|
;; The actual servlet's parent directory.
|
||||||
|
@ -191,8 +189,6 @@
|
||||||
(url-path->path
|
(url-path->path
|
||||||
servlet-root
|
servlet-root
|
||||||
(url-path->string (url-path uri))))
|
(url-path->string (url-path uri))))
|
||||||
(define last-servlet (thread-cell-ref current-servlet))
|
|
||||||
(define last-servlet-instance-id (thread-cell-ref current-servlet-instance-id))
|
|
||||||
(define the-servlet (cached-load servlet-path))
|
(define the-servlet (cached-load servlet-path))
|
||||||
(define manager (servlet-manager the-servlet))
|
(define manager (servlet-manager the-servlet))
|
||||||
(thread-cell-set! current-servlet the-servlet)
|
(thread-cell-set! current-servlet the-servlet)
|
||||||
|
@ -225,17 +221,18 @@
|
||||||
; always call a continuation. The exit-handler above ensures that
|
; always call a continuation. The exit-handler above ensures that
|
||||||
; the post is done.
|
; the post is done.
|
||||||
(semaphore-wait (servlet-instance-data-mutex data))
|
(semaphore-wait (servlet-instance-data-mutex data))
|
||||||
(let/cc suspend
|
(let ([response
|
||||||
(define k ((manager-continuation-lookup manager) instance-id k-id salt))
|
(let/cc suspend
|
||||||
(set-servlet-instance-data-context!
|
(define k ((manager-continuation-lookup manager) instance-id k-id salt))
|
||||||
data
|
(thread-cell-set! current-execution-context
|
||||||
(make-execution-context
|
(make-execution-context
|
||||||
conn req (lambda () (suspend #t))))
|
conn req suspend))
|
||||||
(k req))
|
(k req))])
|
||||||
|
(output-response conn response))
|
||||||
(semaphore-post (servlet-instance-data-mutex data))))
|
(semaphore-post (servlet-instance-data-mutex data))))
|
||||||
((manager-instance-unlock! manager) instance-id)
|
((manager-instance-unlock! manager) instance-id)
|
||||||
(thread-cell-set! current-servlet-instance-id last-servlet-instance-id)
|
(thread-cell-set! current-servlet-instance-id #f)
|
||||||
(thread-cell-set! current-servlet last-servlet))
|
(thread-cell-set! current-servlet #f))
|
||||||
|
|
||||||
;; ************************************************************
|
;; ************************************************************
|
||||||
;; ************************************************************
|
;; ************************************************************
|
||||||
|
@ -281,11 +278,13 @@
|
||||||
(lambda (initial-request)
|
(lambda (initial-request)
|
||||||
(invoke-unit/sig servlet servlet^)))
|
(invoke-unit/sig servlet servlet^)))
|
||||||
(define (v0.response->v1.lambda response-path response)
|
(define (v0.response->v1.lambda response-path response)
|
||||||
(letrec ([go (lambda ()
|
(define go
|
||||||
(begin
|
(box
|
||||||
(set! go (lambda () (load/use-compiled a-path)))
|
(lambda ()
|
||||||
response))])
|
(set-box! go (lambda () (load/use-compiled a-path)))
|
||||||
(lambda (initial-request) (go))))
|
response)))
|
||||||
|
(lambda (initial-request)
|
||||||
|
((unbox go))))
|
||||||
(define (v1.module->v1.lambda timeout start)
|
(define (v1.module->v1.lambda timeout start)
|
||||||
(lambda (initial-request)
|
(lambda (initial-request)
|
||||||
(adjust-timeout! timeout)
|
(adjust-timeout! timeout)
|
||||||
|
|
|
@ -7,11 +7,12 @@
|
||||||
|
|
||||||
(define-struct (exn:fail:servlet:instance exn:fail) ())
|
(define-struct (exn:fail:servlet:instance exn:fail) ())
|
||||||
(define-struct servlet (custodian namespace manager handler))
|
(define-struct servlet (custodian namespace manager handler))
|
||||||
(define-struct servlet-instance-data (mutex context))
|
(define-struct servlet-instance-data (mutex))
|
||||||
(define-struct execution-context (connection request suspend))
|
(define-struct execution-context (connection request suspend))
|
||||||
|
|
||||||
(define current-servlet (make-thread-cell #f))
|
(define current-servlet (make-thread-cell #f))
|
||||||
(define current-servlet-instance-id (make-thread-cell #f))
|
(define current-servlet-instance-id (make-thread-cell #f))
|
||||||
|
(define current-execution-context (make-thread-cell #f))
|
||||||
|
|
||||||
(define (get-current-servlet-instance-id)
|
(define (get-current-servlet-instance-id)
|
||||||
(define instance-id (thread-cell-ref current-servlet-instance-id))
|
(define instance-id (thread-cell-ref current-servlet-instance-id))
|
||||||
|
@ -40,8 +41,7 @@
|
||||||
[manager manager?]
|
[manager manager?]
|
||||||
[handler (request? . -> . servlet-response?)])]
|
[handler (request? . -> . servlet-response?)])]
|
||||||
[struct servlet-instance-data
|
[struct servlet-instance-data
|
||||||
([mutex semaphore?]
|
([mutex semaphore?])]
|
||||||
[context execution-context?])]
|
|
||||||
[struct execution-context
|
[struct execution-context
|
||||||
([connection connection?]
|
([connection connection?]
|
||||||
[request request?]
|
[request request?]
|
||||||
|
@ -50,6 +50,8 @@
|
||||||
[current-servlet thread-cell?]
|
[current-servlet thread-cell?]
|
||||||
; XXX contract maybe
|
; XXX contract maybe
|
||||||
[current-servlet-instance-id thread-cell?]
|
[current-servlet-instance-id thread-cell?]
|
||||||
|
; XXX contract maybe
|
||||||
|
[current-execution-context thread-cell?]
|
||||||
[get-current-servlet-instance-id (-> number?)]
|
[get-current-servlet-instance-id (-> number?)]
|
||||||
[current-servlet-manager (-> manager?)]
|
[current-servlet-manager (-> manager?)]
|
||||||
[current-servlet-instance-data (-> servlet-instance-data?)]))
|
[current-servlet-instance-data (-> servlet-instance-data?)]))
|
|
@ -35,7 +35,6 @@
|
||||||
(lambda (initial-request)
|
(lambda (initial-request)
|
||||||
(let ([v (servlet-expr initial-request)])
|
(let ([v (servlet-expr initial-request)])
|
||||||
(set! final-value v)
|
(set! final-value v)
|
||||||
;(set! final-conn (execution-context-connection (servlet-instance-context (current-servlet-instance))))
|
|
||||||
(semaphore-post sema)
|
(semaphore-post sema)
|
||||||
(if (response? v)
|
(if (response? v)
|
||||||
v
|
v
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
(require (lib "contract.ss")
|
(require (lib "contract.ss")
|
||||||
(lib "etc.ss")
|
(lib "etc.ss")
|
||||||
(lib "xml.ss" "xml"))
|
(lib "xml.ss" "xml"))
|
||||||
(require "response.ss"
|
(require "managers/manager.ss"
|
||||||
"managers/manager.ss"
|
|
||||||
"private/servlet.ss"
|
"private/servlet.ss"
|
||||||
"private/url.ss"
|
"private/url.ss"
|
||||||
"servlet-helpers.ss"
|
"servlet-helpers.ss"
|
||||||
|
@ -71,9 +70,8 @@
|
||||||
;; send/back: response -> void
|
;; send/back: response -> void
|
||||||
;; send a response and don't clear the continuation table
|
;; send a response and don't clear the continuation table
|
||||||
(define (send/back resp)
|
(define (send/back resp)
|
||||||
(define ctxt (servlet-instance-data-context (current-servlet-instance-data)))
|
(define ctxt (thread-cell-ref current-execution-context))
|
||||||
(output-response (execution-context-connection ctxt) resp)
|
((execution-context-suspend ctxt) resp))
|
||||||
((execution-context-suspend ctxt)))
|
|
||||||
|
|
||||||
;; send/finish: response -> void
|
;; send/finish: response -> void
|
||||||
;; send a response and clear the continuation table
|
;; send a response and clear the continuation table
|
||||||
|
@ -93,15 +91,13 @@
|
||||||
(with-frame-after
|
(with-frame-after
|
||||||
(let/cc k
|
(let/cc k
|
||||||
(define instance-id (get-current-servlet-instance-id))
|
(define instance-id (get-current-servlet-instance-id))
|
||||||
(define ctxt (servlet-instance-data-context (current-servlet-instance-data)))
|
(define ctxt (thread-cell-ref current-execution-context))
|
||||||
(define k-embedding ((manager-continuation-store! (current-servlet-manager)) instance-id k expiration-handler))
|
(define k-embedding ((manager-continuation-store! (current-servlet-manager)) instance-id k expiration-handler))
|
||||||
(define k-url ((current-url-transform)
|
(define k-url ((current-url-transform)
|
||||||
(embed-ids
|
(embed-ids
|
||||||
(list* instance-id k-embedding)
|
(list* instance-id k-embedding)
|
||||||
(request-uri (execution-context-request ctxt)))))
|
(request-uri (execution-context-request ctxt)))))
|
||||||
(define response (response-generator k-url))
|
(send/back (response-generator k-url))))))
|
||||||
(output-response (execution-context-connection ctxt) response)
|
|
||||||
((execution-context-suspend ctxt))))))
|
|
||||||
|
|
||||||
;; send/forward: (url -> response) [(request -> response)] -> request
|
;; send/forward: (url -> response) [(request -> response)] -> request
|
||||||
;; clear the continuation table, then behave like send/suspend
|
;; clear the continuation table, then behave like send/suspend
|
||||||
|
|
|
@ -3,24 +3,25 @@
|
||||||
(lib "timer.ss" "web-server")
|
(lib "timer.ss" "web-server")
|
||||||
(lib "response.ss" "web-server")
|
(lib "response.ss" "web-server")
|
||||||
(lib "connection-manager.ss" "web-server"))
|
(lib "connection-manager.ss" "web-server"))
|
||||||
|
|
||||||
(provide start-servlet resume-servlet)
|
(provide start-servlet resume-servlet)
|
||||||
|
|
||||||
;; make-servlet-custodian: -> custodian
|
;; make-servlet-custodian: -> custodian
|
||||||
(define make-servlet-custodian
|
(define make-servlet-custodian
|
||||||
(let ([cust (current-custodian)])
|
(let ([cust (current-custodian)])
|
||||||
(lambda () (make-custodian cust))))
|
(lambda () (make-custodian cust))))
|
||||||
|
|
||||||
;; start-servlet: connection request hash-table number (number->void request -> response) -> void
|
;; start-servlet: connection request hash-table number (number->void request -> response) -> void
|
||||||
;; start a new instance of a servlet
|
;; start a new instance of a servlet
|
||||||
(define (start-servlet conn req instance-table instance-timeout svt)
|
(define (start-servlet conn req instance-table instance-timeout svt)
|
||||||
(let ([sema (make-semaphore 0)])
|
(define sema (make-semaphore 0))
|
||||||
|
(define response
|
||||||
(let/cc suspend
|
(let/cc suspend
|
||||||
(let* ([servlet-custodian (make-servlet-custodian)]
|
(let* ([servlet-custodian (make-servlet-custodian)]
|
||||||
[inst (create-new-instance!
|
[inst (create-new-instance!
|
||||||
instance-table servlet-custodian
|
instance-table servlet-custodian
|
||||||
(make-execution-context
|
(make-execution-context
|
||||||
conn req (lambda () (suspend #t)))
|
conn req suspend)
|
||||||
sema)]
|
sema)]
|
||||||
[servlet-exit-handler (make-servlet-exit-handler inst instance-table)]
|
[servlet-exit-handler (make-servlet-exit-handler inst instance-table)]
|
||||||
[time-bomb (start-timer instance-timeout
|
[time-bomb (start-timer instance-timeout
|
||||||
|
@ -34,9 +35,10 @@
|
||||||
(reset-timer! time-bomb secs))
|
(reset-timer! time-bomb secs))
|
||||||
req)])
|
req)])
|
||||||
(when (response? r)
|
(when (response? r)
|
||||||
(send/back r)))))))
|
(send/back r))))))))
|
||||||
(semaphore-post sema)))
|
(output-respose conn response)
|
||||||
|
(semaphore-post sema))
|
||||||
|
|
||||||
;; make-servlet-exit-handler: servlet-instance -> alpha -> void
|
;; make-servlet-exit-handler: servlet-instance -> alpha -> void
|
||||||
;; exit handler for a servlet
|
;; exit handler for a servlet
|
||||||
(define (make-servlet-exit-handler inst instance-table)
|
(define (make-servlet-exit-handler inst instance-table)
|
||||||
|
@ -46,7 +48,7 @@
|
||||||
(execution-context-connection
|
(execution-context-connection
|
||||||
(servlet-instance-context inst)))
|
(servlet-instance-context inst)))
|
||||||
(custodian-shutdown-all (servlet-instance-custodian inst))))
|
(custodian-shutdown-all (servlet-instance-custodian inst))))
|
||||||
|
|
||||||
;; make-servlet-exception-handler: host -> exn -> void
|
;; make-servlet-exception-handler: host -> exn -> void
|
||||||
;; This exception handler traps all unhandled servlet exceptions
|
;; This exception handler traps all unhandled servlet exceptions
|
||||||
(define (make-servlet-exception-handler inst)
|
(define (make-servlet-exception-handler inst)
|
||||||
|
@ -61,27 +63,29 @@
|
||||||
(p ,(exn-message the-exn))))
|
(p ,(exn-message the-exn))))
|
||||||
(request-method req))
|
(request-method req))
|
||||||
((execution-context-suspend ctxt)))))
|
((execution-context-suspend ctxt)))))
|
||||||
|
|
||||||
;; resume-servlet: connection request continuation-reference hash-table -> void
|
;; resume-servlet: connection request continuation-reference hash-table -> void
|
||||||
;; pull the continuation out of the table and apply it
|
;; pull the continuation out of the table and apply it
|
||||||
(define (resume-servlet conn req k-ref instance-table)
|
(define (resume-servlet conn req k-ref instance-table)
|
||||||
(let* ([inst (hash-table-get instance-table (car k-ref)
|
(define inst (hash-table-get instance-table (car k-ref)
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(raise
|
(raise
|
||||||
(make-exn:servlet:instance
|
(make-exn:servlet:instance
|
||||||
"" (current-continuation-marks)))))]
|
"" (current-continuation-marks))))))
|
||||||
[k-table
|
(define k-table
|
||||||
(servlet-instance-k-table inst)])
|
(servlet-instance-k-table inst))
|
||||||
|
(define response
|
||||||
(let/cc suspend
|
(let/cc suspend
|
||||||
(set-servlet-instance-context!
|
(set-servlet-instance-context!
|
||||||
inst
|
inst
|
||||||
(make-execution-context
|
(make-execution-context
|
||||||
conn req (lambda () (suspend #t))))
|
conn req suspend))
|
||||||
(semaphore-wait (servlet-instance-mutex inst))
|
(semaphore-wait (servlet-instance-mutex inst))
|
||||||
((hash-table-get k-table (cadr k-ref)
|
((hash-table-get k-table (cadr k-ref)
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(raise
|
(raise
|
||||||
(make-exn:servlet:continuation
|
(make-exn:servlet:continuation
|
||||||
"" (current-continuation-marks)))))
|
"" (current-continuation-marks)))))
|
||||||
req))
|
req)))
|
||||||
(semaphore-post (servlet-instance-mutex inst)))))
|
(output-response conn response)
|
||||||
|
(semaphore-post (servlet-instance-mutex inst))))
|
Loading…
Reference in New Issue
Block a user