Skip to content

Commit

Permalink
Introduce RESET request
Browse files Browse the repository at this point in the history
Signed-off-by: Cole Miller <cole.miller@canonical.com>
  • Loading branch information
cole-miller committed Nov 21, 2022
1 parent 0c38457 commit 44a0310
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 2 deletions.
39 changes: 39 additions & 0 deletions src/gateway.c
Original file line number Diff line number Diff line change
Expand Up @@ -1268,6 +1268,45 @@ static int handle_weight(struct handle *req)
return 0;
}

static void resetCb(struct exec *exec, int status)
{
tracef("reset cb status:%d", status);
struct gateway *g = exec->data;
struct handle *req = g->req;
struct response_empty response = {0};
g->req = NULL;
if (status != 0) {
failure(req, status, "database reset failed");
return;
}
/* status and exec->status should always match. */
assert(exec->status == 0);
SUCCESS(empty, EMPTY);
}

static int handle_reset(struct handle *req)
{
tracef("handle reset");
struct cursor *cursor = &req->cursor;
struct gateway *g = req->gateway;
int rc;

START_V0(reset, empty);
(void)response;
CHECK_LEADER(req);
LOOKUP_DB(request.db_id);
FAIL_IF_CHECKPOINTING;

g->req = req;
rc = leader__reset(g->leader, &g->exec, resetCb);
if (rc != 0) {
tracef("leader reset failed %d");
g->req = NULL;
return rc;
}
return 0;
}

int gateway__handle(struct gateway *g,
struct handle *req,
int type,
Expand Down
102 changes: 102 additions & 0 deletions src/leader.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,3 +450,105 @@ int leader__barrier(struct leader *l, struct barrier *barrier, barrier_cb cb)
}
return 0;
}

static void resetBarrierCb(struct barrier *barrier, int status)
{
tracef("reset barrier cb status:%d", status);
struct exec *exec = barrier->data;
struct leader *l = exec->leader;
sqlite3_vfs *vfs;
dqlite_vfs_frame *frames;
struct vfs_database_memory_usage usage;
unsigned n, i;
int rv;

if (status != 0) {
rv = status;
goto finish;
}

#if SQLITE_VERSION_NUMBER >= 302400
vfs = sqlite3_vfs_find(l->db->config->name);
assert(vfs != NULL);
usage = VfsDatabaseMemoryUsage(vfs, l->db->filename);
tracef("reset barrier usage before database_n_pages=%u wal_n_frames=%u wal_n_tx=%u shm_n_regions=%u",
usage.database_n_pages,
usage.wal_n_frames,
usage.wal_n_tx,
usage.shm_n_regions);

rv = sqlite3_db_config(l->conn, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
assert(rv == 0);
exec->status = sqlite3_exec(l->conn, "VACUUM", NULL, NULL, NULL);
rv = sqlite3_db_config(l->conn, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
assert(rv == 0);

rv = VfsPoll(vfs, l->db->filename, &frames, &n);
if (rv != 0 || n == 0) {
goto finish;
}

rv = leaderApplyFrames(exec, frames, n);
for (i = 0; i < n; i++) {
sqlite3_free(frames[i].data);
}
sqlite3_free(frames);
if (rv != 0) {
VfsAbort(vfs, l->db->filename);
goto finish;
}

usage = VfsDatabaseMemoryUsage(vfs, l->db->filename);
tracef("reset barrier usage after database_n_pages=%u wal_n_frames=%u wal_n_tx=%u shm_n_regions=%u",
usage.database_n_pages,
usage.wal_n_frames,
usage.wal_n_tx,
usage.shm_n_regions);
return;
#else
tracef("reset barrier cb not supported");
(void)vfs;
(void)frames;
(void)n;
(void)i;
rv = DQLITE_ERROR;
#endif

finish:
if (rv != 0) {
l->exec->status = rv;
}
leaderExecDone(l->exec);
}

int leader__reset(struct leader *l, struct exec *exec, exec_cb cb)
{
tracef("leader reset");
int version = sqlite3_libversion_number();
int rv;

if (version < 302400) {
tracef("leader reset not supported");
return DQLITE_ERROR;
}

exec->leader = l;
exec->barrier.data = exec;
exec->barrier.cb = NULL;
exec->stmt = NULL;
exec->cb = cb;

if (l->exec != NULL) {
tracef("leader reset busy");
return SQLITE_BUSY;
}
l->exec = exec;

rv = leader__barrier(l, &exec->barrier, resetBarrierCb);
if (rv != 0) {
tracef("raft barrier failed %d", rv);
l->exec = NULL;
return rv;
}
return 0;
}
2 changes: 2 additions & 0 deletions src/leader.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,6 @@ int leader__exec(struct leader *l,
*/
int leader__barrier(struct leader *l, struct barrier *barrier, barrier_cb cb);

int leader__reset(struct leader *l, struct exec *exec, exec_cb cb);

#endif /* LEADER_H_*/
3 changes: 2 additions & 1 deletion src/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ enum {
DQLITE_REQUEST_CLUSTER,
DQLITE_REQUEST_TRANSFER,
DQLITE_REQUEST_DESCRIBE,
DQLITE_REQUEST_WEIGHT
DQLITE_REQUEST_WEIGHT,
DQLITE_REQUEST_RESET
};

#define DQLITE_REQUEST_CLUSTER_FORMAT_V0 0 /* ID and address */
Expand Down
4 changes: 3 additions & 1 deletion src/request.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#define REQUEST_TRANSFER(X, ...) X(uint64, id, ##__VA_ARGS__)
#define REQUEST_DESCRIBE(X, ...) X(uint64, format, ##__VA_ARGS__)
#define REQUEST_WEIGHT(X, ...) X(uint64, weight, ##__VA_ARGS__)
#define REQUEST_RESET(X, ...) X(uint64, db_id, ##__VA_ARGS__)

#define REQUEST__DEFINE(LOWER, UPPER, _) \
SERIALIZE__DEFINE(request_##LOWER, REQUEST_##UPPER);
Expand All @@ -64,7 +65,8 @@
X(cluster, CLUSTER, __VA_ARGS__) \
X(transfer, TRANSFER, __VA_ARGS__) \
X(describe, DESCRIBE, __VA_ARGS__) \
X(weight, WEIGHT, __VA_ARGS__)
X(weight, WEIGHT, __VA_ARGS__) \
X(reset, RESET, __VA_ARGS__)

REQUEST__TYPES(REQUEST__DEFINE);

Expand Down
16 changes: 16 additions & 0 deletions src/vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2702,3 +2702,19 @@ int VfsRestore(sqlite3_vfs *vfs,

return 0;
}

struct vfs_database_memory_usage VfsDatabaseMemoryUsage(sqlite3_vfs *vfs, const char *filename)
{
struct vfs *v;
struct vfsDatabase *d;
struct vfs_database_memory_usage usage = {0};

v = (struct vfs *)(vfs->pAppData);
d = vfsDatabaseLookup(v, filename);
assert(d != NULL);
usage.database_n_pages = d->n_pages;
usage.wal_n_frames = d->wal.n_frames;
usage.wal_n_tx = d->wal.n_tx;
usage.shm_n_regions = d->shm.n_regions;
return usage;
}
11 changes: 11 additions & 0 deletions src/vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,15 @@ int VfsDatabaseNumPages(sqlite3_vfs *vfs,
const char* filename,
uint32_t *n);

struct vfs_database_memory_usage
{
unsigned database_n_pages;
unsigned wal_n_frames;
unsigned wal_n_tx;
unsigned shm_n_regions;
};

struct vfs_database_memory_usage VfsDatabaseMemoryUsage(sqlite3_vfs *vfs,
const char *filename);

#endif /* VFS_H_ */
58 changes: 58 additions & 0 deletions test/unit/test_gateway.c
Original file line number Diff line number Diff line change
Expand Up @@ -2077,6 +2077,64 @@ TEST_CASE(request_cluster, unrecognizedFormat, NULL)
return MUNIT_OK;
}

#if SQLITE_VERSION_NUMBER >= 302400

/******************************************************************************
*
* reset
*
******************************************************************************/

struct reset_fixture
{
FIXTURE;
struct request_reset request;
struct response_empty response;
};

TEST_SUITE(reset);
TEST_SETUP(reset)
{
struct reset_fixture *f = munit_malloc(sizeof *f);
SETUP;
CLUSTER_ELECT(0);
OPEN;
return f;
}
TEST_TEAR_DOWN(reset)
{
struct reset_fixture *f = data;
TEAR_DOWN;
free(f);
}

TEST_CASE(reset, simple, NULL)
{
struct reset_fixture *f = data;
char buf[100];
int i;
(void)params;
EXEC("CREATE TABLE test (n INT)");
for (i = 0; i < 100; i += 1) {
snprintf(buf, 100, "INSERT INTO test VALUES (%d)", i);
EXEC(buf);
}
f->request.db_id = 0;
ENCODE(&f->request, reset);
HANDLE(RESET);
WAIT;
ASSERT_CALLBACK(0, EMPTY);

CLUSTER_DEPOSE;
SELECT(1);
CLUSTER_ELECT(1);
OPEN;
EXEC("CREATE TABLE test (n INT)");
return MUNIT_OK;
}

#endif /* SQLITE_VERSION_NUMBER >= 302400 */

/******************************************************************************
*
* invalid
Expand Down

0 comments on commit 44a0310

Please sign in to comment.