Skip to content

Commit

Permalink
Merge branch 'master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
daniellockyer authored Dec 22, 2023
2 parents b89110e + 7552aa0 commit cedce8f
Show file tree
Hide file tree
Showing 14 changed files with 311 additions and 323 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ jobs:
target: arm64
name: ${{ matrix.os }} (node=${{ matrix.node }}, host=${{ matrix.host }}, target=${{ matrix.target }})
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
architecture: ${{ matrix.host }}
Expand Down Expand Up @@ -137,7 +137,7 @@ jobs:
node: 16
name: ${{ matrix.variant }} (node=${{ matrix.node }}, target=${{ matrix.target }})
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v2
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Asynchronous, non-blocking [SQLite3](https://sqlite.org/) bindings for [Node.js]
- [Extension support](https://github.com/TryGhost/node-sqlite3/wiki/API#databaseloadextensionpath-callback), including bundled support for the [json1 extension](https://www.sqlite.org/json1.html)
- Big test suite
- Written in modern C++ and tested for memory leaks
- Bundles SQLite v3.41.1, or you can build using a local SQLite
- Bundles SQLite v3.42.0, or you can build using a local SQLite

# Installing

Expand Down
2 changes: 1 addition & 1 deletion deps/common-sqlite.gypi
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
'variables': {
'sqlite_version%':'3410100',
'sqlite_version%':'3420000',
"toolset%":'',
},
'target_defaults': {
Expand Down
Binary file removed deps/sqlite-autoconf-3410100.tar.gz
Binary file not shown.
Binary file added deps/sqlite-autoconf-3420000.tar.gz
Binary file not shown.
11 changes: 5 additions & 6 deletions src/async.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,19 @@ template <class Item, class Parent> class Async {
}

static void listener(uv_async_t* handle) {
Async* async = static_cast<Async*>(handle->data);
auto* async = static_cast<Async*>(handle->data);
std::vector<Item*> rows;
NODE_SQLITE3_MUTEX_LOCK(&async->mutex)
rows.swap(async->data);
NODE_SQLITE3_MUTEX_UNLOCK(&async->mutex)
for (unsigned int i = 0, size = rows.size(); i < size; i++) {
async->callback(async->parent, rows[i]);
}
for(auto row : rows)
async->callback(async->parent, row);
}

static void close(uv_handle_t* handle) {
assert(handle != NULL);
assert(handle->data != NULL);
Async* async = static_cast<Async*>(handle->data);
auto* async = static_cast<Async*>(handle->data);
delete async;
}

Expand All @@ -56,7 +55,7 @@ template <class Item, class Parent> class Async {

void add(Item* item) {
NODE_SQLITE3_MUTEX_LOCK(&mutex);
data.push_back(item);
data.emplace_back(item);
NODE_SQLITE3_MUTEX_UNLOCK(&mutex)
}

Expand Down
93 changes: 46 additions & 47 deletions src/backup.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include <string.h>
#include <cstring>
#include <napi.h>

#include "macros.h"
#include "database.h"
#include "backup.h"
Expand All @@ -11,9 +10,9 @@ Napi::Object Backup::Init(Napi::Env env, Napi::Object exports) {
Napi::HandleScope scope(env);

// declare napi_default_method here as it is only available in Node v14.12.0+
napi_property_attributes napi_default_method = static_cast<napi_property_attributes>(napi_writable | napi_configurable);
auto napi_default_method = static_cast<napi_property_attributes>(napi_writable | napi_configurable);

Napi::Function t = DefineClass(env, "Backup", {
auto t = DefineClass(env, "Backup", {
InstanceMethod("step", &Backup::Step, napi_default_method),
InstanceMethod("finish", &Backup::Finish, napi_default_method),
InstanceAccessor("idle", &Backup::IdleGetter, nullptr),
Expand All @@ -34,7 +33,7 @@ void Backup::Process() {
}

while (inited && !locked && !queue.empty()) {
std::unique_ptr<Call> call(queue.front());
auto call = std::move(queue.front());
queue.pop();

call->callback(call->baton);
Expand All @@ -43,19 +42,19 @@ void Backup::Process() {

void Backup::Schedule(Work_Callback callback, Baton* baton) {
if (finished) {
queue.push(new Call(callback, baton));
queue.emplace(new Call(callback, baton));
CleanQueue();
}
else if (!inited || locked || !queue.empty()) {
queue.push(new Call(callback, baton));
queue.emplace(new Call(callback, baton));
}
else {
callback(baton);
}
}

template <class T> void Backup::Error(T* baton) {
Napi::Env env = baton->backup->Env();
auto env = baton->backup->Env();
Napi::HandleScope scope(env);

Backup* backup = baton->backup;
Expand All @@ -76,7 +75,7 @@ template <class T> void Backup::Error(T* baton) {
}

void Backup::CleanQueue() {
Napi::Env env = this->Env();
auto env = this->Env();
Napi::HandleScope scope(env);

if (inited && !queue.empty()) {
Expand All @@ -88,7 +87,7 @@ void Backup::CleanQueue() {

// Clear out the queue so that this object can get GC'ed.
while (!queue.empty()) {
std::unique_ptr<Call> call(queue.front());
auto call = std::move(queue.front());
queue.pop();

std::unique_ptr<Baton> baton(call->baton);
Expand All @@ -111,7 +110,7 @@ void Backup::CleanQueue() {
else while (!queue.empty()) {
// Just delete all items in the queue; we already fired an event when
// initializing the backup failed.
std::unique_ptr<Call> call(queue.front());
auto call = std::move(queue.front());
queue.pop();

// We don't call the actual callback, so we have to make sure that
Expand All @@ -121,13 +120,13 @@ void Backup::CleanQueue() {
}

Backup::Backup(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Backup>(info) {
Napi::Env env = info.Env();
auto env = info.Env();
if (!info.IsConstructCall()) {
Napi::TypeError::New(env, "Use the new operator to create new Backup objects").ThrowAsJavaScriptException();
return;
}

int length = info.Length();
auto length = info.Length();

if (length <= 0 || !Database::HasInstance(info[0])) {
Napi::TypeError::New(env, "Database object expected").ThrowAsJavaScriptException();
Expand All @@ -154,32 +153,32 @@ Backup::Backup(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Backup>(info)
return;
}

Database* db = Napi::ObjectWrap<Database>::Unwrap(info[0].As<Napi::Object>());
Napi::String filename = info[1].As<Napi::String>();
Napi::String sourceName = info[2].As<Napi::String>();
Napi::String destName = info[3].As<Napi::String>();
Napi::Boolean filenameIsDest = info[4].As<Napi::Boolean>();
auto* database = Napi::ObjectWrap<Database>::Unwrap(info[0].As<Napi::Object>());
auto filename = info[1].As<Napi::String>();
auto sourceName = info[2].As<Napi::String>();
auto destName = info[3].As<Napi::String>();
auto filenameIsDest = info[4].As<Napi::Boolean>();

info.This().As<Napi::Object>().DefineProperty(Napi::PropertyDescriptor::Value("filename", filename));
info.This().As<Napi::Object>().DefineProperty(Napi::PropertyDescriptor::Value("sourceName", sourceName));
info.This().As<Napi::Object>().DefineProperty(Napi::PropertyDescriptor::Value("destName", destName));
info.This().As<Napi::Object>().DefineProperty(Napi::PropertyDescriptor::Value("filenameIsDest", filenameIsDest));

init(db);
init(database);

InitializeBaton* baton = new InitializeBaton(db, info[5].As<Napi::Function>(), this);
auto* baton = new InitializeBaton(database, info[5].As<Napi::Function>(), this);
baton->filename = filename.Utf8Value();
baton->sourceName = sourceName.Utf8Value();
baton->destName = destName.Utf8Value();
baton->filenameIsDest = filenameIsDest.Value();
db->Schedule(Work_BeginInitialize, baton);
database->Schedule(Work_BeginInitialize, baton);
}

void Backup::Work_BeginInitialize(Database::Baton* baton) {
assert(baton->db->open);
baton->db->pending++;
Napi::Env env = baton->db->Env();
int status = napi_create_async_work(
auto env = baton->db->Env();
int UNUSED(status) = napi_create_async_work(
env, NULL, Napi::String::New(env, "sqlite3.Backup.Initialize"),
Work_Initialize, Work_AfterInitialize, baton, &baton->request
);
Expand All @@ -192,7 +191,7 @@ void Backup::Work_Initialize(napi_env e, void* data) {

// In case stepping fails, we use a mutex to make sure we get the associated
// error message.
sqlite3_mutex* mtx = sqlite3_db_mutex(baton->db->_handle);
auto* mtx = sqlite3_db_mutex(baton->db->_handle);
sqlite3_mutex_enter(mtx);

backup->status = sqlite3_open(baton->filename.c_str(), &backup->_otherDb);
Expand All @@ -218,9 +217,9 @@ void Backup::Work_Initialize(napi_env e, void* data) {

void Backup::Work_AfterInitialize(napi_env e, napi_status status, void* data) {
std::unique_ptr<InitializeBaton> baton(static_cast<InitializeBaton*>(data));
Backup* backup = baton->backup;
auto* backup = baton->backup;

Napi::Env env = backup->Env();
auto env = backup->Env();
Napi::HandleScope scope(env);

if (backup->status != SQLITE_OK) {
Expand All @@ -239,13 +238,13 @@ void Backup::Work_AfterInitialize(napi_env e, napi_status status, void* data) {
}

Napi::Value Backup::Step(const Napi::CallbackInfo& info) {
Backup* backup = this;
Napi::Env env = backup->Env();
auto* backup = this;
auto env = backup->Env();

REQUIRE_ARGUMENT_INTEGER(0, pages);
OPTIONAL_ARGUMENT_FUNCTION(1, callback);

StepBaton* baton = new StepBaton(backup, callback, pages);
auto* baton = new StepBaton(backup, callback, pages);
backup->GetRetryErrors(baton->retryErrorsSet);
backup->Schedule(Work_BeginStep, baton);
return info.This();
Expand Down Expand Up @@ -281,9 +280,9 @@ void Backup::Work_Step(napi_env e, void* data) {

void Backup::Work_AfterStep(napi_env e, napi_status status, void* data) {
std::unique_ptr<StepBaton> baton(static_cast<StepBaton*>(data));
Backup* backup = baton->backup;
auto* backup = baton->backup;

Napi::Env env = backup->Env();
auto env = backup->Env();
Napi::HandleScope scope(env);

if (backup->status == SQLITE_DONE) {
Expand All @@ -308,12 +307,12 @@ void Backup::Work_AfterStep(napi_env e, napi_status status, void* data) {
}

Napi::Value Backup::Finish(const Napi::CallbackInfo& info) {
Backup* backup = this;
Napi::Env env = backup->Env();
auto* backup = this;
auto env = backup->Env();

OPTIONAL_ARGUMENT_FUNCTION(0, callback);

Baton* baton = new Baton(backup, callback);
auto* baton = new Baton(backup, callback);
backup->Schedule(Work_BeginFinish, baton);
return info.This();
}
Expand All @@ -329,9 +328,9 @@ void Backup::Work_Finish(napi_env e, void* data) {

void Backup::Work_AfterFinish(napi_env e, napi_status status, void* data) {
std::unique_ptr<Baton> baton(static_cast<Baton*>(data));
Backup* backup = baton->backup;
auto* backup = baton->backup;

Napi::Env env = backup->Env();
auto env = backup->Env();
Napi::HandleScope scope(env);

backup->FinishAll();
Expand Down Expand Up @@ -369,39 +368,39 @@ void Backup::FinishSqlite() {
}

Napi::Value Backup::IdleGetter(const Napi::CallbackInfo& info) {
Backup* backup = this;
auto* backup = this;
bool idle = backup->inited && !backup->locked && backup->queue.empty();
return Napi::Boolean::New(this->Env(), idle);
}

Napi::Value Backup::CompletedGetter(const Napi::CallbackInfo& info) {
Backup* backup = this;
auto* backup = this;
return Napi::Boolean::New(this->Env(), backup->completed);
}

Napi::Value Backup::FailedGetter(const Napi::CallbackInfo& info) {
Backup* backup = this;
auto* backup = this;
return Napi::Boolean::New(this->Env(), backup->failed);
}

Napi::Value Backup::RemainingGetter(const Napi::CallbackInfo& info) {
Backup* backup = this;
auto* backup = this;
return Napi::Number::New(this->Env(), backup->remaining);
}

Napi::Value Backup::PageCountGetter(const Napi::CallbackInfo& info) {
Backup* backup = this;
auto* backup = this;
return Napi::Number::New(this->Env(), backup->pageCount);
}

Napi::Value Backup::RetryErrorGetter(const Napi::CallbackInfo& info) {
Backup* backup = this;
auto* backup = this;
return backup->retryErrors.Value();
}

void Backup::RetryErrorSetter(const Napi::CallbackInfo& info, const Napi::Value& value) {
Backup* backup = this;
Napi::Env env = backup->Env();
auto* backup = this;
auto env = backup->Env();
if (!value.IsArray()) {
Napi::Error::New(env, "retryErrors must be an array").ThrowAsJavaScriptException();
return;
Expand All @@ -413,9 +412,9 @@ void Backup::RetryErrorSetter(const Napi::CallbackInfo& info, const Napi::Value&
void Backup::GetRetryErrors(std::set<int>& retryErrorsSet) {
retryErrorsSet.clear();
Napi::Array array = retryErrors.Value();
int length = array.Length();
for (int i = 0; i < length; i++) {
Napi::Value code = (array).Get(i);
auto length = array.Length();
for (size_t i = 0; i < length; i++) {
Napi::Value code = (array).Get(static_cast<uint32_t>(i));
if (code.IsNumber()) {
retryErrorsSet.insert(code.As<Napi::Number>().Int32Value());
}
Expand Down
9 changes: 5 additions & 4 deletions src/backup.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class Backup : public Napi::ObjectWrap<Backup> {
Baton(db_, cb_), backup(backup_), filenameIsDest(true) {
backup->Ref();
}
virtual ~InitializeBaton() {
virtual ~InitializeBaton() override {
backup->Unref();
if (!db->IsOpen() && db->IsLocked()) {
// The database handle was closed before the backup could be opened.
Expand All @@ -135,6 +135,7 @@ class Backup : public Napi::ObjectWrap<Backup> {
std::set<int> retryErrorsSet;
StepBaton(Backup* backup_, Napi::Function cb_, int pages_) :
Baton(backup_, cb_), pages(pages_) {}
virtual ~StepBaton() override = default;
};

typedef void (*Work_Callback)(Baton* baton);
Expand Down Expand Up @@ -169,8 +170,8 @@ class Backup : public Napi::ObjectWrap<Backup> {
retryErrors.Reset();
}

WORK_DEFINITION(Step);
WORK_DEFINITION(Finish);
WORK_DEFINITION(Step)
WORK_DEFINITION(Finish)
Napi::Value IdleGetter(const Napi::CallbackInfo& info);
Napi::Value CompletedGetter(const Napi::CallbackInfo& info);
Napi::Value FailedGetter(const Napi::CallbackInfo& info);
Expand Down Expand Up @@ -211,7 +212,7 @@ class Backup : public Napi::ObjectWrap<Backup> {
int remaining;
int pageCount;
bool finished;
std::queue<Call*> queue;
std::queue<std::unique_ptr<Call>> queue;

Napi::Reference<Array> retryErrors;
};
Expand Down
Loading

0 comments on commit cedce8f

Please sign in to comment.