/ Check-in [63955442]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add new extension "bgckpt" in ext/misc/bgckpt.c. For experimenting with running wal2 mode checkpoints in a background thread.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wal2
Files: files | file ages | folders
SHA3-256: 63955442304052f5adddd05ccaeebe87ddc5e25af695702793518f015b4f0a87
User & Date: dan 2017-10-10 20:11:10
Wiki:wal2
Context
2018-12-01
20:14
Sync this branch with the latest trunk. check-in: 7a44fa5a user: dan tags: wal2
2017-10-10
20:11
Add new extension "bgckpt" in ext/misc/bgckpt.c. For experimenting with running wal2 mode checkpoints in a background thread. check-in: 63955442 user: dan tags: wal2
2017-10-09
19:50
Merge latest trunk changes with this branch. check-in: d218d815 user: dan tags: wal2
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added ext/misc/bgckpt.c.





























































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*
** 2017-10-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.
**
******************************************************************************
**
*/

#if !defined(SQLITE_TEST) || defined(SQLITE_OS_UNIX)

#include "sqlite3.h"
#include <string.h>
#include <pthread.h>

/*
** API declarations.
*/
typedef struct Checkpointer Checkpointer;
int sqlite3_bgckpt_create(const char *zFilename, Checkpointer **pp);
int sqlite3_bgckpt_checkpoint(Checkpointer *p, int bBlock);
void sqlite3_bgckpt_destroy(Checkpointer *p);


struct Checkpointer {
  sqlite3 *db;                    /* Database handle */

  pthread_t thread;               /* Background thread */
  pthread_mutex_t mutex;
  pthread_cond_t cond;

  int rc;                         /* Error from "PRAGMA wal_checkpoint" */
  int bCkpt;                      /* True if checkpoint requested */
  int bExit;                      /* True if exit requested */
};

static void *bgckptThreadMain(void *pCtx){
  int rc = SQLITE_OK;
  Checkpointer *p = (Checkpointer*)pCtx;

  while( rc==SQLITE_OK ){
    int bExit;

    pthread_mutex_lock(&p->mutex);
    if( p->bCkpt==0 && p->bExit==0 ){
      pthread_cond_wait(&p->cond, &p->mutex);
    }
    p->bCkpt = 0;
    bExit = p->bExit;
    pthread_mutex_unlock(&p->mutex);

    if( bExit ) break;
    rc = sqlite3_exec(p->db, "PRAGMA wal_checkpoint", 0, 0, 0);
    if( rc==SQLITE_BUSY ){
      rc = SQLITE_OK;
    }
  }

  pthread_mutex_lock(&p->mutex);
  p->rc = rc;
  pthread_mutex_unlock(&p->mutex);
  return 0;
}

void sqlite3_bgckpt_destroy(Checkpointer *p){
  if( p ){
    void *ret = 0;

    /* Signal the background thread to exit */
    pthread_mutex_lock(&p->mutex);
    p->bExit = 1;
    pthread_cond_broadcast(&p->cond);
    pthread_mutex_unlock(&p->mutex);

    pthread_join(p->thread, &ret);
    sqlite3_close(p->db);
    sqlite3_free(p);
  }
}


int sqlite3_bgckpt_create(const char *zFilename, Checkpointer **pp){
  Checkpointer *pNew = 0;
  int rc;

  pNew = (Checkpointer*)sqlite3_malloc(sizeof(Checkpointer));
  if( pNew==0 ){
    rc = SQLITE_NOMEM;
  }else{
    memset(pNew, 0, sizeof(Checkpointer));
    rc = sqlite3_open(zFilename, &pNew->db);
  }

  if( rc==SQLITE_OK ){
    pthread_mutex_init(&pNew->mutex, 0);
    pthread_cond_init(&pNew->cond, 0);
    pthread_create(&pNew->thread, 0, bgckptThreadMain, (void*)pNew);
  }

  if( rc!=SQLITE_OK ){
    sqlite3_bgckpt_destroy(pNew);
    pNew = 0;
  }
  *pp = pNew;
  return rc;
}

int sqlite3_bgckpt_checkpoint(Checkpointer *p, int bBlock){
  int rc;
  pthread_mutex_lock(&p->mutex);
  rc = p->rc;
  if( rc==SQLITE_OK ){
    p->bCkpt = 1;
    pthread_cond_broadcast(&p->cond);
  }
  pthread_mutex_unlock(&p->mutex);
  return rc;
}

#ifdef SQLITE_TEST

#if defined(INCLUDE_SQLITE_TCL_H)
#  include "sqlite_tcl.h"
#else
#  include "tcl.h"
#  ifndef SQLITE_TCLAPI
#    define SQLITE_TCLAPI
#  endif
#endif

const char *sqlite3ErrName(int rc);

static void SQLITE_TCLAPI bgckpt_del(void * clientData){
  Checkpointer *pCkpt = (Checkpointer*)clientData;
  sqlite3_bgckpt_destroy(pCkpt);
}

/*
** Tclcmd: $ckpt SUBCMD ...
*/
static int SQLITE_TCLAPI bgckpt_obj_cmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  Checkpointer *pCkpt = (Checkpointer*)clientData;
  const char *aCmd[] = { "checkpoint", "destroy", 0 };
  int iCmd;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCMD ...");
    return TCL_ERROR;
  }

  if( Tcl_GetIndexFromObj(interp, objv[1], aCmd, "sub-command", 0, &iCmd) ){
    return TCL_ERROR;
  }

  switch( iCmd ){
    case 0: {
      int rc;
      int bBlock = 0;

      if( objc>3 ){
        Tcl_WrongNumArgs(interp, 2, objv, "?BLOCKING?");
        return TCL_ERROR;
      }
      if( objc==3 && Tcl_GetBooleanFromObj(interp, objv[2], &bBlock) ){
        return TCL_ERROR;
      }

      rc = sqlite3_bgckpt_checkpoint(pCkpt, bBlock);
      if( rc!=SQLITE_OK ){
        Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
        return TCL_ERROR;
      }
      break;
    }

    case 1: {
      Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
      break;
    }
  }

  return TCL_OK;
}

/*
** Tclcmd: bgckpt CMDNAME FILENAME
*/
static int SQLITE_TCLAPI bgckpt_cmd(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  const char *zCmd;
  const char *zFilename;
  int rc;
  Checkpointer *pCkpt;

  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "CMDNAME FILENAME");
    return TCL_ERROR;
  }
  zCmd = Tcl_GetString(objv[1]);
  zFilename = Tcl_GetString(objv[2]);

  rc = sqlite3_bgckpt_create(zFilename, &pCkpt);
  if( rc!=SQLITE_OK ){
    Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
    return TCL_ERROR;
  }

  Tcl_CreateObjCommand(interp, zCmd, bgckpt_obj_cmd, (void*)pCkpt, bgckpt_del);
  Tcl_SetObjResult(interp, objv[1]);
  return TCL_OK;
}

int Bgckpt_Init(Tcl_Interp *interp){
  Tcl_CreateObjCommand(interp, "bgckpt", bgckpt_cmd, 0, 0);
  return TCL_OK;
}
#endif   /* SQLITE_TEST */

#else
int Bgckpt_Init(Tcl_Interp *interp){
  return TCL_OK;
}
#endif

Changes to main.mk.

323
324
325
326
327
328
329

330
331
332
333
334
335
336
  $(TOP)/src/test_windirent.c \
  $(TOP)/src/test_wsd.c

# Extensions to be statically loaded.
#
TESTSRC += \
  $(TOP)/ext/misc/amatch.c \

  $(TOP)/ext/misc/carray.c \
  $(TOP)/ext/misc/closure.c \
  $(TOP)/ext/misc/csv.c \
  $(TOP)/ext/misc/eval.c \
  $(TOP)/ext/misc/fileio.c \
  $(TOP)/ext/misc/fuzzer.c \
  $(TOP)/ext/misc/ieee754.c \







>







323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
  $(TOP)/src/test_windirent.c \
  $(TOP)/src/test_wsd.c

# Extensions to be statically loaded.
#
TESTSRC += \
  $(TOP)/ext/misc/amatch.c \
  $(TOP)/ext/misc/bgckpt.c \
  $(TOP)/ext/misc/carray.c \
  $(TOP)/ext/misc/closure.c \
  $(TOP)/ext/misc/csv.c \
  $(TOP)/ext/misc/eval.c \
  $(TOP)/ext/misc/fileio.c \
  $(TOP)/ext/misc/fuzzer.c \
  $(TOP)/ext/misc/ieee754.c \

Changes to src/tclsqlite.c.

4179
4180
4181
4182
4183
4184
4185

4186
4187
4188
4189
4190
4191
4192
....
4227
4228
4229
4230
4231
4232
4233

4234
4235
4236
4237
4238
4239
4240
    extern int SqlitetestSyscall_Init(Tcl_Interp*);
#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
    extern int TestSession_Init(Tcl_Interp*);
#endif
    extern int Fts5tcl_Init(Tcl_Interp *);
    extern int SqliteRbu_Init(Tcl_Interp*);
    extern int Sqlitetesttcl_Init(Tcl_Interp*);

#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
    extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
#endif

#ifdef SQLITE_ENABLE_ZIPVFS
    extern int Zipvfs_Init(Tcl_Interp*);
    Zipvfs_Init(interp);
................................................................................
    SqlitetestSyscall_Init(interp);
#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
    TestSession_Init(interp);
#endif
    Fts5tcl_Init(interp);
    SqliteRbu_Init(interp);
    Sqlitetesttcl_Init(interp);


#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
    Sqlitetestfts3_Init(interp);
#endif

    Tcl_CreateObjCommand(
        interp, "load_testfixture_extensions", init_all_cmd, 0, 0







>







 







>







4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
....
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
    extern int SqlitetestSyscall_Init(Tcl_Interp*);
#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
    extern int TestSession_Init(Tcl_Interp*);
#endif
    extern int Fts5tcl_Init(Tcl_Interp *);
    extern int SqliteRbu_Init(Tcl_Interp*);
    extern int Sqlitetesttcl_Init(Tcl_Interp*);
    extern int Bgckpt_Init(Tcl_Interp*);
#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
    extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
#endif

#ifdef SQLITE_ENABLE_ZIPVFS
    extern int Zipvfs_Init(Tcl_Interp*);
    Zipvfs_Init(interp);
................................................................................
    SqlitetestSyscall_Init(interp);
#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
    TestSession_Init(interp);
#endif
    Fts5tcl_Init(interp);
    SqliteRbu_Init(interp);
    Sqlitetesttcl_Init(interp);
    Bgckpt_Init(interp);

#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
    Sqlitetestfts3_Init(interp);
#endif

    Tcl_CreateObjCommand(
        interp, "load_testfixture_extensions", init_all_cmd, 0, 0