Do not use fixed heap on Linux. Updates #12.

modified:   all_test.go
	modified:   generator.go
	modified:   internal/bin/bin_linux_386.go
	modified:   internal/bin/bin_linux_amd64.go
	modified:   main.c
	modified:   sqlite.go
	modified:   sqlite_go18.go
This commit is contained in:
Jan Mercl
2017-06-13 15:18:34 +02:00
parent ec1aabd88a
commit 11216f7304
7 changed files with 17134 additions and 19088 deletions

View File

@@ -312,3 +312,39 @@ func TestIssue11(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
} }
// https://github.com/cznic/sqlite/issues/12
func TestMemDB(t *testing.T) {
// Verify we can create out-of-the heap memory DB instance.
db, err := sql.Open(driverName, "file::memory:")
if err != nil {
t.Fatal(err)
}
defer func() {
db.Close()
}()
v := strings.Repeat("a", 1024)
if _, err := db.Exec(`
create table t(s string);
begin;
`); err != nil {
t.Fatal(err)
}
s, err := db.Prepare("insert into t values(?)")
if err != nil {
t.Fatal(err)
}
// Heap used to be fixed at 32MB.
for i := 0; i < (64<<20)/len(v); i++ {
if _, err := s.Exec(v); err != nil {
t.Fatalf("%v * %v= %v: %v", i, len(v), i*len(v), err)
}
}
if _, err := db.Exec(`commit;`); err != nil {
t.Fatal(err)
}
}

View File

@@ -61,33 +61,16 @@ import (
"unsafe" "unsafe"
"github.com/cznic/crt" "github.com/cznic/crt"
"github.com/edsrzf/mmap-go"
) )
const minAlloc = 2<<5 var inf = math.Inf(1)
var (
inf = math.Inf(1)
)
func ftrace(s string, args ...interface{}) { func ftrace(s string, args ...interface{}) {
_, fn, fl, _ := runtime.Caller(1) _, fn, fl, _ := runtime.Caller(1)
fmt.Fprintf(os.Stderr, "# %%s:%%d: %%v\n", path.Base(fn), fl, fmt.Sprintf(s, args...)) fmt.Fprintf(os.Stderr, "# %%s:%%d: %%v\n", path.Base(fn), fl, fmt.Sprintf(s, args...))
os.Stderr.Sync() os.Stderr.Sync()
} }
func Init(heapSize, heapReserve int) int {
heap, err := mmap.MapRegion(nil, heapSize+heapReserve, mmap.RDWR, mmap.ANON, 0)
if err != nil {
panic(err)
}
tls := crt.NewTLS()
crt.RegisterHeap(unsafe.Pointer(&heap[0]), int64(heapSize+heapReserve))
crt.X__register_stdfiles(tls, Xstdin, Xstdout, Xstderr)
return int(Xinit(tls, int32(heapSize)))
}
` `
) )
@@ -265,11 +248,13 @@ func main() {
asta, src := build( asta, src := build(
` `
#define HAVE_MALLOC_H 1
#define HAVE_MALLOC_USABLE_SIZE 1
#define HAVE_USLEEP 1 #define HAVE_USLEEP 1
#define SQLITE_DEBUG 1 #define SQLITE_DEBUG 1
#define SQLITE_ENABLE_API_ARMOR 1 #define SQLITE_ENABLE_API_ARMOR 1
#define SQLITE_ENABLE_MEMSYS5 1
#define SQLITE_USE_URI 1 #define SQLITE_USE_URI 1
#define SQLITE_WITHOUT_MSIZE 1
`, `,
[][]string{ [][]string{
{"main.c"}, {"main.c"},

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

27
main.c
View File

@@ -1,36 +1,13 @@
// Copyright 2017 The Sqlite Authors. All rights reserved. // Copyright 2017 The Sqlite Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// SQLite Is Public Domain
// +build ignore // +build ignore
#define minAlloc (2<<5)
#include <sqlite3.h> #include <sqlite3.h>
#include <stdlib.h>
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
init(-1); // Prevent the linker from optimizing out everything.
} int (*f) (int, ...) = sqlite3_config;
int init(int heapSize)
{
void *heap = malloc(heapSize);
if (heap == 0) {
return 1;
}
int rc = sqlite3_config(SQLITE_CONFIG_HEAP, heap, heapSize, minAlloc);
if (rc) {
return 2;
}
rc = sqlite3_threadsafe();
if (!rc) {
return 3;
}
return 0;
} }

View File

@@ -34,15 +34,26 @@ var (
) )
const ( const (
driverName = "sqlite" driverName = "sqlite"
heapReserve = 1 << 20 ptrSize = 1 << (^uintptr(0)>>32&1 + ^uintptr(0)>>16&1 + ^uintptr(0)>>8&1 + 3) / 8
heapSize = 32 << 20
ptrSize = 1 << (^uintptr(0)>>32&1 + ^uintptr(0)>>16&1 + ^uintptr(0)>>8&1 + 3) / 8
) )
func init() { func init() {
if v := bin.Init(heapSize, heapReserve); v != 0 { tls := crt.NewTLS()
panic(fmt.Errorf("initialization failed: %v", v)) crt.X__register_stdfiles(tls, bin.Xstdin, bin.Xstdout, bin.Xstderr)
if bin.Xsqlite3_threadsafe(tls) == 0 {
panic(fmt.Errorf("sqlite: thread safety configuration error"))
}
if bin.Xsqlite3_config(
tls,
bin.XSQLITE_CONFIG_LOG,
func(tls *crt.TLS, pArg unsafe.Pointer, iErrCode int32, zMsg *int8) {
fmt.Fprintf(os.Stderr, "%v(%#x): %s\n", iErrCode, iErrCode, crt.GoString(zMsg))
},
unsafe.Pointer(nil),
) != 0 {
panic("sqlite: cannot configure error log callback")
} }
sql.Register(driverName, newDrv()) sql.Register(driverName, newDrv())
@@ -58,12 +69,12 @@ func tracer(rx interface{}, format string, args ...interface{}) {
type result struct { type result struct {
*stmt *stmt
lastInsertId int64 lastInsertID int64
rowsAffected int rowsAffected int
} }
func (r *result) String() string { func (r *result) String() string {
return fmt.Sprintf("&%T@%p{stmt: %p, LastInsertId: %v, RowsAffected: %v}", *r, r, r.stmt, r.lastInsertId, r.rowsAffected) return fmt.Sprintf("&%T@%p{stmt: %p, LastInsertId: %v, RowsAffected: %v}", *r, r, r.stmt, r.lastInsertID, r.rowsAffected)
} }
func newResult(s *stmt) (_ *result, err error) { func newResult(s *stmt) (_ *result, err error) {
@@ -72,7 +83,7 @@ func newResult(s *stmt) (_ *result, err error) {
return nil, err return nil, err
} }
if r.lastInsertId, err = r.lastInsertRowID(); err != nil { if r.lastInsertID, err = r.lastInsertRowID(); err != nil {
return nil, err return nil, err
} }
@@ -97,7 +108,7 @@ func (r *result) LastInsertId() (int64, error) {
return 0, nil return 0, nil
} }
return r.lastInsertId, nil return r.lastInsertID, nil
} }
// RowsAffected returns the number of rows affected by the query. // RowsAffected returns the number of rows affected by the query.
@@ -693,8 +704,8 @@ func (s *stmt) step(pstmt unsafe.Pointer) (int, error) {
// sqlite3_stmt **ppStmt, /* OUT: Statement handle */ // sqlite3_stmt **ppStmt, /* OUT: Statement handle */
// const char **pzTail /* OUT: Pointer to unused portion of zSql */ // const char **pzTail /* OUT: Pointer to unused portion of zSql */
// ); // );
func (s *stmt) prepareV2(zSql *int8) error { func (s *stmt) prepareV2(zSQL *int8) error {
if rc := bin.Xsqlite3_prepare_v2(s.tls, s.pdb(), zSql, -1, s.ppstmt, s.pzTail); rc != bin.XSQLITE_OK { if rc := bin.Xsqlite3_prepare_v2(s.tls, s.pdb(), zSQL, -1, s.ppstmt, s.pzTail); rc != bin.XSQLITE_OK {
return s.errstr(rc) return s.errstr(rc)
} }
@@ -1050,6 +1061,7 @@ func (c *conn) close() (err error) {
return err return err
} }
// Driver implements database/sql/driver.Driver.
type Driver struct { type Driver struct {
sync.Mutex sync.Mutex
} }

View File

@@ -63,11 +63,7 @@ func (s *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driv
func toNamedValues2(vals []driver.NamedValue) []namedValue { func toNamedValues2(vals []driver.NamedValue) []namedValue {
args := make([]namedValue, 0, len(vals)) args := make([]namedValue, 0, len(vals))
for _, val := range vals { for _, val := range vals {
args = append(args, namedValue{ args = append(args, namedValue(val))
Name: val.Name,
Ordinal: val.Ordinal,
Value: val.Value,
})
} }
return args return args
} }