diff options
author | Jan Mercl <0xjnml@gmail.com> | 2017-07-01 23:04:53 +0200 |
---|---|---|
committer | Jan Mercl <0xjnml@gmail.com> | 2017-07-01 23:04:53 +0200 |
commit | 5e8a085cfb2f6df373a2a68436b1c1acacba592b (patch) | |
tree | 6cd0e355f252b4e45331b7e476904c9b588ddce5 /internal/threadtest4 | |
parent | 8370d1a12ed5bbad6630675316ee3985d8372a7b (diff) |
Add a couple of tests. Build only on linux, do not pass.
modified: Makefile
modified: all_test.go
modified: generator.go
modified: internal/bin/bin_linux_386.go
modified: internal/bin/bin_linux_amd64.go
new file: internal/mptest/mptest_linux_386.go
new file: internal/mptest/mptest_linux_amd64.go
new file: internal/threadtest1/threadtest1_linux_386.go
new file: internal/threadtest1/threadtest1_linux_amd64.go
new file: internal/threadtest2/threadtest2_linux_386.go
new file: internal/threadtest2/threadtest2_linux_amd64.go
new file: internal/threadtest4/threadtest4_linux_386.go
new file: internal/threadtest4/threadtest4_linux_amd64.go
modified: main.c
new file: sqlite.h
new file: testdata/mptest/config01.test
new file: testdata/mptest/config02.test
new file: testdata/mptest/crash01.test
new file: testdata/mptest/crash02.subtest
new file: testdata/mptest/multiwrite01.test
Diffstat (limited to 'internal/threadtest4')
-rw-r--r-- | internal/threadtest4/threadtest4_linux_386.go | 600 | ||||
-rw-r--r-- | internal/threadtest4/threadtest4_linux_amd64.go | 600 |
2 files changed, 1200 insertions, 0 deletions
diff --git a/internal/threadtest4/threadtest4_linux_386.go b/internal/threadtest4/threadtest4_linux_386.go new file mode 100644 index 0000000..252ac2f --- /dev/null +++ b/internal/threadtest4/threadtest4_linux_386.go @@ -0,0 +1,600 @@ +// Code generated by ccgo. DO NOT EDIT. + +// threadtest4.c + +// 2014-12-11 +// +// The author disclaims copyright to this source code. In place of +// a legal notice, here is a blessing: +// +// May you do good and not evil. +// May you find forgiveness for yourself and forgive others. +// May you share freely, never taking more than you give. +// +// ************************************************************************* +// This file implements a simple standalone program used to stress the +// SQLite library when accessing the same set of databases simultaneously +// from multiple threads in shared-cache mode. +// +// This test program runs on unix-like systems only. It uses pthreads. +// To compile: +// +// gcc -g -Wall -I. threadtest4.c sqlite3.c -ldl -lpthread +// +// To run: +// +// ./a.out 10 +// +// The argument is the number of threads. There are also options, such +// as -wal and -multithread and -serialized. +// +// Consider also compiling with clang instead of gcc and adding the +// -fsanitize=thread option. + +package main + +import ( + "math" + "os" + "unsafe" + + "github.com/cznic/crt" + "github.com/cznic/sqlite/internal/bin" +) + +var argv []*int8 + +func main() { + for _, v := range os.Args { + argv = append(argv, (*int8)(crt.CString(v))) + } + argv = append(argv, nil) + X_start(crt.NewTLS(), int32(len(os.Args)), &argv[0]) +} + +func X_start(tls *crt.TLS, _argc int32, _argv **int8) { + crt.X__register_stdfiles(tls, Xstdin, Xstdout, Xstderr) + crt.X__builtin_exit(tls, Xmain(tls, _argc, _argv)) +} + +var Xstdin unsafe.Pointer + +func init() { + Xstdin = unsafe.Pointer(&X__stdfiles) +} + +var X__stdfiles [3]unsafe.Pointer + +var Xstdout unsafe.Pointer + +func init() { + Xstdout = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 4) +} + +var Xstderr unsafe.Pointer + +func init() { + Xstderr = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 8) +} + +func Xmain(tls *crt.TLS, _argc int32, _argv **int8) (r0 int32) { + var _nWorker, _i, _nErr, _nTest, _rc int32 + var _wkrFlags uint32 + var _1_z *int8 + var _db unsafe.Pointer + var _wrMutex crt.Xpthread_mutex_t + var _infoTop XWorkerInfo + var _aInfo, _p *XWorkerInfo + r0 = i32(0) + _nWorker = i32(0) + _wkrFlags = u32(0) + _nErr = i32(0) + _nTest = i32(0) + _db = nil + bin.Xsqlite3_config(tls, i32(2)) + _i = i32(1) +_0: + if _i >= _argc { + goto _3 + } + _1_z = *(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 4*uintptr(_i))) + if int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(0))))) != i32(45) { + goto _4 + } + if (int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(1))))) == i32(45)) && (int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(2))))) != i32(0)) { + *(*uintptr)(unsafe.Pointer(&_1_z)) += uintptr(1) + } + if crt.Xstrcmp(tls, _1_z, str(0)) == i32(0) { + bin.Xsqlite3_config(tls, i32(2)) + { + p := &_wkrFlags + *p = (*p) & uint32(i32(-2)) + sink0 = *p + } + goto _8 + } + if crt.Xstrcmp(tls, _1_z, str(13)) == i32(0) { + bin.Xsqlite3_config(tls, i32(3)) + { + p := &_wkrFlags + *p = (*p) | uint32(i32(1)) + sink0 = *p + } + goto _10 + } + if crt.Xstrcmp(tls, _1_z, str(25)) == i32(0) { + { + p := &_wkrFlags + *p = (*p) | uint32(i32(2)) + sink0 = *p + } + goto _12 + } + if crt.Xstrcmp(tls, _1_z, str(30)) == i32(0) { + { + p := &_wkrFlags + *p = (*p) | uint32(i32(4)) + sink0 = *p + } + goto _14 + } + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(37), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 4*uintptr(_i))))) + crt.Xexit(tls, i32(1)) +_14: +_12: +_10: +_8: + goto _15 +_4: + if int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(0))))) < i32(49) || int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(0))))) > i32(57) || _nWorker != i32(0) { + goto _18 + } + _nWorker = crt.Xatoi(tls, _1_z) + if _nWorker < i32(2) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(70)) + crt.Xexit(tls, i32(1)) + } + goto _20 +_18: + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(92), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 4*uintptr(_i))))) + crt.Xexit(tls, i32(1)) +_20: +_15: + _i += 1 + goto _0 +_3: + if _nWorker == i32(0) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(127), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 4*uintptr(i32(0)))))) + crt.Xexit(tls, i32(1)) + } + if bin.Xsqlite3_threadsafe(tls) == 0 { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(260)) + crt.Xexit(tls, i32(1)) + } + bin.Xsqlite3_initialize(tls) + bin.Xsqlite3_enable_shared_cache(tls, i32(1)) + crt.Xpthread_mutex_init(tls, &_wrMutex, nil) + crt.Xunlink(tls, str(299)) + crt.Xunlink(tls, str(312)) + crt.Xunlink(tls, str(325)) + _rc = bin.Xsqlite3_open(tls, str(299), (**bin.Xsqlite3)(unsafe.Pointer(&_db))) + if _rc != i32(0) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(338)) + crt.Xexit(tls, i32(1)) + } + crt.Xmemset(tls, (unsafe.Pointer)(&_infoTop), i32(0), u32(40)) + *(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_infoTop)) + uintptr(16 /* X4 */))) = _db + *(*uint32)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_infoTop)) + uintptr(8 /* X2 */))) = _wkrFlags + _p = &_infoTop + if (_wkrFlags & uint32(i32(2))) != 0 { + _run_sql(tls, _p, str(382)) + } + _run_sql(tls, _p, str(406)) + _run_sql(tls, _p, str(429)) + _run_sql(tls, _p, str(485)) + _run_sql(tls, _p, str(515)) + _run_sql(tls, _p, str(544)) + _run_sql(tls, _p, str(577)) + _run_sql(tls, _p, str(639)) + _run_sql(tls, _p, str(675)) + _run_sql(tls, _p, str(710)) + _run_sql(tls, _p, str(743)) + _run_sql(tls, _p, str(805)) + _run_sql(tls, _p, str(841)) + _aInfo = (*XWorkerInfo)(_safe_malloc(tls, int32(u32(40)*uint32(_nWorker)))) + crt.Xmemset(tls, (unsafe.Pointer)(_aInfo), i32(0), u32(40)*uint32(_nWorker)) + _i = i32(0) +_25: + if _i >= _nWorker { + goto _28 + } + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))))) + uintptr(0 /* X0 */))) = _i + i32(1) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))))) + uintptr(4 /* X1 */))) = _nWorker + *(*uint32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))))) + uintptr(8 /* X2 */))) = _wkrFlags + *(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))))) + uintptr(12 /* X3 */))) = _db + *(**crt.Xpthread_mutex_t)(unsafe.Pointer((*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))))) + uintptr(36 /* X9 */))))) = &_wrMutex + _rc = crt.Xpthread_create(tls, (*uint32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i)))))+uintptr(32 /* X8 */))), nil, _worker_thread, (unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))))) + if _rc != i32(0) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(876), _i+i32(1)) + crt.Xexit(tls, i32(1)) + } + crt.Xsched_yield(tls) + _i += 1 + goto _25 +_28: + _i = i32(0) +_30: + if _i >= _nWorker { + goto _33 + } + crt.Xpthread_join(tls, (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))).X8, nil) + crt.Xprintf(tls, str(914), (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))).X0, (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))).X5, (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))).X6) + if ((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo)) + 40*uintptr(_i))).X7) != nil { + crt.Xprintf(tls, str(954), unsafe.Pointer((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+40*uintptr(_i))).X7)) + goto _35 + } + crt.Xprintf(tls, str(960)) +_35: + { + p := &_nErr + *p = (*p) + ((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo)) + 40*uintptr(_i))).X5) + sink1 = *p + } + { + p := &_nTest + *p = (*p) + ((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo)) + 40*uintptr(_i))).X6) + sink1 = *p + } + crt.Xfflush(tls, (*crt.XFILE)(Xstdout)) + _i += 1 + goto _30 +_33: + bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_db)) + bin.Xsqlite3_free(tls, (unsafe.Pointer)(_aInfo)) + crt.Xprintf(tls, str(962), _nErr, _nTest) + return _nErr + + _ = _wrMutex + _ = _infoTop + panic(0) +} + +// Run a SQL statements. Panic if unable. +func _run_sql(tls *crt.TLS, _p *XWorkerInfo, _zFormat *int8, args ...interface{}) { + var _rc, _nRetry int32 + var _zSql *int8 + var _pStmt unsafe.Pointer + var _ap []interface{} + _pStmt = nil + _nRetry = i32(0) + _ap = args + _zSql = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap) + _ap = nil + _check_oom(tls, (unsafe.Pointer)(_zSql)) + _rc = bin.Xsqlite3_prepare_v2(tls, (*bin.Xsqlite3)(_p.X4), _zSql, i32(-1), &_pStmt, nil) + if _rc != i32(0) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(991), _rc, bin.Xsqlite3_extended_errcode(tls, (*bin.Xsqlite3)(_p.X4)), unsafe.Pointer(bin.Xsqlite3_errmsg(tls, (*bin.Xsqlite3)(_p.X4))), unsafe.Pointer(_zSql)) + crt.Xexit(tls, i32(1)) + } + _worker_trace(tls, _p, str(1036), unsafe.Pointer(_zSql)) +_1: + if store1(&_rc, bin.Xsqlite3_step(tls, _pStmt)) == i32(101) { + goto _2 + } + if (_rc&i32(255)) != i32(5) && (_rc&i32(255)) != i32(6) { + goto _4 + } + bin.Xsqlite3_reset(tls, _pStmt) + _nRetry += 1 + if _nRetry < i32(10) { + _worker_trace(tls, _p, str(1049), _nRetry, unsafe.Pointer(_zSql)) + crt.Xsched_yield(tls) + goto _1 + } + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1067), _p.X0, unsafe.Pointer(_zSql)) + crt.Xexit(tls, i32(1)) +_4: + if _rc != i32(100) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1109), _rc, bin.Xsqlite3_extended_errcode(tls, (*bin.Xsqlite3)(_p.X4)), unsafe.Pointer(bin.Xsqlite3_errmsg(tls, (*bin.Xsqlite3)(_p.X4))), unsafe.Pointer(_zSql)) + crt.Xexit(tls, i32(1)) + } + goto _1 +_2: + bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql)) + bin.Xsqlite3_finalize(tls, _pStmt) +} + +// Report an OOM error and die if the argument is NULL +func _check_oom(tls *crt.TLS, _x unsafe.Pointer) { + if _x == nil { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1151)) + crt.Xexit(tls, i32(1)) + } +} + +// Print a trace message for a worker +func _worker_trace(tls *crt.TLS, _p *XWorkerInfo, _zFormat *int8, args ...interface{}) { + var _zMsg *int8 + var _ap []interface{} + if ((_p.X2) & uint32(i32(4))) == uint32(i32(0)) { + return + } + _ap = args + _zMsg = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap) + _check_oom(tls, (unsafe.Pointer)(_zMsg)) + _ap = nil + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1166), _p.X0, unsafe.Pointer(_zMsg)) + bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zMsg)) +} + +// Allocate memory. If the allocation fails, print an error message and +// kill the process. +func _safe_malloc(tls *crt.TLS, _sz int32) (r0 unsafe.Pointer) { + var _x unsafe.Pointer + _x = bin.Xsqlite3_malloc(tls, func() int32 { + if _sz > i32(0) { + return _sz + } + return i32(1) + }()) + _check_oom(tls, _x) + return _x +} + +// Each thread runs the following function. +func _worker_thread(tls *crt.TLS, _pArg unsafe.Pointer) (r0 unsafe.Pointer) { + var _iOuter, _i, _rc int32 + var _pStmt unsafe.Pointer + var _p *XWorkerInfo + _p = (*XWorkerInfo)(_pArg) + crt.Xprintf(tls, str(1183), _p.X0) + crt.Xfflush(tls, (*crt.XFILE)(Xstdout)) + _iOuter = i32(1) +_0: + if _iOuter > (_p.X1) { + goto _3 + } + _worker_open_connection(tls, _p, _iOuter) + _i = i32(0) +_4: + if _i >= i32(4) { + goto _7 + } + _worker_add_content(tls, _p, (_i*i32(100))+i32(1), (_i+i32(1))*i32(100), (((_p.X0)+_iOuter)%i32(3))+i32(1)) + _worker_add_content(tls, _p, (_i*i32(100))+i32(1), (_i+i32(1))*i32(100), ((((_p.X0)+_iOuter)+i32(1))%i32(3))+i32(1)) + _worker_add_content(tls, _p, (_i*i32(100))+i32(1), (_i+i32(1))*i32(100), ((((_p.X0)+_iOuter)+i32(2))%i32(3))+i32(1)) + _i += 1 + goto _4 +_7: + _pStmt = _prep_sql(tls, _p.X4, str(1202), _p.X0) + _worker_trace(tls, _p, str(1239), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt))) + _rc = bin.Xsqlite3_step(tls, _pStmt) + if _rc != i32(100) { + _worker_error(tls, _p, str(1250), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt))) + goto _9 + } + if bin.Xsqlite3_column_int(tls, _pStmt, i32(0)) != i32(400) { + _worker_error(tls, _p, str(1269), bin.Xsqlite3_column_int(tls, _pStmt, i32(0))) + } +_9: + bin.Xsqlite3_finalize(tls, _pStmt) + if (_p.X5) != 0 { + goto _3 + } + if ((_iOuter + (_p.X0)) % i32(3)) == i32(0) { + bin.Xsqlite3_db_release_memory(tls, (*bin.Xsqlite3)(_p.X4)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1 + } + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(1286)) + _run_sql(tls, _p, str(1293)) + _run_sql(tls, _p, str(1325)) + _run_sql(tls, _p, str(1357)) + _run_sql(tls, _p, str(1389)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1 + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + if _iOuter == (_p.X0) { + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(1399)) + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + } + _pStmt = _prep_sql(tls, _p.X4, str(1406), _p.X0, _p.X0, _p.X0) + _worker_trace(tls, _p, str(1239), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt))) + _i = i32(0) +_14: + if _i >= (_p.X1) { + goto _17 + } + _rc = bin.Xsqlite3_step(tls, _pStmt) + if _rc != i32(100) { + _worker_error(tls, _p, str(1250), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt))) + goto _17 + } + crt.Xsched_yield(tls) + _i += 1 + goto _14 +_17: + bin.Xsqlite3_finalize(tls, _pStmt) + if (_p.X5) != 0 { + goto _3 + } + _worker_delete_all_content(tls, _p, ((_p.X0)+_iOuter)%i32(2)) + _worker_close_connection(tls, _p) + *(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(16 /* X4 */))) = nil + _iOuter += 1 + goto _0 +_3: + _worker_close_connection(tls, _p) + crt.Xprintf(tls, str(1552), _p.X0) + crt.Xfflush(tls, (*crt.XFILE)(Xstdout)) + return nil +} + +// Open the database connection for WorkerInfo. The order in which +// the files are opened is a function of the tid value. +func _worker_open_connection(tls *crt.TLS, _p *XWorkerInfo, _iCnt int32) { + var _x, _rc int32 + var _zFile *int8 + _x = ((_p.X0) + _iCnt) % i32(6) + _zFile = bin.Xsqlite3_mprintf(tls, str(1572), int32(*(*uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)((*[3]uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_worker_open_connectionØ00aOrderØ001))+3*uintptr(_x))))) + 1*uintptr(i32(0)))))) + _check_oom(tls, (unsafe.Pointer)(_zFile)) + _worker_trace(tls, _p, str(1586), unsafe.Pointer(_zFile)) + _rc = bin.Xsqlite3_open_v2(tls, _zFile, (**bin.Xsqlite3)(unsafe.Pointer((*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p))+uintptr(16 /* X4 */))))), i32(131074), nil) + if _rc != i32(0) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1594), unsafe.Pointer(_zFile), _p.X0) + crt.Xexit(tls, i32(1)) + } + bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zFile)) + _run_sql(tls, _p, str(1634)) + bin.Xsqlite3_busy_timeout(tls, (*bin.Xsqlite3)(_p.X4), i32(10000)) + _run_sql(tls, _p, str(1662)) + _run_sql(tls, _p, str(1686), int32(*(*uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)((*[3]uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_worker_open_connectionØ00aOrderØ001))+3*uintptr(_x))))) + 1*uintptr(i32(1)))))) + _run_sql(tls, _p, str(1717), int32(*(*uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)((*[3]uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_worker_open_connectionØ00aOrderØ001))+3*uintptr(_x))))) + 1*uintptr(i32(2)))))) +} + +var _worker_open_connectionØ00aOrderØ001 [6][3]uint8 + +func init() { + _worker_open_connectionØ00aOrderØ001 = [6][3]uint8{[3]uint8{u8(1), u8(2), u8(3)}, [3]uint8{u8(1), u8(3), u8(2)}, [3]uint8{u8(2), u8(1), u8(3)}, [3]uint8{u8(2), u8(3), u8(1)}, [3]uint8{u8(3), u8(1), u8(2)}, [3]uint8{u8(3), u8(2), u8(1)}} +} + +// Create rows mn through mx in table iTab for the given worker +func _worker_add_content(tls *crt.TLS, _p *XWorkerInfo, _mn int32, _mx int32, _iTab int32) { + var _zTabDef *int8 + switch _iTab { + case i32(1): + goto _1 + case i32(2): + goto _2 + case i32(3): + goto _3 + default: + goto _4 + } + +_1: + _zTabDef = str(1748) + goto _4 +_2: + _zTabDef = str(1765) + goto _4 +_3: + _zTabDef = str(1782) + goto _4 +_4: + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(1799), _mn, _mx, unsafe.Pointer(_zTabDef), _p.X0) + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1 +} + +// Prepare a single SQL query +func _prep_sql(tls *crt.TLS, _db unsafe.Pointer, _zFormat *int8, args ...interface{}) (r0 unsafe.Pointer) { + var _rc int32 + var _zSql *int8 + var _pStmt unsafe.Pointer + var _ap []interface{} + _pStmt = nil + _ap = args + _zSql = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap) + _ap = nil + _check_oom(tls, (unsafe.Pointer)(_zSql)) + _rc = bin.Xsqlite3_prepare_v2(tls, (*bin.Xsqlite3)(_db), _zSql, i32(-1), &_pStmt, nil) + if _rc != i32(0) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(991), _rc, bin.Xsqlite3_extended_errcode(tls, (*bin.Xsqlite3)(_db)), unsafe.Pointer(bin.Xsqlite3_errmsg(tls, (*bin.Xsqlite3)(_db))), unsafe.Pointer(_zSql)) + crt.Xexit(tls, i32(1)) + } + bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql)) + return _pStmt +} + +// Set an error message on a worker +func _worker_error(tls *crt.TLS, _p *XWorkerInfo, _zFormat *int8, args ...interface{}) { + var _ap []interface{} + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(20 /* X5 */))) += 1 + bin.Xsqlite3_free(tls, (unsafe.Pointer)(_p.X7)) + _ap = args + *(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(28 /* X7 */))) = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap) + _ap = nil +} + +// Delete all content in the three databases associated with a +// single thread. Make this happen all in a single transaction if +// inTrans is true, or separately for each database if inTrans is +// false. +func _worker_delete_all_content(tls *crt.TLS, _p *XWorkerInfo, _inTrans int32) { + if _inTrans != 0 { + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(1947)) + _run_sql(tls, _p, str(1953), _p.X0) + _run_sql(tls, _p, str(1981), _p.X0) + _run_sql(tls, _p, str(2009), _p.X0) + _run_sql(tls, _p, str(2037)) + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1 + goto _1 + } + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(1953), _p.X0) + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1 + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(1981), _p.X0) + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1 + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(2009), _p.X0) + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X6 */))) += 1 +_1: +} + +// Close the worker database connection +func _worker_close_connection(tls *crt.TLS, _p *XWorkerInfo) { + if (_p.X4) != nil { + _worker_trace(tls, _p, str(2044)) + bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_p.X4)) + *(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(16 /* X4 */))) = nil + } +} + +func bool2int(b bool) int32 { + if b { + return 1 + } + return 0 +} +func bug20530(interface{}) {} //TODO remove when https://github.com/golang/go/issues/20530 is fixed. +func i16(n int16) int16 { return n } +func i32(n int32) int32 { return n } +func i64(n int64) int64 { return n } +func i8(n int8) int8 { return n } +func init() { nzf32 *= -1; nzf64 *= -1 } +func u16(n uint16) uint16 { return n } +func u32(n uint32) uint32 { return n } +func u64(n uint64) uint64 { return n } +func u8(n byte) byte { return n } + +var inf = math.Inf(1) +var nzf32 float32 // -0.0 +var nzf64 float64 // -0.0 +var sink1 int32 //TODO report GC bug +var sink0 uint32 //TODO report GC bug +func store1(p *int32, v int32) int32 { *p = v; return v } + +type XWorkerInfo struct { + X0 int32 + X1 int32 + X2 uint32 + X3 unsafe.Pointer + X4 unsafe.Pointer + X5 int32 + X6 int32 + X7 *int8 + X8 uint32 + X9 unsafe.Pointer +} // t2 struct{int32,int32,uint32,*struct{},*struct{},int32,int32,*int8,uint32,*struct{}} +func str(n int) *int8 { return (*int8)(unsafe.Pointer(&strTab[n])) } +func wstr(n int) *int32 { return (*int32)(unsafe.Pointer(&strTab[n])) } + +var strTab = []byte("-multithread\x00-serialized\x00-wal\x00-trace\x00unknown command-line option: %s\x0a\x00minimum of 2 threads\x0a\x00extra command-line argument: \"%s\"\x0a\x00usage: %s ?OPTIONS? N\x0aN is the number of threads and must be at least 2.\x0aOptions:\x0a --serialized\x0a --multithread\x0a --wal\x0a --trace\x0a\x00requires a threadsafe build of SQLite\x0a\x00tt4-test1.db\x00tt4-test2.db\x00tt4-test3.db\x00Unable to open test database: tt4-test2.db\x0a\x00PRAGMA journal_mode=WAL\x00PRAGMA synchronous=OFF\x00CREATE TABLE IF NOT EXISTS t1(tid INTEGER, sp, a, b, c)\x00CREATE INDEX t1tid ON t1(tid)\x00CREATE INDEX t1ab ON t1(a,b)\x00ATTACH 'tt4-test2.db' AS 'test2'\x00CREATE TABLE IF NOT EXISTS test2.t2(tid INTEGER, sp, d, e, f)\x00CREATE INDEX test2.t2tid ON t2(tid)\x00CREATE INDEX test2.t2de ON t2(d,e)\x00ATTACH 'tt4-test3.db' AS 'test3'\x00CREATE TABLE IF NOT EXISTS test3.t3(tid INTEGER, sp, x, y, z)\x00CREATE INDEX test3.t3tid ON t3(tid)\x00CREATE INDEX test3.t3xy ON t3(x,y)\x00thread creation failed for thread %d\x0a\x00Joined thread %d: %d errors in %d tests\x00: %s\x0a\x00\x0a\x00Total %d errors in %d tests\x0a\x00SQL error (%d,%d): %s\x0aWhile preparing: [%s]\x0a\x00running [%s]\x00retry %d for [%s]\x00Deadlock in thread %d while running [%s]\x0a\x00SQL error (%d,%d): %s\x0aWhile running [%s]\x0a\x00out of memory\x0a\x00TRACE(%02d): %s\x0a\x00worker %d startup\x0a\x00SELECT count(a) FROM t1 WHERE tid=%d\x00query [%s]\x00Failed to step: %s\x00Wrong result: %d\x00BEGIN;\x00UPDATE t1 SET c=NULL WHERE a=55\x00UPDATE t2 SET f=NULL WHERE d=42\x00UPDATE t3 SET z=NULL WHERE x=31\x00ROLLBACK;\x00VACUUM\x00SELECT t1.rowid, t2.rowid, t3.rowid FROM t1, t2, t3 WHERE t1.tid=%d AND t2.tid=%d AND t3.tid=%d AND t1.a<>t2.d AND t2.d<>t3.x ORDER BY 1, 2, 3\x00worker %d finished\x0a\x00tt4-test%d.db\x00open %s\x00sqlite_open_v2(%s) failed on thread %d\x0a\x00PRAGMA read_uncommitted=ON;\x00PRAGMA synchronous=OFF;\x00ATTACH 'tt4-test%d.db' AS aux1\x00ATTACH 'tt4-test%d.db' AS aux2\x00t1(tid,sp,a,b,c)\x00t2(tid,sp,d,e,f)\x00t3(tid,sp,x,y,z)\x00WITH RECURSIVE\x0a c(i) AS (VALUES(%d) UNION ALL SELECT i+1 FROM c WHERE i<%d)\x0aINSERT INTO %s SELECT %d, zeroblob(3000), i, printf('%%d',i), i FROM c;\x00BEGIN\x00DELETE FROM t1 WHERE tid=%d\x00DELETE FROM t2 WHERE tid=%d\x00DELETE FROM t3 WHERE tid=%d\x00COMMIT\x00close\x00") diff --git a/internal/threadtest4/threadtest4_linux_amd64.go b/internal/threadtest4/threadtest4_linux_amd64.go new file mode 100644 index 0000000..4fd935b --- /dev/null +++ b/internal/threadtest4/threadtest4_linux_amd64.go @@ -0,0 +1,600 @@ +// Code generated by ccgo. DO NOT EDIT. + +// threadtest4.c + +// 2014-12-11 +// +// The author disclaims copyright to this source code. In place of +// a legal notice, here is a blessing: +// +// May you do good and not evil. +// May you find forgiveness for yourself and forgive others. +// May you share freely, never taking more than you give. +// +// ************************************************************************* +// This file implements a simple standalone program used to stress the +// SQLite library when accessing the same set of databases simultaneously +// from multiple threads in shared-cache mode. +// +// This test program runs on unix-like systems only. It uses pthreads. +// To compile: +// +// gcc -g -Wall -I. threadtest4.c sqlite3.c -ldl -lpthread +// +// To run: +// +// ./a.out 10 +// +// The argument is the number of threads. There are also options, such +// as -wal and -multithread and -serialized. +// +// Consider also compiling with clang instead of gcc and adding the +// -fsanitize=thread option. + +package main + +import ( + "math" + "os" + "unsafe" + + "github.com/cznic/crt" + "github.com/cznic/sqlite/internal/bin" +) + +var argv []*int8 + +func main() { + for _, v := range os.Args { + argv = append(argv, (*int8)(crt.CString(v))) + } + argv = append(argv, nil) + X_start(crt.NewTLS(), int32(len(os.Args)), &argv[0]) +} + +func X_start(tls *crt.TLS, _argc int32, _argv **int8) { + crt.X__register_stdfiles(tls, Xstdin, Xstdout, Xstderr) + crt.X__builtin_exit(tls, Xmain(tls, _argc, _argv)) +} + +var Xstdin unsafe.Pointer + +func init() { + Xstdin = unsafe.Pointer(&X__stdfiles) +} + +var X__stdfiles [3]unsafe.Pointer + +var Xstdout unsafe.Pointer + +func init() { + Xstdout = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 8) +} + +var Xstderr unsafe.Pointer + +func init() { + Xstderr = (unsafe.Pointer)(uintptr(unsafe.Pointer(&X__stdfiles)) + 16) +} + +func Xmain(tls *crt.TLS, _argc int32, _argv **int8) (r0 int32) { + var _nWorker, _i, _nErr, _nTest, _rc int32 + var _wkrFlags uint32 + var _1_z *int8 + var _db unsafe.Pointer + var _wrMutex crt.Xpthread_mutex_t + var _infoTop XWorkerInfo + var _aInfo, _p *XWorkerInfo + r0 = i32(0) + _nWorker = i32(0) + _wkrFlags = u32(0) + _nErr = i32(0) + _nTest = i32(0) + _db = nil + bin.Xsqlite3_config(tls, i32(2)) + _i = i32(1) +_0: + if _i >= _argc { + goto _3 + } + _1_z = *(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 8*uintptr(_i))) + if int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(0))))) != i32(45) { + goto _4 + } + if (int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(1))))) == i32(45)) && (int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(2))))) != i32(0)) { + *(*uintptr)(unsafe.Pointer(&_1_z)) += uintptr(1) + } + if crt.Xstrcmp(tls, _1_z, str(0)) == i32(0) { + bin.Xsqlite3_config(tls, i32(2)) + { + p := &_wkrFlags + *p = (*p) & uint32(i32(-2)) + sink0 = *p + } + goto _8 + } + if crt.Xstrcmp(tls, _1_z, str(13)) == i32(0) { + bin.Xsqlite3_config(tls, i32(3)) + { + p := &_wkrFlags + *p = (*p) | uint32(i32(1)) + sink0 = *p + } + goto _10 + } + if crt.Xstrcmp(tls, _1_z, str(25)) == i32(0) { + { + p := &_wkrFlags + *p = (*p) | uint32(i32(2)) + sink0 = *p + } + goto _12 + } + if crt.Xstrcmp(tls, _1_z, str(30)) == i32(0) { + { + p := &_wkrFlags + *p = (*p) | uint32(i32(4)) + sink0 = *p + } + goto _14 + } + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(37), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 8*uintptr(_i))))) + crt.Xexit(tls, i32(1)) +_14: +_12: +_10: +_8: + goto _15 +_4: + if int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(0))))) < i32(49) || int32(*(*int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_1_z)) + 1*uintptr(i32(0))))) > i32(57) || _nWorker != i32(0) { + goto _18 + } + _nWorker = crt.Xatoi(tls, _1_z) + if _nWorker < i32(2) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(70)) + crt.Xexit(tls, i32(1)) + } + goto _20 +_18: + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(92), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 8*uintptr(_i))))) + crt.Xexit(tls, i32(1)) +_20: +_15: + _i += 1 + goto _0 +_3: + if _nWorker == i32(0) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(127), unsafe.Pointer(*(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_argv)) + 8*uintptr(i32(0)))))) + crt.Xexit(tls, i32(1)) + } + if bin.Xsqlite3_threadsafe(tls) == 0 { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(260)) + crt.Xexit(tls, i32(1)) + } + bin.Xsqlite3_initialize(tls) + bin.Xsqlite3_enable_shared_cache(tls, i32(1)) + crt.Xpthread_mutex_init(tls, &_wrMutex, nil) + crt.Xunlink(tls, str(299)) + crt.Xunlink(tls, str(312)) + crt.Xunlink(tls, str(325)) + _rc = bin.Xsqlite3_open(tls, str(299), (**bin.Xsqlite3)(unsafe.Pointer(&_db))) + if _rc != i32(0) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(338)) + crt.Xexit(tls, i32(1)) + } + crt.Xmemset(tls, (unsafe.Pointer)(&_infoTop), i32(0), u64(64)) + *(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_infoTop)) + uintptr(24 /* X4 */))) = _db + *(*uint32)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_infoTop)) + uintptr(8 /* X2 */))) = _wkrFlags + _p = &_infoTop + if (_wkrFlags & uint32(i32(2))) != 0 { + _run_sql(tls, _p, str(382)) + } + _run_sql(tls, _p, str(406)) + _run_sql(tls, _p, str(429)) + _run_sql(tls, _p, str(485)) + _run_sql(tls, _p, str(515)) + _run_sql(tls, _p, str(544)) + _run_sql(tls, _p, str(577)) + _run_sql(tls, _p, str(639)) + _run_sql(tls, _p, str(675)) + _run_sql(tls, _p, str(710)) + _run_sql(tls, _p, str(743)) + _run_sql(tls, _p, str(805)) + _run_sql(tls, _p, str(841)) + _aInfo = (*XWorkerInfo)(_safe_malloc(tls, int32(u64(64)*uint64(_nWorker)))) + crt.Xmemset(tls, (unsafe.Pointer)(_aInfo), i32(0), u64(64)*uint64(_nWorker)) + _i = i32(0) +_25: + if _i >= _nWorker { + goto _28 + } + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))))) + uintptr(0 /* X0 */))) = _i + i32(1) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))))) + uintptr(4 /* X1 */))) = _nWorker + *(*uint32)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))))) + uintptr(8 /* X2 */))) = _wkrFlags + *(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))))) + uintptr(16 /* X3 */))) = _db + *(**crt.Xpthread_mutex_t)(unsafe.Pointer((*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))))) + uintptr(56 /* X9 */))))) = &_wrMutex + _rc = crt.Xpthread_create(tls, (*uint64)(unsafe.Pointer(uintptr((unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i)))))+uintptr(48 /* X8 */))), nil, _worker_thread, (unsafe.Pointer)((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))))) + if _rc != i32(0) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(876), _i+i32(1)) + crt.Xexit(tls, i32(1)) + } + crt.Xsched_yield(tls) + _i += 1 + goto _25 +_28: + _i = i32(0) +_30: + if _i >= _nWorker { + goto _33 + } + crt.Xpthread_join(tls, (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))).X8, nil) + crt.Xprintf(tls, str(914), (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))).X0, (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))).X5, (*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))).X6) + if ((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo)) + 64*uintptr(_i))).X7) != nil { + crt.Xprintf(tls, str(954), unsafe.Pointer((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo))+64*uintptr(_i))).X7)) + goto _35 + } + crt.Xprintf(tls, str(960)) +_35: + { + p := &_nErr + *p = (*p) + ((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo)) + 64*uintptr(_i))).X5) + sink1 = *p + } + { + p := &_nTest + *p = (*p) + ((*XWorkerInfo)(unsafe.Pointer(uintptr((unsafe.Pointer)(_aInfo)) + 64*uintptr(_i))).X6) + sink1 = *p + } + crt.Xfflush(tls, (*crt.XFILE)(Xstdout)) + _i += 1 + goto _30 +_33: + bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_db)) + bin.Xsqlite3_free(tls, (unsafe.Pointer)(_aInfo)) + crt.Xprintf(tls, str(962), _nErr, _nTest) + return _nErr + + _ = _wrMutex + _ = _infoTop + panic(0) +} + +// Run a SQL statements. Panic if unable. +func _run_sql(tls *crt.TLS, _p *XWorkerInfo, _zFormat *int8, args ...interface{}) { + var _rc, _nRetry int32 + var _zSql *int8 + var _pStmt unsafe.Pointer + var _ap []interface{} + _pStmt = nil + _nRetry = i32(0) + _ap = args + _zSql = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap) + _ap = nil + _check_oom(tls, (unsafe.Pointer)(_zSql)) + _rc = bin.Xsqlite3_prepare_v2(tls, (*bin.Xsqlite3)(_p.X4), _zSql, i32(-1), &_pStmt, nil) + if _rc != i32(0) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(991), _rc, bin.Xsqlite3_extended_errcode(tls, (*bin.Xsqlite3)(_p.X4)), unsafe.Pointer(bin.Xsqlite3_errmsg(tls, (*bin.Xsqlite3)(_p.X4))), unsafe.Pointer(_zSql)) + crt.Xexit(tls, i32(1)) + } + _worker_trace(tls, _p, str(1036), unsafe.Pointer(_zSql)) +_1: + if store1(&_rc, bin.Xsqlite3_step(tls, _pStmt)) == i32(101) { + goto _2 + } + if (_rc&i32(255)) != i32(5) && (_rc&i32(255)) != i32(6) { + goto _4 + } + bin.Xsqlite3_reset(tls, _pStmt) + _nRetry += 1 + if _nRetry < i32(10) { + _worker_trace(tls, _p, str(1049), _nRetry, unsafe.Pointer(_zSql)) + crt.Xsched_yield(tls) + goto _1 + } + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1067), _p.X0, unsafe.Pointer(_zSql)) + crt.Xexit(tls, i32(1)) +_4: + if _rc != i32(100) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1109), _rc, bin.Xsqlite3_extended_errcode(tls, (*bin.Xsqlite3)(_p.X4)), unsafe.Pointer(bin.Xsqlite3_errmsg(tls, (*bin.Xsqlite3)(_p.X4))), unsafe.Pointer(_zSql)) + crt.Xexit(tls, i32(1)) + } + goto _1 +_2: + bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql)) + bin.Xsqlite3_finalize(tls, _pStmt) +} + +// Report an OOM error and die if the argument is NULL +func _check_oom(tls *crt.TLS, _x unsafe.Pointer) { + if _x == nil { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1151)) + crt.Xexit(tls, i32(1)) + } +} + +// Print a trace message for a worker +func _worker_trace(tls *crt.TLS, _p *XWorkerInfo, _zFormat *int8, args ...interface{}) { + var _zMsg *int8 + var _ap []interface{} + if ((_p.X2) & uint32(i32(4))) == uint32(i32(0)) { + return + } + _ap = args + _zMsg = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap) + _check_oom(tls, (unsafe.Pointer)(_zMsg)) + _ap = nil + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1166), _p.X0, unsafe.Pointer(_zMsg)) + bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zMsg)) +} + +// Allocate memory. If the allocation fails, print an error message and +// kill the process. +func _safe_malloc(tls *crt.TLS, _sz int32) (r0 unsafe.Pointer) { + var _x unsafe.Pointer + _x = bin.Xsqlite3_malloc(tls, func() int32 { + if _sz > i32(0) { + return _sz + } + return i32(1) + }()) + _check_oom(tls, _x) + return _x +} + +// Each thread runs the following function. +func _worker_thread(tls *crt.TLS, _pArg unsafe.Pointer) (r0 unsafe.Pointer) { + var _iOuter, _i, _rc int32 + var _pStmt unsafe.Pointer + var _p *XWorkerInfo + _p = (*XWorkerInfo)(_pArg) + crt.Xprintf(tls, str(1183), _p.X0) + crt.Xfflush(tls, (*crt.XFILE)(Xstdout)) + _iOuter = i32(1) +_0: + if _iOuter > (_p.X1) { + goto _3 + } + _worker_open_connection(tls, _p, _iOuter) + _i = i32(0) +_4: + if _i >= i32(4) { + goto _7 + } + _worker_add_content(tls, _p, (_i*i32(100))+i32(1), (_i+i32(1))*i32(100), (((_p.X0)+_iOuter)%i32(3))+i32(1)) + _worker_add_content(tls, _p, (_i*i32(100))+i32(1), (_i+i32(1))*i32(100), ((((_p.X0)+_iOuter)+i32(1))%i32(3))+i32(1)) + _worker_add_content(tls, _p, (_i*i32(100))+i32(1), (_i+i32(1))*i32(100), ((((_p.X0)+_iOuter)+i32(2))%i32(3))+i32(1)) + _i += 1 + goto _4 +_7: + _pStmt = _prep_sql(tls, _p.X4, str(1202), _p.X0) + _worker_trace(tls, _p, str(1239), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt))) + _rc = bin.Xsqlite3_step(tls, _pStmt) + if _rc != i32(100) { + _worker_error(tls, _p, str(1250), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt))) + goto _9 + } + if bin.Xsqlite3_column_int(tls, _pStmt, i32(0)) != i32(400) { + _worker_error(tls, _p, str(1269), bin.Xsqlite3_column_int(tls, _pStmt, i32(0))) + } +_9: + bin.Xsqlite3_finalize(tls, _pStmt) + if (_p.X5) != 0 { + goto _3 + } + if ((_iOuter + (_p.X0)) % i32(3)) == i32(0) { + bin.Xsqlite3_db_release_memory(tls, (*bin.Xsqlite3)(_p.X4)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1 + } + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(1286)) + _run_sql(tls, _p, str(1293)) + _run_sql(tls, _p, str(1325)) + _run_sql(tls, _p, str(1357)) + _run_sql(tls, _p, str(1389)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1 + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + if _iOuter == (_p.X0) { + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(1399)) + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + } + _pStmt = _prep_sql(tls, _p.X4, str(1406), _p.X0, _p.X0, _p.X0) + _worker_trace(tls, _p, str(1239), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt))) + _i = i32(0) +_14: + if _i >= (_p.X1) { + goto _17 + } + _rc = bin.Xsqlite3_step(tls, _pStmt) + if _rc != i32(100) { + _worker_error(tls, _p, str(1250), unsafe.Pointer(bin.Xsqlite3_sql(tls, _pStmt))) + goto _17 + } + crt.Xsched_yield(tls) + _i += 1 + goto _14 +_17: + bin.Xsqlite3_finalize(tls, _pStmt) + if (_p.X5) != 0 { + goto _3 + } + _worker_delete_all_content(tls, _p, ((_p.X0)+_iOuter)%i32(2)) + _worker_close_connection(tls, _p) + *(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X4 */))) = nil + _iOuter += 1 + goto _0 +_3: + _worker_close_connection(tls, _p) + crt.Xprintf(tls, str(1552), _p.X0) + crt.Xfflush(tls, (*crt.XFILE)(Xstdout)) + return nil +} + +// Open the database connection for WorkerInfo. The order in which +// the files are opened is a function of the tid value. +func _worker_open_connection(tls *crt.TLS, _p *XWorkerInfo, _iCnt int32) { + var _x, _rc int32 + var _zFile *int8 + _x = ((_p.X0) + _iCnt) % i32(6) + _zFile = bin.Xsqlite3_mprintf(tls, str(1572), int32(*(*uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)((*[3]uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_worker_open_connectionØ00aOrderØ001))+3*uintptr(_x))))) + 1*uintptr(i32(0)))))) + _check_oom(tls, (unsafe.Pointer)(_zFile)) + _worker_trace(tls, _p, str(1586), unsafe.Pointer(_zFile)) + _rc = bin.Xsqlite3_open_v2(tls, _zFile, (**bin.Xsqlite3)(unsafe.Pointer((*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p))+uintptr(24 /* X4 */))))), i32(131074), nil) + if _rc != i32(0) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(1594), unsafe.Pointer(_zFile), _p.X0) + crt.Xexit(tls, i32(1)) + } + bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zFile)) + _run_sql(tls, _p, str(1634)) + bin.Xsqlite3_busy_timeout(tls, (*bin.Xsqlite3)(_p.X4), i32(10000)) + _run_sql(tls, _p, str(1662)) + _run_sql(tls, _p, str(1686), int32(*(*uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)((*[3]uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_worker_open_connectionØ00aOrderØ001))+3*uintptr(_x))))) + 1*uintptr(i32(1)))))) + _run_sql(tls, _p, str(1717), int32(*(*uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)((*[3]uint8)(unsafe.Pointer(uintptr((unsafe.Pointer)(&_worker_open_connectionØ00aOrderØ001))+3*uintptr(_x))))) + 1*uintptr(i32(2)))))) +} + +var _worker_open_connectionØ00aOrderØ001 [6][3]uint8 + +func init() { + _worker_open_connectionØ00aOrderØ001 = [6][3]uint8{[3]uint8{u8(1), u8(2), u8(3)}, [3]uint8{u8(1), u8(3), u8(2)}, [3]uint8{u8(2), u8(1), u8(3)}, [3]uint8{u8(2), u8(3), u8(1)}, [3]uint8{u8(3), u8(1), u8(2)}, [3]uint8{u8(3), u8(2), u8(1)}} +} + +// Create rows mn through mx in table iTab for the given worker +func _worker_add_content(tls *crt.TLS, _p *XWorkerInfo, _mn int32, _mx int32, _iTab int32) { + var _zTabDef *int8 + switch _iTab { + case i32(1): + goto _1 + case i32(2): + goto _2 + case i32(3): + goto _3 + default: + goto _4 + } + +_1: + _zTabDef = str(1748) + goto _4 +_2: + _zTabDef = str(1765) + goto _4 +_3: + _zTabDef = str(1782) + goto _4 +_4: + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(1799), _mn, _mx, unsafe.Pointer(_zTabDef), _p.X0) + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1 +} + +// Prepare a single SQL query +func _prep_sql(tls *crt.TLS, _db unsafe.Pointer, _zFormat *int8, args ...interface{}) (r0 unsafe.Pointer) { + var _rc int32 + var _zSql *int8 + var _pStmt unsafe.Pointer + var _ap []interface{} + _pStmt = nil + _ap = args + _zSql = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap) + _ap = nil + _check_oom(tls, (unsafe.Pointer)(_zSql)) + _rc = bin.Xsqlite3_prepare_v2(tls, (*bin.Xsqlite3)(_db), _zSql, i32(-1), &_pStmt, nil) + if _rc != i32(0) { + crt.Xfprintf(tls, (*crt.XFILE)(Xstderr), str(991), _rc, bin.Xsqlite3_extended_errcode(tls, (*bin.Xsqlite3)(_db)), unsafe.Pointer(bin.Xsqlite3_errmsg(tls, (*bin.Xsqlite3)(_db))), unsafe.Pointer(_zSql)) + crt.Xexit(tls, i32(1)) + } + bin.Xsqlite3_free(tls, (unsafe.Pointer)(_zSql)) + return _pStmt +} + +// Set an error message on a worker +func _worker_error(tls *crt.TLS, _p *XWorkerInfo, _zFormat *int8, args ...interface{}) { + var _ap []interface{} + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(32 /* X5 */))) += 1 + bin.Xsqlite3_free(tls, (unsafe.Pointer)(_p.X7)) + _ap = args + *(**int8)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(40 /* X7 */))) = bin.Xsqlite3_vmprintf(tls, _zFormat, _ap) + _ap = nil +} + +// Delete all content in the three databases associated with a +// single thread. Make this happen all in a single transaction if +// inTrans is true, or separately for each database if inTrans is +// false. +func _worker_delete_all_content(tls *crt.TLS, _p *XWorkerInfo, _inTrans int32) { + if _inTrans != 0 { + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(1947)) + _run_sql(tls, _p, str(1953), _p.X0) + _run_sql(tls, _p, str(1981), _p.X0) + _run_sql(tls, _p, str(2009), _p.X0) + _run_sql(tls, _p, str(2037)) + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1 + goto _1 + } + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(1953), _p.X0) + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1 + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(1981), _p.X0) + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1 + crt.Xpthread_mutex_lock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + _run_sql(tls, _p, str(2009), _p.X0) + crt.Xpthread_mutex_unlock(tls, (*crt.Xpthread_mutex_t)(_p.X9)) + *(*int32)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(36 /* X6 */))) += 1 +_1: +} + +// Close the worker database connection +func _worker_close_connection(tls *crt.TLS, _p *XWorkerInfo) { + if (_p.X4) != nil { + _worker_trace(tls, _p, str(2044)) + bin.Xsqlite3_close(tls, (*bin.Xsqlite3)(_p.X4)) + *(*unsafe.Pointer)(unsafe.Pointer(uintptr((unsafe.Pointer)(_p)) + uintptr(24 /* X4 */))) = nil + } +} + +func bool2int(b bool) int32 { + if b { + return 1 + } + return 0 +} +func bug20530(interface{}) {} //TODO remove when https://github.com/golang/go/issues/20530 is fixed. +func i16(n int16) int16 { return n } +func i32(n int32) int32 { return n } +func i64(n int64) int64 { return n } +func i8(n int8) int8 { return n } +func init() { nzf32 *= -1; nzf64 *= -1 } +func u16(n uint16) uint16 { return n } +func u32(n uint32) uint32 { return n } +func u64(n uint64) uint64 { return n } +func u8(n byte) byte { return n } + +var inf = math.Inf(1) +var nzf32 float32 // -0.0 +var nzf64 float64 // -0.0 +var sink1 int32 //TODO report GC bug +var sink0 uint32 //TODO report GC bug +func store1(p *int32, v int32) int32 { *p = v; return v } + +type XWorkerInfo struct { + X0 int32 + X1 int32 + X2 uint32 + X3 unsafe.Pointer + X4 unsafe.Pointer + X5 int32 + X6 int32 + X7 *int8 + X8 uint64 + X9 unsafe.Pointer +} // t2 struct{int32,int32,uint32,*struct{},*struct{},int32,int32,*int8,uint64,*struct{}} +func str(n int) *int8 { return (*int8)(unsafe.Pointer(&strTab[n])) } +func wstr(n int) *int32 { return (*int32)(unsafe.Pointer(&strTab[n])) } + +var strTab = []byte("-multithread\x00-serialized\x00-wal\x00-trace\x00unknown command-line option: %s\x0a\x00minimum of 2 threads\x0a\x00extra command-line argument: \"%s\"\x0a\x00usage: %s ?OPTIONS? N\x0aN is the number of threads and must be at least 2.\x0aOptions:\x0a --serialized\x0a --multithread\x0a --wal\x0a --trace\x0a\x00requires a threadsafe build of SQLite\x0a\x00tt4-test1.db\x00tt4-test2.db\x00tt4-test3.db\x00Unable to open test database: tt4-test2.db\x0a\x00PRAGMA journal_mode=WAL\x00PRAGMA synchronous=OFF\x00CREATE TABLE IF NOT EXISTS t1(tid INTEGER, sp, a, b, c)\x00CREATE INDEX t1tid ON t1(tid)\x00CREATE INDEX t1ab ON t1(a,b)\x00ATTACH 'tt4-test2.db' AS 'test2'\x00CREATE TABLE IF NOT EXISTS test2.t2(tid INTEGER, sp, d, e, f)\x00CREATE INDEX test2.t2tid ON t2(tid)\x00CREATE INDEX test2.t2de ON t2(d,e)\x00ATTACH 'tt4-test3.db' AS 'test3'\x00CREATE TABLE IF NOT EXISTS test3.t3(tid INTEGER, sp, x, y, z)\x00CREATE INDEX test3.t3tid ON t3(tid)\x00CREATE INDEX test3.t3xy ON t3(x,y)\x00thread creation failed for thread %d\x0a\x00Joined thread %d: %d errors in %d tests\x00: %s\x0a\x00\x0a\x00Total %d errors in %d tests\x0a\x00SQL error (%d,%d): %s\x0aWhile preparing: [%s]\x0a\x00running [%s]\x00retry %d for [%s]\x00Deadlock in thread %d while running [%s]\x0a\x00SQL error (%d,%d): %s\x0aWhile running [%s]\x0a\x00out of memory\x0a\x00TRACE(%02d): %s\x0a\x00worker %d startup\x0a\x00SELECT count(a) FROM t1 WHERE tid=%d\x00query [%s]\x00Failed to step: %s\x00Wrong result: %d\x00BEGIN;\x00UPDATE t1 SET c=NULL WHERE a=55\x00UPDATE t2 SET f=NULL WHERE d=42\x00UPDATE t3 SET z=NULL WHERE x=31\x00ROLLBACK;\x00VACUUM\x00SELECT t1.rowid, t2.rowid, t3.rowid FROM t1, t2, t3 WHERE t1.tid=%d AND t2.tid=%d AND t3.tid=%d AND t1.a<>t2.d AND t2.d<>t3.x ORDER BY 1, 2, 3\x00worker %d finished\x0a\x00tt4-test%d.db\x00open %s\x00sqlite_open_v2(%s) failed on thread %d\x0a\x00PRAGMA read_uncommitted=ON;\x00PRAGMA synchronous=OFF;\x00ATTACH 'tt4-test%d.db' AS aux1\x00ATTACH 'tt4-test%d.db' AS aux2\x00t1(tid,sp,a,b,c)\x00t2(tid,sp,d,e,f)\x00t3(tid,sp,x,y,z)\x00WITH RECURSIVE\x0a c(i) AS (VALUES(%d) UNION ALL SELECT i+1 FROM c WHERE i<%d)\x0aINSERT INTO %s SELECT %d, zeroblob(3000), i, printf('%%d',i), i FROM c;\x00BEGIN\x00DELETE FROM t1 WHERE tid=%d\x00DELETE FROM t2 WHERE tid=%d\x00DELETE FROM t3 WHERE tid=%d\x00COMMIT\x00close\x00") |