[pysqlite] Is this error due to my Linux version?

Ed Pasma <[email protected]> Tue, 12 Aug 2008 07:59:18 +0200
Newsgroups gmane.comp.python.db.pysqlite.user
Message-ID <[email protected]>

Hello, can anybody with a Linux system and SQLite 3.5.9 see if  
attached script reaches the end? (http://home.wanadoo.nl/italy4ever/ 
thread_io.py.html)

It fails on my SuSE 9, 2.4.21 with OperationalError: Library routine  
called out of sequence (sqlite_misuse).

The script measures the effect of sqlite shared-cache mode on  
performance. The error occurs when this is enabled. It runs fine on  
OS X and WINNT, but I wish to make a platform independent package.  
SQLite was built threadsafe for sure.

Thanks for any information, Edzard

_______________________________________________
list-pysqlite mailing list
list-pysqlite-FR6EJeJVuqdwc357pe9rcyQmJico6nz3epZhswDD4dQ@public.gmane.org
http://itsystementwicklung.de/cgi-bin/mailman/listinfo/list-pysqlite
thread_io.py (text/x-python-script, 3.1 KB)
#!/usr/bin/env python
"""
A test that concurrently reads and writes a database.
The test is repeated for various numbers of threads
and for both regular and shared-cache access mode.
"""
import sys, time, random, threading
try:
    import pysqlite2.dbapi2 as sqlite3
except:
    import sqlite3

sharedcache = True
format = '%12s %12s %12s %12s'
errors = False

def main ():
    print format % ('threads', 'sharedcache', 'rows', 'seconds')
    print format % ('-------', '-----------', '----', '-------')
    for nthreads in 1, 2, 3, 4:
        for sharedcache in False, True:
            sqlite3.enable_shared_cache (sharedcache)
            t0 = time.time ()
            con = Connection ('test.db', isolation_level = None)
            cur = con.cursor ()
            try:
                cur.execute ('BEGIN')
                cur.execute ('CREATE TABLE IF NOT EXISTS t (c)')
                cur.execute ('DELETE FROM t');
                for i in range (5000):
                    cur.execute ('INSERT INTO t VALUES (?)',
                            (str (credits), ), # 150 bytes
                            )
                cur.execute ('COMMIT')
                threads = []
                for i in range (nthreads):
                    threads.append (threading.Thread (
                            group=None,
                            target= sub,
                            name = None,
                            args = (nthreads, i),
                            kwargs={},
                            verbose=None,
                            ))
                for i in threads:
                    i.start ()
                for i in threads:
                    i.join ()
                n = cur.execute ('SELECT COUNT (*) FROM t').fetchone () [0]
                dt = round (time.time () - t0, 1)
                print format % (nthreads, sharedcache, n, dt)
            finally:
                con.close ()
        if errors:
            break

def sub (nthreads, nr):
    con = Connection ('test.db', isolation_level = None)
    cur = con.cursor ()
    try:
        for i in range (24):
            cur.execute ('SELECT COUNT (*) FROM t WHERE c = 0').fetchone () [0]
            if i % nthreads == nr:
                cur.execute ('BEGIN')

                cur.execute ('INSERT INTO t VALUES (?)', (nr, ))
                cur.execute ('COMMIT')
            time.sleep (.01)
    except:
        global errors
        errors = True
        con.close ()
        raise
    con.close ()

class Connection (sqlite3.Connection):
    " use custom Cursor "
    def cursor (self):
        return Cursor (self)

class Cursor (sqlite3.Cursor):
    " add busy handler for shared cache mode "
    def execute (self, *args, **kwargs):
        t0 = time.time ()
        while True:
            try:
                return sqlite3.Cursor.execute (self, *args, **kwargs)
                break
            except sqlite3.OperationalError, e:
                if 'locked' not in str (e) or \
                        time.time () - t0 > 5.:
                    raise
                time.sleep (.01)

if __name__ == '__main__':
    main ()