[elephant-devel] Sqlite-3 backend, threads and transactions

Ignas Mikalajunas ignas.mikalajunas at gmail.com
Wed Apr 19 15:34:41 UTC 2006


    Hi, I am trying to use elephant as a backend data store for my
blogging application. And have encountered some problems with it ...
As i want to only commit the transaction in cases of error and tbnl is
using throw for redirects i need to manualy open/close transactions,
but it seems (ele:start-transaction) is only designed to work with BDB
backend, so i must use (clsql:start-transaction) instead.

At the moment the wrapper around each request looks like this:

(defun common-blog-view-wrapper (function)
  (ele:with-open-store (`(:sqlite3 ,(format nil "~A"
(get-config-option "database-path"))))
    (let ((error nil)
          (transaction nil))
      (unwind-protect
           (handler-bind ((error (lambda (cond)
                                   (declare (ignore cond))
                                   (setf error t))))
             (clsql:start-transaction)
             (setf transaction t)
             (tbnl::string-to-octets (funcall function) :utf-8))
        (when transaction
          (if error
              (clsql:rollback)
              (clsql:commit)))))))

As sqlite requires each thread to have it's own connection by throwing
an error if one thread tries to reuse a connection created by another
thread at least on Ubuntu Dapper. Google says that it depends on a
compile time flag for libsqlite3. Everything works more or less fine ,
but when i am reloading the page multiple times in a row very fast i
am getting a traceback (attached). And can't quite grok what went
wrong ... Maybe some one who knows internals of elephant can help me
out with this, as i could not really track where could a database
connection appear in another thread.

A testcase for SBCL:

(defun test ()
  (ele:with-open-store ('(:sqlite3 "/home/ignas/src/common-blog/dev.db"))))

(sb-thread:make-thread #'test) ;; a few times - works

(dotimes (i 3) (sb-thread:make-thread #'test)) ;; you get 3 tracebacks

By the way thanks for a wonderful library!

--
Ignas Mikalajūnas
-------------- next part --------------
While accessing database #<SQLITE3-DATABASE /home/ignas/src/common-blog/dev.db OPEN {B386C11}>
  with expression "UPDATE _CLSQL_SEQ_PERSISTENT_SEQ SET last_value=1033":
  Error 21 / library routine called out of sequence
  has occurred.


0: (BACKTRACE 536870911 #<SB-IMPL::STRING-OUTPUT-STREAM {A716771}>)
1: (TBNL::GET-BACKTRACE #<unavailable argument>)
2: ((LAMBDA (COND)) #<CLSQL-SYS:SQL-DATABASE-DATA-ERROR {A7164B9}>)
3: ((LAMBDA (COND)) #<CLSQL-SYS:SQL-DATABASE-DATA-ERROR {A7164B9}>)
4: (SIGNAL #<CLSQL-SYS:SQL-DATABASE-DATA-ERROR {A7164B9}>)
5: (ERROR CLSQL-SYS:SQL-DATABASE-DATA-ERROR)
6: ((SB-PCL::FAST-METHOD CLSQL-SYS:DATABASE-EXECUTE-COMMAND
                         (T CLSQL-SQLITE3:SQLITE3-DATABASE))
    #<unavailable argument>
    #<unavailable argument>
    "UPDATE _CLSQL_SEQ_PERSISTENT_SEQ SET last_value=1033"
    #<CLSQL-SQLITE3:SQLITE3-DATABASE /home/ignas/src/common-blog/dev.db OPEN {B386C11}>)
7: ((LAMBDA
        (SB-PCL::.PV-CELL. SB-PCL::.NEXT-METHOD-CALL. SB-PCL::.ARG0.
         SB-PCL::.ARG1.))
    #<unavailable argument>
    #<unavailable argument>
    "UPDATE _CLSQL_SEQ_PERSISTENT_SEQ SET last_value=1033"
    #<CLSQL-SQLITE3:SQLITE3-DATABASE /home/ignas/src/common-blog/dev.db OPEN {B386C11}>)
8: ((FLET #:WITHOUT-INTERRUPTS-BODY-138))
9: ((SB-PCL::FAST-METHOD CLSQL-SYS:DATABASE-SEQUENCE-NEXT (T T))
    #<unavailable argument>
    #<unavailable argument>
    "PERSISTENT_SEQ"
    #<CLSQL-SQLITE3:SQLITE3-DATABASE /home/ignas/src/common-blog/dev.db OPEN {B386C11}>)
10: ((SB-PCL::FAST-METHOD CLSQL-SYS:DATABASE-SEQUENCE-NEXT
                          (T "#<...>" . "#<...>"))
     #<unavailable argument>
     #<unavailable argument>
     "PERSISTENT_SEQ"
     #<CLSQL-SQLITE3:SQLITE3-DATABASE /home/ignas/src/common-blog/dev.db OPEN {B386C11}>)
11: ((SB-PCL::FAST-METHOD INITIALIZE-INSTANCE :BEFORE (ELEPHANT:PERSISTENT))
     #<unavailable argument>
     #<unavailable argument>
     #<ELEPHANT:SQL-BTREE {B713E91}>
     (:SC #<ELEPHANT:SQL-STORE-CONTROLLER {B712DE9}>))
12: ((LAMBDA (SB-PCL::|.P0.|)) #<unavailable argument>)
13: (ELEPHANT:MAKE-SQL-BTREE #<ELEPHANT:SQL-STORE-CONTROLLER {B712DE9}>)
14: ((SB-PCL::FAST-METHOD ELEPHANT:OPEN-CONTROLLER
                          (ELEPHANT:SQL-STORE-CONTROLLER))
     (#(NIL 2 1) . #())
     #<unavailable argument>
     #<ELEPHANT:SQL-STORE-CONTROLLER {B712DE9}>
     (:RECOVER NIL :RECOVER-FATAL NIL :THREAD T))
15: (ELEPHANT::GET-CONTROLLER (:SQLITE3 "/home/ignas/src/common-blog/dev.db"))
16: (COMMON-BLOG::COMMON-BLOG-VIEW-WRAPPER COMMON-BLOG::ENTRY)
17: (TBNL::PROCESS-REQUEST
     (("content-stream"
       . #<SB-SYS:FD-STREAM for "a constant string" {B4627E9}>)
      ("server-protocol" . "HTTP/1.1") ("url" . "/entry/gtk-tutorial")
      ("method" . "GET") ("server-ip-port" . "9980")
      ("Cookie"
       . "zope3_cs_8aa2da3=J7bMX78FLS0bh-3MMCMigC0-yuMxtVntJOUMci.xjDZBdR.8ZvgWfQ")
      ("Connection" . "keep-alive") ("Keep-Alive" . "300")
      ("Accept-Charset" . "ISO-8859-1,utf-8;q=0.7,*;q=0.7")
      ("Accept-Encoding" . "gzip,deflate")
      ("Accept-Language" . "en-us,en;q=0.5")
      ("Accept"
       . "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5")
      ("User-Agent"
       . "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.2) Gecko/20060308 Firefox/1.5.0.2")
      ("Host" . "localhost:9980")))
18: (TBNL::LISTEN-FOR-REQUEST
     #<SB-SYS:FD-STREAM for "a constant string" {B4627E9}>
     TBNL::PROCESS-REQUEST)
19: ((LAMBDA ()))
20: ((LAMBDA ()))
21: ("foreign function: call_into_lisp")
22: ("foreign function: funcall0")
23: ("foreign function: new_thread_trampoline")
24: ("foreign function: #xB7FC6341")







More information about the elephant-devel mailing list