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@672
|
146 (qkey "" :type string)
|
mas01cr@672
|
147 (ikey "" :type string)
|
mas01cr@511
|
148 (distance 0d0 :type double-float)
|
mas01cr@511
|
149 (qpos 0 :type (and unsigned-byte fixnum))
|
mas01cr@511
|
150 (ipos 0 :type (and unsigned-byte fixnum)))
|
mas01cr@511
|
151
|
mas01cr@511
|
152 ;;; Hrm. To copy (from the malloc heap) or not to copy? Copying
|
mas01cr@511
|
153 ;;; would make things generally easier, I guess, and we have to hope
|
mas01cr@511
|
154 ;;; that the order of magnitude is not such that the copying causes
|
mas01cr@511
|
155 ;;; pain.
|
mas01cr@511
|
156 (defclass results (sequence standard-object)
|
mas01cr@511
|
157 ())
|
mas01cr@511
|
158 (defclass copied-query-results (results)
|
mas01cr@511
|
159 ((results :initarg results :accessor %copied-results)))
|
mas01cr@511
|
160 (defmethod print-object ((o copied-query-results) s)
|
mas01cr@511
|
161 (pprint-logical-block (s nil)
|
mas01cr@511
|
162 (print-unreadable-object (o s :type t)
|
mas01cr@511
|
163 (format s "(~D results):~2I~@:_" (length o))
|
mas01cr@511
|
164 (sequence:dosequence (r o)
|
mas01cr@511
|
165 (pprint-pop)
|
mas01cr@511
|
166 (format s "~A ~6,3e ~D ~D~@:_"
|
mas01cr@672
|
167 (result-ikey r) (result-distance r)
|
mas01cr@511
|
168 (result-qpos r) (result-ipos r))))))
|
mas01cr@511
|
169
|
mas01cr@511
|
170 (defmethod sequence:length ((o copied-query-results))
|
mas01cr@511
|
171 (length (%copied-results o)))
|
mas01cr@511
|
172 (defmethod sequence:elt ((o copied-query-results) index)
|
mas01cr@511
|
173 (elt (%copied-results o) index))
|
mas01cr@511
|
174 (defmethod (setf sequence:elt) (new-value (o copied-query-results) index)
|
mas01cr@511
|
175 (setf (elt (%copied-results o) index) new-value))
|
mas01cr@511
|
176 (defmethod sequence:make-sequence-like
|
mas01cr@511
|
177 ((o copied-query-results) length &rest args
|
mas01cr@511
|
178 &key initial-element initial-contents)
|
mas01cr@511
|
179 (declare (ignore initial-element initial-contents))
|
mas01cr@511
|
180 (let ((vector (apply #'make-array length args)))
|
mas01cr@511
|
181 (make-instance 'copied-query-results 'results vector)))
|
mas01cr@511
|
182 (defmethod sequence:adjust-sequence
|
mas01cr@511
|
183 ((o copied-query-results) length &rest args
|
mas01cr@511
|
184 &key initial-element initial-contents)
|
mas01cr@511
|
185 (declare (ignore initial-element initial-contents))
|
mas01cr@511
|
186 (let ((results (%copied-results o)))
|
mas01cr@511
|
187 (apply #'sequence:adjust-sequence results length args))
|
mas01cr@511
|
188 o)
|
mas01cr@511
|
189
|
mas01cr@511
|
190 (defclass proxied-query-results (results)
|
mas01cr@511
|
191 ((adb :initarg adb)
|
mas01cr@511
|
192 (spec :initarg spec)
|
mas01cr@511
|
193 (results :initarg results)))
|
mas01cr@511
|
194 (defmethod initialize-instance :after ((o proxied-query-results) &key)
|
mas01cr@511
|
195 (when (and (slot-boundp o 'results)
|
mas01cr@511
|
196 (not (null-alien o))
|
mas01cr@511
|
197 (slot-boundp o 'spec))
|
mas01cr@511
|
198 (with-slots (results spec adb) o
|
mas01cr@511
|
199 (flet ((results-finalizer ()
|
mas01cr@511
|
200 (with-slots (alien) adb
|
mas01cr@511
|
201 (%free-query-results alien spec results))))
|
mas01cr@511
|
202 (sb-ext:finalize o #'results-finalizer)))))
|
mas01cr@511
|
203
|
mas01cr@511
|
204 (defgeneric query (datum db &key))
|
mas01cr@511
|
205
|
mas01cr@511
|
206 ;;; FIXME: I don't like this way of generalizing the boilerplate;
|
mas01cr@511
|
207 ;;; isn't there a nice functional way of doing this?
|
mas01cr@511
|
208 (macrolet
|
mas01cr@511
|
209 ((def (name datum-class &body qdatum-forms)
|
mas01cr@511
|
210 `(defmethod ,name ((datum ,datum-class) (db adb) &key
|
mas01cr@511
|
211 (sequence-length 1) (sequence-start 0)
|
mas01cr@511
|
212 exhaustivep accumulation distance
|
mas01cr@511
|
213 ;; FIXME: dubious historical defaults
|
mas01cr@511
|
214 (npoints 10) (ntracks 10)
|
mas01cr@511
|
215
|
mas01cr@511
|
216 (radius nil radiusp)
|
mas01cr@511
|
217 (include-keys nil include-keys-p)
|
mas01cr@677
|
218 (exclude-keys nil exclude-keys-p)
|
mas01cr@677
|
219 (query-hop 1 query-hop-p)
|
mas01cr@677
|
220 (db-hop 1 db-hop-p))
|
mas01cr@511
|
221 (unless (slot-boundp db 'alien)
|
mas01cr@511
|
222 (error "database ~S is closed" db))
|
mas01cr@511
|
223 (with-alien ((qid adb-query-id-t)
|
mas01cr@511
|
224 (qparams adb-query-parameters-t)
|
mas01cr@511
|
225 (qrefine adb-query-refine-t)
|
mas01cr@511
|
226 (qdatum adb-datum-t))
|
mas01cr@511
|
227 ,@qdatum-forms
|
mas01cr@511
|
228 (setf (slot qid 'datum) (addr qdatum))
|
mas01cr@511
|
229 (setf (slot qid 'sequence-length) sequence-length)
|
mas01cr@511
|
230 (setf (slot qid 'sequence-start) sequence-start)
|
mas01cr@511
|
231 (setf (slot qid 'flags) (if exhaustivep 1 0))
|
mas01cr@511
|
232
|
mas01cr@511
|
233 (setf (slot qparams 'accumulation)
|
mas01cr@511
|
234 (ecase accumulation
|
mas01cr@511
|
235 (:db 1)
|
mas01cr@511
|
236 (:per-track 2)
|
mas01cr@511
|
237 (:one-to-one 3)))
|
mas01cr@511
|
238 (setf (slot qparams 'distance)
|
mas01cr@511
|
239 (ecase distance
|
mas01cr@511
|
240 (:dot-product 1)
|
mas01cr@511
|
241 (:euclidean-normed 2)
|
mas01cr@511
|
242 (:euclidean 3)))
|
mas01cr@511
|
243 (setf (slot qparams 'npoints) (or npoints 0))
|
mas01cr@511
|
244 (setf (slot qparams 'ntracks) (or ntracks 0))
|
mas01cr@511
|
245
|
mas01cr@511
|
246 (let ((refine-flags 0))
|
mas01cr@511
|
247 (when radiusp
|
mas01cr@511
|
248 (setf refine-flags (logior refine-flags 4))
|
mas01cr@511
|
249 (setf (slot qrefine 'radius) (float radius 0d0)))
|
mas01cr@511
|
250 ;; FIXME: the freeing of the KEYS slot in these
|
mas01cr@511
|
251 ;; include/exclude keylists isn't interrupt-safe.
|
mas01cr@511
|
252 ;;
|
mas01cr@511
|
253 ;; FIXME: think quite hard about the behaviour of this
|
mas01cr@511
|
254 ;; when LENGTH is 0.
|
mas01cr@511
|
255 (when include-keys-p
|
mas01cr@511
|
256 (setf refine-flags (logior refine-flags 1))
|
mas01cr@511
|
257 (let ((length (length include-keys)))
|
mas01cr@511
|
258 (setf (slot (slot qrefine 'include) 'nkeys) length)
|
mas01cr@511
|
259 (let ((keys (make-alien c-string length)))
|
mas01cr@511
|
260 (setf (slot (slot qrefine 'include) 'keys) keys)
|
mas01cr@511
|
261 (loop for key being the elements of include-keys
|
mas01cr@511
|
262 for i upfrom 0
|
mas01cr@511
|
263 do (setf (deref keys i) key)))))
|
mas01cr@511
|
264 (when exclude-keys-p
|
mas01cr@511
|
265 (setf refine-flags (logior refine-flags 2))
|
mas01cr@511
|
266 (let ((length (length exclude-keys)))
|
mas01cr@511
|
267 (setf (slot (slot qrefine 'exclude) 'nkeys) length)
|
mas01cr@511
|
268 (let ((keys (make-alien c-string length)))
|
mas01cr@511
|
269 (setf (slot (slot qrefine 'exclude) 'keys) keys)
|
mas01cr@511
|
270 (loop for key being the elements of exclude-keys
|
mas01cr@511
|
271 for i upfrom 0
|
mas01cr@511
|
272 do (setf (deref keys i) key)))))
|
mas01cr@677
|
273 (when (or query-hop-p db-hop-p)
|
mas01cr@677
|
274 (setf refine-flags (logior refine-flags 64))
|
mas01cr@677
|
275 (setf (slot qrefine 'qhopsize) query-hop
|
mas01cr@677
|
276 (slot qrefine 'ihopsize) db-hop))
|
mas01cr@511
|
277 (setf (slot qrefine 'flags) refine-flags))
|
mas01cr@511
|
278
|
mas01cr@511
|
279 ;; FIXME: hm, this possibly suggests that there's something
|
mas01cr@511
|
280 ;; a bit wrong with the C audioDB interface. The API
|
mas01cr@511
|
281 ;; currently exposed effectively requires either that all
|
mas01cr@511
|
282 ;; the processing of query results happens in the same
|
mas01cr@511
|
283 ;; dynamic extent as the call to audiodb_query_spec(), or
|
mas01cr@511
|
284 ;; that the adb_query_spec_t object is allocated on the
|
mas01cr@511
|
285 ;; heap. We need to think harder about whether the spec
|
mas01cr@511
|
286 ;; argument is really required (I think it probably isn't).
|
mas01cr@511
|
287 ;;
|
mas01cr@511
|
288 ;; meanwhile, here we're using it with dynamic extent anyway, so
|
mas01cr@511
|
289 ;; we could put it right back on the stack.
|
mas01cr@511
|
290 (let ((qspec (make-alien adb-query-spec-t)))
|
mas01cr@511
|
291 (unwind-protect
|
mas01cr@511
|
292 (progn
|
mas01cr@511
|
293 (setf (slot qspec 'qid) qid)
|
mas01cr@511
|
294 (setf (slot qspec 'params) qparams)
|
mas01cr@511
|
295 (setf (slot qspec 'refine) qrefine)
|
mas01cr@511
|
296
|
mas01cr@511
|
297 (let ((results
|
mas01cr@511
|
298 (sb-int:with-float-traps-masked (:invalid)
|
mas01cr@511
|
299 (%query (slot-value db 'alien) qspec))))
|
mas01cr@511
|
300 (flet ((collect-copied-results ()
|
mas01cr@511
|
301 (let ((nresults (slot results 'nresults))
|
mas01cr@511
|
302 (cresults (slot results 'results)))
|
mas01cr@511
|
303 (coerce
|
mas01cr@511
|
304 (loop for i below nresults
|
mas01cr@511
|
305 for r = (deref cresults i)
|
mas01cr@511
|
306 collect (make-result
|
mas01cr@672
|
307 :ikey (slot r 'ikey)
|
mas01cr@672
|
308 :qkey (slot r 'qkey)
|
mas01cr@511
|
309 :distance (slot r 'dist)
|
mas01cr@511
|
310 :qpos (slot r 'qpos)
|
mas01cr@511
|
311 :ipos (slot r 'ipos)))
|
mas01cr@511
|
312 'vector))))
|
mas01cr@511
|
313 (unwind-protect
|
mas01cr@511
|
314 (make-instance 'copied-query-results
|
mas01cr@511
|
315 'results (collect-copied-results))
|
mas01cr@511
|
316 (%free-query-results (slot-value db 'alien) qspec results)))))
|
mas01cr@511
|
317 (when (logbitp 0 (slot (slot qspec 'refine) 'flags))
|
mas01cr@511
|
318 (free-alien (slot (slot (slot qspec 'refine) 'include) 'keys)))
|
mas01cr@511
|
319 (when (logbitp 1 (slot (slot qspec 'refine) 'flags))
|
mas01cr@511
|
320 (free-alien (slot (slot (slot qspec 'refine) 'exclude) 'keys)))
|
mas01cr@511
|
321 (free-alien qspec)))))))
|
mas01cr@647
|
322 (def query string (setf (slot qdatum 'key) datum
|
mas01cr@647
|
323 (slot qdatum 'data) nil))
|
mas01cr@511
|
324 (def query datum
|
mas01cr@511
|
325 (setf (slot qdatum 'key) (datum-key datum))
|
mas01cr@511
|
326 (setf (slot qdatum 'dim) (array-dimension (datum-data datum) 1))
|
mas01cr@511
|
327 (setf (slot qdatum 'nvectors) (array-dimension (datum-data datum) 0))
|
mas01cr@511
|
328 (setf (slot qdatum 'data) (sb-sys:vector-sap (sb-ext:array-storage-vector (datum-data datum))))
|
mas01cr@511
|
329 (if (datum-times datum)
|
mas01cr@511
|
330 (setf (slot qdatum 'times) (sb-sys:vector-sap (sb-ext:array-storage-vector (datum-times datum))))
|
mas01cr@511
|
331 (setf (slot qdatum 'times) nil))
|
mas01cr@511
|
332 (if (datum-power datum)
|
mas01cr@511
|
333 (setf (slot qdatum 'power) (sb-sys:vector-sap (sb-ext:array-storage-vector (datum-times datum))))
|
mas01cr@511
|
334 (setf (slot qdatum 'power) nil))))
|
mas01cr@511
|
335
|
mas01cr@646
|
336 (defgeneric liszt (adb))
|
mas01cr@646
|
337 (defmethod liszt ((db adb))
|
mas01cr@646
|
338 (let ((results (%liszt (slot-value db 'alien))))
|
mas01cr@646
|
339 (unwind-protect
|
mas01cr@646
|
340 (loop for i below (slot results 'nresults)
|
mas01cr@646
|
341 with entries = (slot results 'entries)
|
mas01cr@646
|
342 for entry = (deref entries i)
|
mas01cr@646
|
343 collect (cons (slot entry 'key) (slot entry 'nvectors)))
|
mas01cr@646
|
344 (%free-liszt-results (slot-value db 'alien) results))))
|
mas01cr@646
|
345
|
mas01cr@511
|
346 #+test
|
mas01cr@511
|
347 (sb-adb:with-adb (db "/home/csr21/tmp/omras2-workshop/9.adb")
|
mas01cr@511
|
348 (sb-adb:query "KSA_CHARM_337" db :exhaustivep t :sequence-length 30
|
mas01cr@511
|
349 :accumulation :per-track :distance :euclidean :npoints 1 :ntracks 20))
|
mas01cr@511
|
350
|
mas01cr@511
|
351 #+test
|
mas01cr@511
|
352 (sb-adb:with-adb (db "/home/csr21/tmp/omras2-workshop/9.adb")
|
mas01cr@511
|
353 (sb-adb:query "KSA_CHARM_337" db :sequence-start 20 :sequence-length 20
|
mas01cr@511
|
354 :accumulation :per-track :distance :euclidean-normed
|
mas01cr@511
|
355 :npoints 10 :ntracks 1))
|
mas01cr@511
|
356
|
mas01cr@511
|
357 #+test
|
mas01cr@511
|
358 (sb-adb:with-adb (db "/home/csr21/tmp/omras2-workshop/9.adb")
|
mas01cr@511
|
359 (sb-adb:query "KSA_CHARM_337" db
|
mas01cr@511
|
360 :exhaustivep t :sequence-length 30
|
mas01cr@511
|
361 :accumulation :per-track :distance :euclidean-normed
|
mas01cr@511
|
362 :npoints 2 :ntracks 10))
|
mas01cr@511
|
363
|
mas01cr@511
|
364 ;;; only hacks and tests below
|
mas01cr@511
|
365 #|
|
mas01cr@511
|
366 (defun foo ()
|
mas01cr@511
|
367 (let ((db (%open "/home/csr21/tmp/omras2-workshop/9.adb" sb-posix:o-rdonly)))
|
mas01cr@511
|
368 (unless (null-alien db)
|
mas01cr@511
|
369 (unwind-protect
|
mas01cr@511
|
370 (with-alien ((status adb-status-t))
|
mas01cr@511
|
371 (%status db (addr status))
|
mas01cr@511
|
372 (print (list (slot status 'dim) (slot status 'nfiles))))
|
mas01cr@511
|
373 (%close db)))))
|
mas01cr@511
|
374
|
mas01cr@511
|
375 (defun set-up-spec (spec qid qparams qrefine)
|
mas01cr@511
|
376 (declare (type (alien adb-query-parameters-t) qparams)
|
mas01cr@511
|
377 (type (alien adb-query-refine-t) qrefine)
|
mas01cr@511
|
378 (type (alien adb-query-id-t) qid)
|
mas01cr@511
|
379 (type (alien adb-query-spec-t) spec))
|
mas01cr@511
|
380 (setf (slot spec 'refine) qrefine)
|
mas01cr@511
|
381 nil)
|
mas01cr@511
|
382
|
mas01cr@511
|
383 (defun bar ()
|
mas01cr@511
|
384 (let ((db (%open "/home/csr21/tmp/omras2-workshop/9.adb" sb-posix:o-rdonly)))
|
mas01cr@511
|
385 (unless (null-alien db)
|
mas01cr@511
|
386 (unwind-protect
|
mas01cr@511
|
387 (with-alien ((qid adb-query-id-t)
|
mas01cr@511
|
388 (qparams adb-query-parameters-t)
|
mas01cr@511
|
389 (qrefine adb-query-refine-t)
|
mas01cr@511
|
390 (qspec adb-query-spec-t)
|
mas01cr@511
|
391 (datum adb-datum-t))
|
mas01cr@511
|
392 (setf (slot datum 'key) "KSA_CHARM_337")
|
mas01cr@511
|
393 (setf (slot datum 'data) (sap-alien (sb-sys:int-sap 0) (* double)))
|
mas01cr@511
|
394
|
mas01cr@511
|
395 (setf (slot qid 'datum) (addr datum))
|
mas01cr@511
|
396 (setf (slot qid 'sequence-length) 30)
|
mas01cr@511
|
397 (setf (slot qid 'flags) 1) ; ADB_QID_FLAG_EXHAUSTIVE
|
mas01cr@511
|
398
|
mas01cr@511
|
399 (setf (slot qparams 'accumulation) 2) ; ADB_ACCUMULATION_PER_TRACK
|
mas01cr@511
|
400 (setf (slot qparams 'distance) 2) ; ADB_DISTANCE_EUCLIDEAN_NORMED
|
mas01cr@511
|
401 (setf (slot qparams 'npoints) 1)
|
mas01cr@511
|
402 (setf (slot qparams 'ntracks) 20)
|
mas01cr@511
|
403
|
mas01cr@511
|
404 (setf (slot qrefine 'flags) 0)
|
mas01cr@511
|
405 (setf (slot qrefine 'hopsize) 1)
|
mas01cr@511
|
406
|
mas01cr@511
|
407 (setf (slot qspec 'qid) qid)
|
mas01cr@511
|
408 (setf (slot qspec 'params) qparams)
|
mas01cr@511
|
409 (setf (slot qspec 'refine) qrefine)
|
mas01cr@511
|
410 (let ((results (%query db (addr qspec))))
|
mas01cr@511
|
411 (unless (null-alien results)
|
mas01cr@511
|
412 (unwind-protect
|
mas01cr@511
|
413 (flet ((print-result (n)
|
mas01cr@511
|
414 (let ((result (deref (slot results 'results) n)))
|
mas01cr@511
|
415 (format t "~&~A ~F ~D ~D~%"
|
mas01cr@511
|
416 (slot result 'key) (slot result 'dist)
|
mas01cr@511
|
417 (slot result 'qpos) (slot result 'ipos)))))
|
mas01cr@511
|
418 (dotimes (i (slot results 'nresults))
|
mas01cr@511
|
419 (print-result i)))
|
mas01cr@511
|
420 (%free-query-results db (addr qspec) results)))))
|
mas01cr@511
|
421 (%close db)))))
|
mas01cr@511
|
422 |#
|