<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
<HTML>
<HEAD>
  <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8">
  <META NAME="GENERATOR" CONTENT="GtkHTML/3.3.2">
</HEAD>
<BODY>
Dear Ignas,<BR>
    Forgive me being a little confused; I had to get my mind back into this after some time off.<BR>
    Basically, would should not open multiple store controllers in different threads onto the same database.<BR>
Onto different databases, this would be acceptable; onto the same database, you are definitely creating<BR>
the danger of inconsistent state.  The code below the pattern I use.<BR>
<BR>
(open-store *testbdb-spec*)<BR>
(defun test ()<BR>
  (format t "store-controller ~A~%" *store-controller*)<BR>
  (with-transaction (:store-controller *store-controller*)<BR>
    (ele::add-to-root "x" (gensym))<BR>
    (format t "Here's one try~A!~%" (ele::get-from-root "x"))<BR>
    ))<BR>
<BR>
(sb-thread:make-thread #'test) <BR>
<BR>
(dotimes (i 5) (sb-thread:make-thread #'test)) <BR>
<BR>
At first it might seem quite objectionably to lave the store-controller object open for a very long duration---but<BR>
I have done for days and days without a problem.  So I am basically recommending one store controller.  Operations<BR>
in multiple threads against one store controller should be threadsafe; I don't think this has really been tested much<BR>
but that was the plan of the original authors, I think.  It is possible that the extensive changes Ian and I have made<BR>
in the last six months have messed that up.<BR>
<BR>
The other problem, of course, is the potential SQLite3 problem you mention.  This may keep the above <BR>
code from working on your installation (please try it for me and report the result.)<BR>
<BR>
In that case, I would much rather address the SQLite3-specific problem than workaround things in <BR>
a very complicated way.<BR>
<BR>
I could not open the url to trouble ticket that you posted.<BR>
<BR>
If it is a question of a compilation switch in SQLite3, is that an option for you?  Could you recompile<BR>
it in your environment?<BR>
<BR>
<BR>
n Wed, 2006-04-19 at 18:34 +0300, Ignas Mik
<BLOCKQUOTE TYPE=CITE>
<PRE>
<FONT COLOR="#000000">    Hi, I am trying to use elephant as a backend data store for my</FONT>
<FONT COLOR="#000000">blogging application. And have encountered some problems with it ...</FONT>
<FONT COLOR="#000000">As i want to only commit the transaction in cases of error and tbnl is</FONT>
<FONT COLOR="#000000">using throw for redirects i need to manualy open/close transactions,</FONT>
<FONT COLOR="#000000">but it seems (ele:start-transaction) is only designed to work with BDB</FONT>
<FONT COLOR="#000000">backend, so i must use (clsql:start-transaction) instead.</FONT>

<FONT COLOR="#000000">At the moment the wrapper around each request looks like this:</FONT>

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

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

<FONT COLOR="#000000">A testcase for SBCL:</FONT>

<FONT COLOR="#000000">(defun test ()</FONT>
<FONT COLOR="#000000">  (ele:with-open-store ('(:sqlite3 "/home/ignas/src/common-blog/dev.db"))))</FONT>

<FONT COLOR="#000000">(sb-thread:make-thread #'test) ;; a few times - works</FONT>

<FONT COLOR="#000000">(dotimes (i 3) (sb-thread:make-thread #'test)) ;; you get 3 tracebacks</FONT>

<FONT COLOR="#000000">By the way thanks for a wonderful library!</FONT>

<FONT COLOR="#000000">--</FONT>
<FONT COLOR="#000000">Ignas Mikalajūnas</FONT>
<FONT COLOR="#000000">_______________________________________________</FONT>
<FONT COLOR="#000000">elephant-devel site list</FONT>
<FONT COLOR="#000000"><A HREF="mailto:elephant-devel@common-lisp.net">elephant-devel@common-lisp.net</A></FONT>
<FONT COLOR="#000000"><A HREF="http://common-lisp.net/mailman/listinfo/elephant-devel">http://common-lisp.net/mailman/listinfo/elephant-devel</A></FONT>
</PRE>
</BLOCKQUOTE>
</BODY>
</HTML>