mas01cr@511
|
1 (in-package "SB-ADB")
|
mas01cr@511
|
2
|
mas01cr@511
|
3 (defclass adb ()
|
mas01cr@511
|
4 ((alien :initarg alien)))
|
mas01cr@511
|
5 (defmethod initialize-instance :after ((o adb) &key)
|
mas01cr@511
|
6 (when (and (slot-boundp o 'alien)
|
mas01cr@511
|
7 (not (null-alien (slot-value o 'alien))))
|
mas01cr@511
|
8 (let ((alien (slot-value o 'alien)))
|
mas01cr@511
|
9 (sb-ext:finalize o (lambda () (%close alien))))))
|
mas01cr@511
|
10
|
mas01cr@511
|
11 ;;; FIXME: deal with interrupt-safety / leak issues
|
mas01cr@511
|
12
|
mas01cr@511
|
13 ;;; FIXME: if-does-not-exist.
|
mas01cr@511
|
14 (defun open (path &key (direction :input) (if-exists :error) (adb-class 'adb))
|
mas01cr@511
|
15 (flet ((direction-flag (direction)
|
mas01cr@511
|
16 (ecase direction
|
mas01cr@511
|
17 ((:input :probe) sb-posix:o-rdonly)
|
mas01cr@511
|
18 ((:output :io) sb-posix:o-rdwr))))
|
mas01cr@511
|
19 (let* ((truepath (probe-file path))
|
mas01cr@511
|
20 (alien (cond
|
mas01cr@511
|
21 (truepath
|
mas01cr@511
|
22 (ecase direction
|
mas01cr@511
|
23 ((:input :probe)
|
mas01cr@511
|
24 (%%open path (direction-flag direction)))
|
mas01cr@511
|
25 ((:output :io)
|
mas01cr@511
|
26 (case if-exists
|
mas01cr@511
|
27 (:error (error "database already exists: ~S" path))
|
mas01cr@511
|
28 (:append (%open path (direction-flag direction)))
|
mas01cr@511
|
29 ;; FIXME: not the best implementation of
|
mas01cr@511
|
30 ;; :SUPERSEDE semantics ever.
|
mas01cr@511
|
31 (:supersede (delete-file path) (%create path 0 0 0))))))
|
mas01cr@511
|
32 ((eql direction :input)
|
mas01cr@511
|
33 (error "database does not exist: ~S" path))
|
mas01cr@511
|
34 (t (%create path 0 0 0)))))
|
mas01cr@511
|
35 (cond
|
mas01cr@511
|
36 ((null-alien alien)
|
mas01cr@511
|
37 (case direction
|
mas01cr@511
|
38 (:probe nil)
|
mas01cr@511
|
39 (t (error "opening database failed: ~S" path))))
|
mas01cr@511
|
40 (t (make-instance adb-class 'alien alien))))))
|
mas01cr@511
|
41 (defmethod close ((o adb))
|
mas01cr@511
|
42 (when (and (slot-boundp o 'alien)
|
mas01cr@511
|
43 (not (null-alien (slot-value o 'alien))))
|
mas01cr@511
|
44 (%close (slot-value o 'alien))
|
mas01cr@511
|
45 (sb-ext:cancel-finalization o)
|
mas01cr@511
|
46 (slot-makunbound o 'alien)))
|
mas01cr@511
|
47 (defmacro with-adb ((adb path &rest open-args &key direction adb-class if-exists)
|
mas01cr@511
|
48 &body body)
|
mas01cr@511
|
49 (declare (ignore direction adb-class if-exists))
|
mas01cr@511
|
50 `(let ((,adb (open ,path ,@open-args)))
|
mas01cr@511
|
51 (unwind-protect
|
mas01cr@511
|
52 (locally ,@body)
|
mas01cr@511
|
53 (close ,adb))))
|
mas01cr@511
|
54
|
mas01cr@511
|
55 (defgeneric l2norm (db))
|
mas01cr@511
|
56 (defmethod l2norm ((db adb))
|
mas01cr@511
|
57 (%l2norm (slot-value db 'alien)))
|
mas01cr@511
|
58
|
mas01cr@511
|
59 (defstruct (datum
|
mas01cr@511
|
60 (:constructor %make-datum)
|
mas01cr@511
|
61 (:constructor
|
mas01cr@511
|
62 make-datum
|
mas01cr@511
|
63 (key %data &key times power
|
mas01cr@511
|
64 &aux (data
|
mas01cr@511
|
65 (make-array (list (length %data) (length (elt %data 0)))
|
mas01cr@511
|
66 :element-type 'double-float
|
mas01cr@511
|
67 :initial-contents %data)))))
|
mas01cr@511
|
68 (key (error "missing argument") :type string)
|
mas01cr@511
|
69 (data (error "missing argument") :type (simple-array double-float (* *)))
|
mas01cr@511
|
70 (times nil :type (or null (simple-array double-float)))
|
mas01cr@511
|
71 (power nil :type (or null (simple-array double-float))))
|
mas01cr@511
|
72
|
mas01cr@511
|
73 (defgeneric insert (datum db))
|
mas01cr@511
|
74
|
mas01cr@511
|
75 (defmethod insert ((datum datum) (db adb))
|
mas01cr@511
|
76 (let* ((data (datum-data datum))
|
mas01cr@511
|
77 (nvectors (array-dimension data 0))
|
mas01cr@511
|
78 (dim (array-dimension data 1)))
|
mas01cr@511
|
79 (when (datum-times datum)
|
mas01cr@511
|
80 (unless (= (array-total-size (datum-times datum)) (* 2 nvectors))
|
mas01cr@511
|
81 (error "dimension mismatch for times: ~S" datum)))
|
mas01cr@511
|
82 (when (datum-power datum)
|
mas01cr@511
|
83 (unless (= (array-total-size (datum-power datum)) nvectors)
|
mas01cr@511
|
84 (error "dimension mismatch for power: ~S" datum)))
|
mas01cr@511
|
85 (with-alien ((d adb-datum-t))
|
mas01cr@511
|
86 (sb-sys:with-pinned-objects ((datum-data datum)
|
mas01cr@511
|
87 (datum-times datum)
|
mas01cr@511
|
88 (datum-power datum))
|
mas01cr@511
|
89 (setf (slot d 'dim) dim)
|
mas01cr@511
|
90 (setf (slot d 'nvectors) nvectors)
|
mas01cr@511
|
91 (setf (slot d 'key) (datum-key datum))
|
mas01cr@511
|
92 (setf (slot d 'data)
|
mas01cr@511
|
93 (sb-sys:vector-sap (sb-ext:array-storage-vector (datum-data datum))))
|
mas01cr@511
|
94 (if (datum-times datum)
|
mas01cr@511
|
95 (setf (slot d 'times) (sb-sys:vector-sap (sb-ext:array-storage-vector (datum-times datum))))
|
mas01cr@511
|
96 (setf (slot d 'times) nil))
|
mas01cr@511
|
97 (if (datum-power datum)
|
mas01cr@635
|
98 (setf (slot d 'power) (sb-sys:vector-sap (sb-ext:array-storage-vector (datum-power datum))))
|
mas01cr@511
|
99 (setf (slot d 'power) nil))
|
mas01cr@511
|
100 (sb-int:with-float-traps-masked (:invalid)
|
mas01cr@511
|
101 (%insert-datum (slot-value db 'alien) (addr d)))))))
|
mas01cr@580
|
102
|
mas01cr@580
|
103 (defgeneric retrieve (key db))
|
mas01cr@580
|
104
|
mas01cr@580
|
105 (defmethod retrieve ((key string) (db adb))
|
mas01cr@580
|
106 ;; KLUDGE: this does multiple copies of the floating point data:
|
mas01cr@580
|
107 ;; once within audiodb_retrieve_datum(), and once from the alien to
|
mas01cr@580
|
108 ;; the lisp arrays. Oh well.
|
mas01cr@580
|
109 (with-alien ((d adb-datum-t))
|
mas01cr@580
|
110 (setf (slot d 'times) nil
|
mas01cr@580
|
111 (slot d 'power) nil)
|
mas01cr@580
|
112 (%retrieve-datum (slot-value db 'alien) key (addr d))
|
mas01cr@580
|
113 (let* ((dim (slot d 'dim))
|
mas01cr@580
|
114 (nvectors (slot d 'nvectors))
|
mas01cr@580
|
115 (data (make-array (list nvectors dim) :element-type 'double-float))
|
mas01cr@580
|
116 (vector (sb-ext:array-storage-vector data))
|
mas01cr@580
|
117 ;; FIXME: this shares KEY
|
mas01cr@580
|
118 (datum (%make-datum :key key :data data)))
|
mas01cr@636
|
119 (flet ((system-area-dfloat-copy (from-sap from-offset to-sap to-offset ndfloats)
|
mas01cr@636
|
120 ;; FIXME: the horror
|
mas01cr@636
|
121 #+#.(cl:if (cl:= sb-vm:n-word-bits 64) '(:and) '(:or))
|
mas01cr@636
|
122 (sb-kernel:system-area-ub64-copy
|
mas01cr@636
|
123 from-sap from-offset to-sap to-offset ndfloats)
|
mas01cr@636
|
124 #-#.(cl:if (cl:= sb-vm:n-word-bits 64) '(:and) '(:or))
|
mas01cr@636
|
125 (sb-kernel:system-area-ub32-copy
|
mas01cr@636
|
126 from-sap from-offset to-sap to-offset (* 2 ndfloats))))
|
mas01cr@636
|
127 (system-area-dfloat-copy (alien-sap (slot d 'data)) 0
|
mas01cr@636
|
128 (sb-sys:vector-sap vector) 0
|
mas01cr@636
|
129 (* dim nvectors))
|
mas01cr@636
|
130 (unless (null-alien (slot d 'times))
|
mas01cr@636
|
131 (let ((times (make-array (* 2 nvectors) :element-type 'double-float)))
|
mas01cr@636
|
132 (system-area-dfloat-copy (alien-sap (slot d 'times)) 0
|
mas01cr@636
|
133 (sb-sys:vector-sap times) 0
|
mas01cr@636
|
134 (* 2 nvectors))
|
mas01cr@636
|
135 (setf (datum-times datum) times)))
|
mas01cr@636
|
136 (unless (null-alien (slot d 'power))
|
mas01cr@636
|
137 (let ((power (make-array nvectors :element-type 'double-float)))
|
mas01cr@636
|
138 (system-area-dfloat-copy (alien-sap (slot d 'power)) 0
|
mas01cr@636
|
139 (sb-sys:vector-sap power) 0
|
mas01cr@636
|
140 nvectors)
|
mas01cr@636
|
141 (setf (datum-power datum) power)))
|
mas01cr@636
|
142 (%free-datum (slot-value db 'alien) (addr d))
|
mas01cr@636
|
143 datum))))
|
mas01cr@511
|
144
|
mas01cr@511
|
145 (defstruct result
|
mas01cr@511
|
146 (key "" :type string)
|
mas01cr@511
|
147 (distance 0d0 :type double-float)
|
mas01cr@511
|
148 (qpos 0 :type (and unsigned-byte fixnum))
|
mas01cr@511
|
149 (ipos 0 :type (and unsigned-byte fixnum)))
|
mas01cr@511
|
150
|
mas01cr@511
|
151 ;;; Hrm. To copy (from the malloc heap) or not to copy? Copying
|
mas01cr@511
|
152 ;;; would make things generally easier, I guess, and we have to hope
|
mas01cr@511
|
153 ;;; that the order of magnitude is not such that the copying causes
|
mas01cr@511
|
154 ;;; pain.
|
mas01cr@511
|
155 (defclass results (sequence standard-object)
|
mas01cr@511
|
156 ())
|
mas01cr@511
|
157 (defclass copied-query-results (results)
|
mas01cr@511
|
158 ((results :initarg results :accessor %copied-results)))
|
mas01cr@511
|
159 (defmethod print-object ((o copied-query-results) s)
|
mas01cr@511
|
160 (pprint-logical-block (s nil)
|
mas01cr@511
|
161 (print-unreadable-object (o s :type t)
|
mas01cr@511
|
162 (format s "(~D results):~2I~@:_" (length o))
|
mas01cr@511
|
163 (sequence:dosequence (r o)
|
mas01cr@511
|
164 (pprint-pop)
|
mas01cr@511
|
165 (format s "~A ~6,3e ~D ~D~@:_"
|
mas01cr@511
|
166 (result-key r) (result-distance r)
|
mas01cr@511
|
167 (result-qpos r) (result-ipos r))))))
|
mas01cr@511
|
168
|
mas01cr@511
|
169 (defmethod sequence:length ((o copied-query-results))
|
mas01cr@511
|
170 (length (%copied-results o)))
|
mas01cr@511
|
171 (defmethod sequence:elt ((o copied-query-results) index)
|
mas01cr@511
|
172 (elt (%copied-results o) index))
|
mas01cr@511
|
173 (defmethod (setf sequence:elt) (new-value (o copied-query-results) index)
|
mas01cr@511
|
174 (setf (elt (%copied-results o) index) new-value))
|
mas01cr@511
|
175 (defmethod sequence:make-sequence-like
|
mas01cr@511
|
176 ((o copied-query-results) length &rest args
|
mas01cr@511
|
177 &key initial-element initial-contents)
|
mas01cr@511
|
178 (declare (ignore initial-element initial-contents))
|
mas01cr@511
|
179 (let ((vector (apply #'make-array length args)))
|
mas01cr@511
|
180 (make-instance 'copied-query-results 'results vector)))
|
mas01cr@511
|
181 (defmethod sequence:adjust-sequence
|
mas01cr@511
|
182 ((o copied-query-results) length &rest args
|
mas01cr@511
|
183 &key initial-element initial-contents)
|
mas01cr@511
|
184 (declare (ignore initial-element initial-contents))
|
mas01cr@511
|
185 (let ((results (%copied-results o)))
|
mas01cr@511
|
186 (apply #'sequence:adjust-sequence results length args))
|
mas01cr@511
|
187 o)
|
mas01cr@511
|
188
|
mas01cr@511
|
189 (defclass proxied-query-results (results)
|
mas01cr@511
|
190 ((adb :initarg adb)
|
mas01cr@511
|
191 (spec :initarg spec)
|
mas01cr@511
|
192 (results :initarg results)))
|
mas01cr@511
|
193 (defmethod initialize-instance :after ((o proxied-query-results) &key)
|
mas01cr@511
|
194 (when (and (slot-boundp o 'results)
|
mas01cr@511
|
195 (not (null-alien o))
|
mas01cr@511
|
196 (slot-boundp o 'spec))
|
mas01cr@511
|
197 (with-slots (results spec adb) o
|
mas01cr@511
|
198 (flet ((results-finalizer ()
|
mas01cr@511
|
199 (with-slots (alien) adb
|
mas01cr@511
|
200 (%free-query-results alien spec results))))
|
mas01cr@511
|
201 (sb-ext:finalize o #'results-finalizer)))))
|
mas01cr@511
|
202
|
mas01cr@511
|
203 (defgeneric query (datum db &key))
|
mas01cr@511
|
204
|
mas01cr@511
|
205 ;;; FIXME: I don't like this way of generalizing the boilerplate;
|
mas01cr@511
|
206 ;;; isn't there a nice functional way of doing this?
|
mas01cr@511
|
207 (macrolet
|
mas01cr@511
|
208 ((def (name datum-class &body qdatum-forms)
|
mas01cr@511
|
209 `(defmethod ,name ((datum ,datum-class) (db adb) &key
|
mas01cr@511
|
210 (sequence-length 1) (sequence-start 0)
|
mas01cr@511
|
211 exhaustivep accumulation distance
|
mas01cr@511
|
212 ;; FIXME: dubious historical defaults
|
mas01cr@511
|
213 (npoints 10) (ntracks 10)
|
mas01cr@511
|
214
|
mas01cr@511
|
215 (radius nil radiusp)
|
mas01cr@511
|
216 (include-keys nil include-keys-p)
|
mas01cr@511
|
217 (exclude-keys nil exclude-keys-p))
|
mas01cr@511
|
218 (unless (slot-boundp db 'alien)
|
mas01cr@511
|
219 (error "database ~S is closed" db))
|
mas01cr@511
|
220 (with-alien ((qid adb-query-id-t)
|
mas01cr@511
|
221 (qparams adb-query-parameters-t)
|
mas01cr@511
|
222 (qrefine adb-query-refine-t)
|
mas01cr@511
|
223 (qdatum adb-datum-t))
|
mas01cr@511
|
224 ,@qdatum-forms
|
mas01cr@511
|
225 (setf (slot qid 'datum) (addr qdatum))
|
mas01cr@511
|
226 (setf (slot qid 'sequence-length) sequence-length)
|
mas01cr@511
|
227 (setf (slot qid 'sequence-start) sequence-start)
|
mas01cr@511
|
228 (setf (slot qid 'flags) (if exhaustivep 1 0))
|
mas01cr@511
|
229
|
mas01cr@511
|
230 (setf (slot qparams 'accumulation)
|
mas01cr@511
|
231 (ecase accumulation
|
mas01cr@511
|
232 (:db 1)
|
mas01cr@511
|
233 (:per-track 2)
|
mas01cr@511
|
234 (:one-to-one 3)))
|
mas01cr@511
|
235 (setf (slot qparams 'distance)
|
mas01cr@511
|
236 (ecase distance
|
mas01cr@511
|
237 (:dot-product 1)
|
mas01cr@511
|
238 (:euclidean-normed 2)
|
mas01cr@511
|
239 (:euclidean 3)))
|
mas01cr@511
|
240 (setf (slot qparams 'npoints) (or npoints 0))
|
mas01cr@511
|
241 (setf (slot qparams 'ntracks) (or ntracks 0))
|
mas01cr@511
|
242
|
mas01cr@511
|
243 (let ((refine-flags 0))
|
mas01cr@511
|
244 (when radiusp
|
mas01cr@511
|
245 (setf refine-flags (logior refine-flags 4))
|
mas01cr@511
|
246 (setf (slot qrefine 'radius) (float radius 0d0)))
|
mas01cr@511
|
247 ;; FIXME: the freeing of the KEYS slot in these
|
mas01cr@511
|
248 ;; include/exclude keylists isn't interrupt-safe.
|
mas01cr@511
|
249 ;;
|
mas01cr@511
|
250 ;; FIXME: think quite hard about the behaviour of this
|
mas01cr@511
|
251 ;; when LENGTH is 0.
|
mas01cr@511
|
252 (when include-keys-p
|
mas01cr@511
|
253 (setf refine-flags (logior refine-flags 1))
|
mas01cr@511
|
254 (let ((length (length include-keys)))
|
mas01cr@511
|
255 (setf (slot (slot qrefine 'include) 'nkeys) length)
|
mas01cr@511
|
256 (let ((keys (make-alien c-string length)))
|
mas01cr@511
|
257 (setf (slot (slot qrefine 'include) 'keys) keys)
|
mas01cr@511
|
258 (loop for key being the elements of include-keys
|
mas01cr@511
|
259 for i upfrom 0
|
mas01cr@511
|
260 do (setf (deref keys i) key)))))
|
mas01cr@511
|
261 (when exclude-keys-p
|
mas01cr@511
|
262 (setf refine-flags (logior refine-flags 2))
|
mas01cr@511
|
263 (let ((length (length exclude-keys)))
|
mas01cr@511
|
264 (setf (slot (slot qrefine 'exclude) 'nkeys) length)
|
mas01cr@511
|
265 (let ((keys (make-alien c-string length)))
|
mas01cr@511
|
266 (setf (slot (slot qrefine 'exclude) 'keys) keys)
|
mas01cr@511
|
267 (loop for key being the elements of exclude-keys
|
mas01cr@511
|
268 for i upfrom 0
|
mas01cr@511
|
269 do (setf (deref keys i) key)))))
|
mas01cr@511
|
270 (setf (slot qrefine 'flags) refine-flags))
|
mas01cr@511
|
271 (setf (slot qrefine 'hopsize) 1)
|
mas01cr@511
|
272
|
mas01cr@511
|
273 ;; FIXME: hm, this possibly suggests that there's something
|
mas01cr@511
|
274 ;; a bit wrong with the C audioDB interface. The API
|
mas01cr@511
|
275 ;; currently exposed effectively requires either that all
|
mas01cr@511
|
276 ;; the processing of query results happens in the same
|
mas01cr@511
|
277 ;; dynamic extent as the call to audiodb_query_spec(), or
|
mas01cr@511
|
278 ;; that the adb_query_spec_t object is allocated on the
|
mas01cr@511
|
279 ;; heap. We need to think harder about whether the spec
|
mas01cr@511
|
280 ;; argument is really required (I think it probably isn't).
|
mas01cr@511
|
281 ;;
|
mas01cr@511
|
282 ;; meanwhile, here we're using it with dynamic extent anyway, so
|
mas01cr@511
|
283 ;; we could put it right back on the stack.
|
mas01cr@511
|
284 (let ((qspec (make-alien adb-query-spec-t)))
|
mas01cr@511
|
285 (unwind-protect
|
mas01cr@511
|
286 (progn
|
mas01cr@511
|
287 (setf (slot qspec 'qid) qid)
|
mas01cr@511
|
288 (setf (slot qspec 'params) qparams)
|
mas01cr@511
|
289 (setf (slot qspec 'refine) qrefine)
|
mas01cr@511
|
290
|
mas01cr@511
|
291 (let ((results
|
mas01cr@511
|
292 (sb-int:with-float-traps-masked (:invalid)
|
mas01cr@511
|
293 (%query (slot-value db 'alien) qspec))))
|
mas01cr@511
|
294 (flet ((collect-copied-results ()
|
mas01cr@511
|
295 (let ((nresults (slot results 'nresults))
|
mas01cr@511
|
296 (cresults (slot results 'results)))
|
mas01cr@511
|
297 (coerce
|
mas01cr@511
|
298 (loop for i below nresults
|
mas01cr@511
|
299 for r = (deref cresults i)
|
mas01cr@511
|
300 collect (make-result
|
mas01cr@511
|
301 :key (slot r 'key)
|
mas01cr@511
|
302 :distance (slot r 'dist)
|
mas01cr@511
|
303 :qpos (slot r 'qpos)
|
mas01cr@511
|
304 :ipos (slot r 'ipos)))
|
mas01cr@511
|
305 'vector))))
|
mas01cr@511
|
306 (unwind-protect
|
mas01cr@511
|
307 (make-instance 'copied-query-results
|
mas01cr@511
|
308 'results (collect-copied-results))
|
mas01cr@511
|
309 (%free-query-results (slot-value db 'alien) qspec results)))))
|
mas01cr@511
|
310 (when (logbitp 0 (slot (slot qspec 'refine) 'flags))
|
mas01cr@511
|
311 (free-alien (slot (slot (slot qspec 'refine) 'include) 'keys)))
|
mas01cr@511
|
312 (when (logbitp 1 (slot (slot qspec 'refine) 'flags))
|
mas01cr@511
|
313 (free-alien (slot (slot (slot qspec 'refine) 'exclude) 'keys)))
|
mas01cr@511
|
314 (free-alien qspec)))))))
|
mas01cr@511
|
315 (def query string (setf (slot qdatum 'key) datum))
|
mas01cr@511
|
316 (def query datum
|
mas01cr@511
|
317 (setf (slot qdatum 'key) (datum-key datum))
|
mas01cr@511
|
318 (setf (slot qdatum 'dim) (array-dimension (datum-data datum) 1))
|
mas01cr@511
|
319 (setf (slot qdatum 'nvectors) (array-dimension (datum-data datum) 0))
|
mas01cr@511
|
320 (setf (slot qdatum 'data) (sb-sys:vector-sap (sb-ext:array-storage-vector (datum-data datum))))
|
mas01cr@511
|
321 (if (datum-times datum)
|
mas01cr@511
|
322 (setf (slot qdatum 'times) (sb-sys:vector-sap (sb-ext:array-storage-vector (datum-times datum))))
|
mas01cr@511
|
323 (setf (slot qdatum 'times) nil))
|
mas01cr@511
|
324 (if (datum-power datum)
|
mas01cr@511
|
325 (setf (slot qdatum 'power) (sb-sys:vector-sap (sb-ext:array-storage-vector (datum-times datum))))
|
mas01cr@511
|
326 (setf (slot qdatum 'power) nil))))
|
mas01cr@511
|
327
|
mas01cr@511
|
328 #+test
|
mas01cr@511
|
329 (sb-adb:with-adb (db "/home/csr21/tmp/omras2-workshop/9.adb")
|
mas01cr@511
|
330 (sb-adb:query "KSA_CHARM_337" db :exhaustivep t :sequence-length 30
|
mas01cr@511
|
331 :accumulation :per-track :distance :euclidean :npoints 1 :ntracks 20))
|
mas01cr@511
|
332
|
mas01cr@511
|
333 #+test
|
mas01cr@511
|
334 (sb-adb:with-adb (db "/home/csr21/tmp/omras2-workshop/9.adb")
|
mas01cr@511
|
335 (sb-adb:query "KSA_CHARM_337" db :sequence-start 20 :sequence-length 20
|
mas01cr@511
|
336 :accumulation :per-track :distance :euclidean-normed
|
mas01cr@511
|
337 :npoints 10 :ntracks 1))
|
mas01cr@511
|
338
|
mas01cr@511
|
339 #+test
|
mas01cr@511
|
340 (sb-adb:with-adb (db "/home/csr21/tmp/omras2-workshop/9.adb")
|
mas01cr@511
|
341 (sb-adb:query "KSA_CHARM_337" db
|
mas01cr@511
|
342 :exhaustivep t :sequence-length 30
|
mas01cr@511
|
343 :accumulation :per-track :distance :euclidean-normed
|
mas01cr@511
|
344 :npoints 2 :ntracks 10))
|
mas01cr@511
|
345
|
mas01cr@511
|
346 ;;; only hacks and tests below
|
mas01cr@511
|
347 #|
|
mas01cr@511
|
348 (defun foo ()
|
mas01cr@511
|
349 (let ((db (%open "/home/csr21/tmp/omras2-workshop/9.adb" sb-posix:o-rdonly)))
|
mas01cr@511
|
350 (unless (null-alien db)
|
mas01cr@511
|
351 (unwind-protect
|
mas01cr@511
|
352 (with-alien ((status adb-status-t))
|
mas01cr@511
|
353 (%status db (addr status))
|
mas01cr@511
|
354 (print (list (slot status 'dim) (slot status 'nfiles))))
|
mas01cr@511
|
355 (%close db)))))
|
mas01cr@511
|
356
|
mas01cr@511
|
357 (defun set-up-spec (spec qid qparams qrefine)
|
mas01cr@511
|
358 (declare (type (alien adb-query-parameters-t) qparams)
|
mas01cr@511
|
359 (type (alien adb-query-refine-t) qrefine)
|
mas01cr@511
|
360 (type (alien adb-query-id-t) qid)
|
mas01cr@511
|
361 (type (alien adb-query-spec-t) spec))
|
mas01cr@511
|
362 (setf (slot spec 'refine) qrefine)
|
mas01cr@511
|
363 nil)
|
mas01cr@511
|
364
|
mas01cr@511
|
365 (defun bar ()
|
mas01cr@511
|
366 (let ((db (%open "/home/csr21/tmp/omras2-workshop/9.adb" sb-posix:o-rdonly)))
|
mas01cr@511
|
367 (unless (null-alien db)
|
mas01cr@511
|
368 (unwind-protect
|
mas01cr@511
|
369 (with-alien ((qid adb-query-id-t)
|
mas01cr@511
|
370 (qparams adb-query-parameters-t)
|
mas01cr@511
|
371 (qrefine adb-query-refine-t)
|
mas01cr@511
|
372 (qspec adb-query-spec-t)
|
mas01cr@511
|
373 (datum adb-datum-t))
|
mas01cr@511
|
374 (setf (slot datum 'key) "KSA_CHARM_337")
|
mas01cr@511
|
375 (setf (slot datum 'data) (sap-alien (sb-sys:int-sap 0) (* double)))
|
mas01cr@511
|
376
|
mas01cr@511
|
377 (setf (slot qid 'datum) (addr datum))
|
mas01cr@511
|
378 (setf (slot qid 'sequence-length) 30)
|
mas01cr@511
|
379 (setf (slot qid 'flags) 1) ; ADB_QID_FLAG_EXHAUSTIVE
|
mas01cr@511
|
380
|
mas01cr@511
|
381 (setf (slot qparams 'accumulation) 2) ; ADB_ACCUMULATION_PER_TRACK
|
mas01cr@511
|
382 (setf (slot qparams 'distance) 2) ; ADB_DISTANCE_EUCLIDEAN_NORMED
|
mas01cr@511
|
383 (setf (slot qparams 'npoints) 1)
|
mas01cr@511
|
384 (setf (slot qparams 'ntracks) 20)
|
mas01cr@511
|
385
|
mas01cr@511
|
386 (setf (slot qrefine 'flags) 0)
|
mas01cr@511
|
387 (setf (slot qrefine 'hopsize) 1)
|
mas01cr@511
|
388
|
mas01cr@511
|
389 (setf (slot qspec 'qid) qid)
|
mas01cr@511
|
390 (setf (slot qspec 'params) qparams)
|
mas01cr@511
|
391 (setf (slot qspec 'refine) qrefine)
|
mas01cr@511
|
392 (let ((results (%query db (addr qspec))))
|
mas01cr@511
|
393 (unless (null-alien results)
|
mas01cr@511
|
394 (unwind-protect
|
mas01cr@511
|
395 (flet ((print-result (n)
|
mas01cr@511
|
396 (let ((result (deref (slot results 'results) n)))
|
mas01cr@511
|
397 (format t "~&~A ~F ~D ~D~%"
|
mas01cr@511
|
398 (slot result 'key) (slot result 'dist)
|
mas01cr@511
|
399 (slot result 'qpos) (slot result 'ipos)))))
|
mas01cr@511
|
400 (dotimes (i (slot results 'nresults))
|
mas01cr@511
|
401 (print-result i)))
|
mas01cr@511
|
402 (%free-query-results db (addr qspec) results)))))
|
mas01cr@511
|
403 (%close db)))))
|
mas01cr@511
|
404 |#
|