Skip to content

Commit 5c48a61

Browse files
committed
Updated code but not working yet
1 parent 77603f9 commit 5c48a61

File tree

2 files changed

+72
-40
lines changed

2 files changed

+72
-40
lines changed

etc/server.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ sqlite3:
3939

4040
# Set trace to true to enable the ability to profile queries. Profiling information
4141
# can be displayed through the API.
42-
trace: true
42+
trace: false
4343

4444
# Set max number of connections that can be simultaneously opened
4545
max: 100

sys/sqlite3/statement.go

Lines changed: 71 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,34 @@ import (
1515
#include <sqlite3.h>
1616
#include <pthread.h>
1717
#include <assert.h>
18+
#include <stdio.h>
1819
1920
// sqlite library needs to be compiled with -DSQLITE_ENABLE_UNLOCK_NOTIFY
2021
// https://www.sqlite.org/unlock_notify.html
2122
2223
// A pointer to an instance of this structure is passed as the user-context
2324
// pointer when registering for an unlock-notify callback.
24-
25-
typedef struct UnlockNotification UnlockNotification;
26-
struct UnlockNotification {
27-
int fired; // True after unlock event has occurred
28-
pthread_cond_t cond; // Condition variable to wait on
29-
pthread_mutex_t mutex; // Mutex to protect structure
30-
};
25+
typedef struct {
26+
int fired; // True after unlock event has occurred
27+
pthread_cond_t cond; // Condition variable to wait on
28+
pthread_mutex_t mutex; // Mutex to protect structure
29+
} UnlockNotification;
30+
31+
// This function allocates a new UnlockNotification structure and returns a pointer to it.
32+
static UnlockNotification* alloc_unlock_notification(void) {
33+
return (UnlockNotification* )malloc(sizeof(UnlockNotification));
34+
}
3135
3236
// This function is an unlock-notify callback registered with SQLite.
33-
static void unlock_notify_cb(void **apArg, int nArg){
34-
for(int i = 0; i < nArg; i++){
35-
UnlockNotification *p = (UnlockNotification *)apArg[i];
36-
pthread_mutex_lock(&p->mutex);
37-
p->fired = 1;
38-
pthread_cond_signal(&p->cond);
39-
pthread_mutex_unlock(&p->mutex);
37+
static void unlock_notify_cb(void** apArg, int nArg){
38+
for(int i = 0; i < nArg; i++) {
39+
UnlockNotification* un = (UnlockNotification* )apArg[i];
40+
printf(" unlocking un=%p\n", un);
41+
fflush(stdout);
42+
pthread_mutex_lock(&un->mutex);
43+
un->fired = 1;
44+
pthread_cond_signal(&un->cond);
45+
pthread_mutex_unlock(&un->mutex);
4046
}
4147
}
4248
@@ -52,77 +58,97 @@ static void unlock_notify_cb(void **apArg, int nArg){
5258
// the system, then this function returns SQLITE_LOCKED immediately. In
5359
// this case the caller should not retry the operation and should roll
5460
// back the current transaction (if any).
55-
static int wait_for_unlock_notify(sqlite3 *db) {
56-
int rc;
61+
static int wait_for_unlock_notify(sqlite3* db){
5762
UnlockNotification un;
58-
59-
// Initialize the UnlockNotification structure.
6063
un.fired = 0;
6164
pthread_mutex_init(&un.mutex, 0);
6265
pthread_cond_init(&un.cond, 0);
6366
64-
// Register for an unlock-notify callback.
65-
rc = sqlite3_unlock_notify(db, unlock_notify_cb, (void *)&un);
66-
assert( rc==SQLITE_LOCKED || rc==SQLITE_OK );
67+
printf("wait_for_unlock_notify %p un=%p\n",db,&un);
68+
fflush(stdout);
6769
70+
// Register for an unlock-notify callback.
6871
// The call to sqlite3_unlock_notify() always returns either SQLITE_LOCKED
6972
// or SQLITE_OK.
7073
//
7174
// If SQLITE_LOCKED was returned, then the system is deadlocked. In this
7275
// case this function needs to return SQLITE_LOCKED to the caller so
7376
// that the current transaction can be rolled back. Otherwise, block
7477
// until the unlock-notify callback is invoked, then return SQLITE_OK.
75-
if( rc==SQLITE_OK ){
78+
int rc = sqlite3_unlock_notify(db, unlock_notify_cb, (void* )&un);
79+
assert(rc==SQLITE_LOCKED || rc==SQLITE_OK);
80+
if(rc == SQLITE_OK) {
7681
pthread_mutex_lock(&un.mutex);
77-
if( !un.fired ){
82+
if (!un.fired) {
7883
pthread_cond_wait(&un.cond, &un.mutex);
7984
}
8085
pthread_mutex_unlock(&un.mutex);
8186
}
8287
88+
printf("unlocked %p un=%p rc=%d\n",db,&un,rc);
89+
fflush(stdout);
90+
8391
// Destroy the mutex and condition variables.
8492
pthread_cond_destroy(&un.cond);
8593
pthread_mutex_destroy(&un.mutex);
8694
8795
return rc;
8896
}
8997
90-
9198
// This code is a wrapper around sqlite3_step
92-
static int _sqlite3_blocking_step(sqlite3_stmt* stmt) {
99+
static int _sqlite3_blocking_step(sqlite3_stmt* stmt, UnlockNotification* un) {
93100
int rc;
94101
sqlite3* db = sqlite3_db_handle(stmt);
95102
for (;;) {
103+
printf("make step db=%p\n",db);
104+
fflush(stdout);
96105
rc = sqlite3_step(stmt);
97-
if (rc != SQLITE_LOCKED) {
98-
break;
99-
}
100106
if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) {
101107
break;
102108
}
109+
printf("calling wait_for_unlock_notify db=%p\n",db);
110+
fflush(stdout);
103111
rc = wait_for_unlock_notify(db);
104112
if (rc != SQLITE_OK) {
105113
break;
106114
}
115+
printf("resetting db=%p\n",db);
116+
fflush(stdout);
107117
sqlite3_reset(stmt);
108118
}
109119
return rc;
110120
}
111121
112122
// This code is a wrapper around sqlite3_prepare_v2
113123
static int _sqlite3_blocking_prepare_v2(
114-
sqlite3* db, // Database handle
115-
const char* sql, // UTF-8 encoded SQL statement
116-
int nSql, // Length of zSql in bytes
117-
sqlite3_stmt** stmt, // OUT: A pointer to the prepared statement
118-
const char** pz // OUT: End of parsed string
124+
sqlite3* db, // Database handle
125+
UnlockNotification* un, // IN: Unlock notification object
126+
const char* sql, // IN: UTF-8 encoded SQL statement
127+
int nSql, // IN: Length of zSql in bytes
128+
sqlite3_stmt** stmt, // OUT: A pointer to the prepared statement
129+
const char** pz // OUT: End of parsed string
119130
){
120131
int rc;
121132
for (;;) {
122133
rc = sqlite3_prepare_v2(db, sql, nSql, stmt, pz);
123-
if (rc != SQLITE_LOCKED) {
134+
if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) {
135+
break;
136+
}
137+
rc = wait_for_unlock_notify(db);
138+
if (rc != SQLITE_OK) {
124139
break;
125140
}
141+
}
142+
return rc;
143+
}
144+
145+
146+
// This code is a wrapper around sqlite3_reset
147+
static int _sqlite3_blocking_reset(sqlite3_stmt* stmt, UnlockNotification* un) {
148+
int rc;
149+
sqlite3* db = sqlite3_db_handle(stmt);
150+
for (;;) {
151+
rc = sqlite3_reset(stmt);
126152
if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) {
127153
break;
128154
}
@@ -206,7 +232,9 @@ func (c *Conn) Prepare(query string) (*Statement, string, error) {
206232
}
207233

208234
// Prepare statement
209-
if err := SQError(C._sqlite3_blocking_prepare_v2((*C.sqlite3)(c), cQuery, -1, &s, &cExtra)); err != SQLITE_OK {
235+
un := C.alloc_unlock_notification()
236+
defer C.free(unsafe.Pointer(un))
237+
if err := SQError(C._sqlite3_blocking_prepare_v2((*C.sqlite3)(c), un, cQuery, -1, &s, &cExtra)); err != SQLITE_OK {
210238
return nil, "", err.With(C.GoString(C.sqlite3_errmsg((*C.sqlite3)(c))))
211239
}
212240

@@ -246,9 +274,11 @@ func (s *Statement) Conn() *Conn {
246274

247275
// Reset statement
248276
func (s *Statement) Reset() error {
249-
err := SQError(C.sqlite3_reset((*C.sqlite3_stmt)(s)))
277+
un := C.alloc_unlock_notification()
278+
defer C.free(unsafe.Pointer(un))
279+
err := SQError(C._sqlite3_blocking_reset((*C.sqlite3_stmt)(s), un))
250280
if (err & 0xFF) == SQLITE_LOCKED {
251-
fmt.Println("TODO: Locked")
281+
fmt.Println("TODO: Locked Reset", int(err))
252282
}
253283
if err != SQLITE_OK {
254284
return err.With(C.GoString(C.sqlite3_errmsg((*C.sqlite3)(s.Conn()))))
@@ -285,9 +315,11 @@ func (s *Statement) Finalize() error {
285315

286316
// Step statement
287317
func (s *Statement) Step() error {
288-
err := SQError(C._sqlite3_blocking_step((*C.sqlite3_stmt)(s)))
318+
un := C.alloc_unlock_notification()
319+
defer C.free(unsafe.Pointer(un))
320+
err := SQError(C._sqlite3_blocking_step((*C.sqlite3_stmt)(s), un))
289321
if (err & 0xFF) == SQLITE_LOCKED {
290-
fmt.Println("TODO Locked (Step)")
322+
fmt.Println("TODO Locked Step", int(err))
291323
}
292324
return err
293325
}

0 commit comments

Comments
 (0)