2
; Copyright (C) 2014 Kookamara LLC
7
; 11410 Windermere Meadows
8
; Austin, TX 78759, USA
9
; http://www.kookamara.com/
11
; License: (An MIT/X11-style license)
13
; Permission is hereby granted, free of charge, to any person obtaining a
14
; copy of this software and associated documentation files (the "Software"),
15
; to deal in the Software without restriction, including without limitation
16
; the rights to use, copy, modify, merge, publish, distribute, sublicense,
17
; and/or sell copies of the Software, and to permit persons to whom the
18
; Software is furnished to do so, subject to the following conditions:
20
; The above copyright notice and this permission notice shall be included in
21
; all copies or substantial portions of the Software.
23
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28
; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29
; DEALINGS IN THE SOFTWARE.
31
; Original author: Jared Davis <jared@kookamara.com>
33
(in-package "SIDEKICK")
36
(acl2::mf-multiprocessing t)
40
(defun maybe-launch-browser (host port)
41
(b* ((state acl2::*the-live-state*)
42
((mv ? browser state) (getenv$ "SIDEKICK_BROWSER" state))
43
((unless (and (stringp browser)
44
(not (equal browser ""))))
47
(acl2::tshell-run-background
48
(str::cat browser " http://" host ":" (str::natstr port) "/"))))
50
(defun start-fn (port)
54
(b* ((state acl2::*the-live-state*)
55
((mv ? port state) (getenv$ "SIDEKICK_PORT" state))
56
(port-num (str::strval port))
59
;; Special hack for Centaur: fall back to FVQ_PORT if
61
((mv ? port state) (getenv$ "FVQ_PORT" state))
62
(port-num (str::strval port))
65
;; Else, just use the default port
68
;; For complicated cluster setups, you might want to fudge the host in
69
;; the usage message and in maybe-launch-browser.
70
(host (b* (((mv ? host state) (getenv$ "SIDEKICK_HOST" state))
71
((when (and (stringp host)
72
(not (equal host ""))))
76
;; Note: apparently this has to include the trailing slash!
77
(str::cat *sidekick-dir* "/public/"))
78
(server (make-instance 'hunchentoot:easy-acceptor
80
:document-root root)))
81
(setf (hunchentoot:acceptor-access-log-destination server)
82
(str::cat *sidekick-dir* "/access.out"))
83
(hunchentoot:start server)
84
(format t "; ----------------------------------------------------------------~%")
86
(format t "; Sidekick started, see http://~a:~D/~%" host port)
88
(format t "; ----------------------------------------------------------------~%~%")
90
(setq *server* server)
91
(maybe-launch-browser host port))
96
(hunchentoot:stop *server*)
101
; We go to some trouble to cache PBT results so that the client can poll it
102
; frequently. We could do more to cache other results like PBT and PCB
103
; results, but this seems pretty workable so far.
105
(defvar *pbt-cached-world* nil)
106
(defvar *pbt-cached-result* nil)
108
; Optimizations so that when new threads create hons spaces, these spaces are
110
(setq acl2::*hl-hspace-str-ht-default-size* 100)
111
(setq acl2::*hl-ctables-nil-ht-default-size* 100)
112
(setq acl2::*hl-ctables-cdr-ht-default-size* 100)
113
(setq acl2::*hl-ctables-cdr-ht-eql-default-size* 100)
114
(setq acl2::*hl-hspace-addr-ht-default-size* 100)
115
(setq acl2::*hl-hspace-sbits-default-size* 100)
116
(setq acl2::*hl-hspace-other-ht-default-size* 100)
117
(setq acl2::*hl-hspace-fal-ht-default-size* 100)
118
(setq acl2::*hl-hspace-persist-ht-default-size* 100)
120
(defmacro with-sidekick-bindings (&rest forms)
122
;; Bind state since we often need that.
123
acl2::*the-live-state*)
125
;; Give this thread its own hons space. Hopefully it won't use it
128
(acl2::*read-string-should-check-bad-lisp-object*
129
;; Turn this off because otherwise we run into hash table ownership
130
;; problems, because bad-lisp-objectp is memoized and memoization
131
;; isn't thread-safe.
135
(defun add-handlers ()
137
(hunchentoot:define-easy-handler (pbt-handler :uri "/pbt") ()
138
(setf (hunchentoot:content-type*) "application/json")
139
(b* ((state acl2::*the-live-state*)
141
((when (and *pbt-cached-result* (eq world *pbt-cached-world*)))
143
((mv er val ?state) (json-pbt 0))
144
(ans (bridge::json-encode
145
(list (cons :error er)
147
(setq *pbt-cached-world* world)
148
(setq *pbt-cached-result* ans)
150
(list (cons :error er)
154
(hunchentoot:define-easy-handler (pbtx-handler :uri "/pbtx") ()
155
(setf (hunchentoot:content-type*) "application/json")
156
(b* ((state acl2::*the-live-state*)
158
((mv er val ?state) (json-pbt :x)))
160
(list (cons :error er)
163
(hunchentoot:define-easy-handler (pcb-handler :uri "/pcb") (num full)
164
(setf (hunchentoot:content-type*) "application/json")
165
(b* ((num (or (str::strval num)
166
(and (equal num ":X") :x)
167
(and (equal num ":x") :x)
169
(state acl2::*the-live-state*)
170
(fullp (equal full "1"))
171
((mv er val ?state) (json-pcb! num fullp)))
173
(list (cons :error er)
176
(hunchentoot:define-easy-handler (package-handler :uri "/package") ()
177
(setf (hunchentoot:content-type*) "application/json")
178
(b* ((state acl2::*the-live-state*)
179
(pkg (acl2::current-package state)))
181
(list (cons :package pkg)))))
183
(hunchentoot:define-easy-handler (pc-handler :uri "/pc") (num)
184
(setf (hunchentoot:content-type*) "application/json")
185
(b* ((num (or (str::strval num)
186
(and (equal num ":X") :x)
187
(and (equal num ":x") :x)
189
(state acl2::*the-live-state*)
190
((mv er val ?state) (json-pc num)))
192
(list (cons :error er)
195
(hunchentoot:define-easy-handler (disassemble-handler :uri "/disassemble") (name)
196
(setf (hunchentoot:content-type*) "application/json")
197
(with-sidekick-bindings
198
(b* (((mv ans state) (sk-get-disassembly name state)))
201
(hunchentoot:define-easy-handler (lint-handler :uri "/lint") ()
202
(setf (hunchentoot:content-type*) "application/json")
203
(b* (((mv ans state) (json-lint state)))
206
(hunchentoot:define-easy-handler (props-handler :uri "/props") (name)
207
(setf (hunchentoot:content-type*) "application/json")
208
(with-sidekick-bindings
209
(b* (((mv ans state) (sk-get-props name state)))
212
(hunchentoot:define-easy-handler (origin-handler :uri "/origin") (name)
213
(setf (hunchentoot:content-type*) "application/json")
214
(with-sidekick-bindings
215
(b* (((mv ans state) (sk-get-origin name state)))
218
(hunchentoot:define-easy-handler (xdoc-handler :uri "/xdoc") (name)
219
(setf (hunchentoot:content-type*) "application/json")
220
(with-sidekick-bindings
221
(b* (((mv ans state) (sk-get-xdoc name state)))
224
(hunchentoot:define-easy-handler (webcommand-handler :uri "/webcommands") ()
225
(setf (hunchentoot:content-type*) "application/json")
226
(b* ((commands (get-webcommands-stack)))
228
(list (cons :commands commands)))))
230
(hunchentoot:define-easy-handler (eventdata-handler :uri "/eventdata") (name)
231
(setf (hunchentoot:content-type*) "application/json")
232
(with-sidekick-bindings
233
(b* (((mv ans state) (sk-get-eventdata name state)))
236
(hunchentoot:define-easy-handler (ubt-handler :uri "/ubt" :default-request-type :post)
237
((n :parameter-type 'string))
238
(setf (hunchentoot:content-type*) "application/json")
239
(with-sidekick-bindings
240
(b* (((mv ans state) (sk-undo-back-through n state)))
245
(hunchentoot:define-easy-handler (handle-explore-th :uri "/explore-th") ()
246
(setf (hunchentoot:content-type*) "application/json")
247
(with-sidekick-bindings
248
(b* (((mv ans state) (sk-explore-th state)))
251
(hunchentoot:define-easy-handler (handle-explore-commands :uri "/explore-commands") ()
252
(setf (hunchentoot:content-type*) "application/json")
253
(with-sidekick-bindings
254
(b* (((mv ans state) (sk-explore-commands state)))
257
(hunchentoot:define-easy-handler (explore-undo-handler :uri "/explore-undo" :default-request-type :post)
258
((n :parameter-type 'string))
259
(setf (hunchentoot:content-type*) "application/json")
260
(with-sidekick-bindings
261
(b* (((mv ans state) (sk-explore-undo n state)))
264
(hunchentoot:define-easy-handler (explore-contrapose-handler :uri "/explore-contrapose" :default-request-type :post)
265
((n :parameter-type 'string))
266
(setf (hunchentoot:content-type*) "application/json")
267
(with-sidekick-bindings
268
(b* (((mv ans state) (sk-explore-contrapose n state)))
271
(hunchentoot:define-easy-handler (explore-demote-handler :uri "/explore-demote" :default-request-type :post)
272
((n :parameter-type 'string))
273
(setf (hunchentoot:content-type*) "application/json")
274
(with-sidekick-bindings
275
(b* (((mv ans state) (sk-explore-demote n state)))
278
(hunchentoot:define-easy-handler (explore-drop-handler :uri "/explore-drop" :default-request-type :post)
279
((n :parameter-type 'string))
280
(setf (hunchentoot:content-type*) "application/json")
281
(with-sidekick-bindings
282
(b* (((mv ans state) (sk-explore-drop n state)))
285
(hunchentoot:define-easy-handler (explore-split-handler :uri "/explore-split" :default-request-type :post)
287
(setf (hunchentoot:content-type*) "application/json")
288
(with-sidekick-bindings
289
(b* (((mv ans state) (sk-explore-split state)))
292
(hunchentoot:define-easy-handler (explore-pro-handler :uri "/explore-pro" :default-request-type :post)
294
(setf (hunchentoot:content-type*) "application/json")
295
(with-sidekick-bindings
296
(b* (((mv ans state) (sk-explore-pro state)))