annotate bindings/sb-alien/interface.lisp @ 770:c54bc2ffbf92 tip

update tags
author convert-repo
date Fri, 16 Dec 2011 11:34:01 +0000
parents e4eae1f59759
children
rev   line source
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 |#