Skip to content

Commit

Permalink
add serialization API
Browse files Browse the repository at this point in the history
  • Loading branch information
kkaefer committed Feb 22, 2011
1 parent e6e6481 commit d9bdb1d
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 49 deletions.
6 changes: 3 additions & 3 deletions lib/sqlite3.js
Expand Up @@ -24,21 +24,21 @@ Database.prototype.prepare = function(sql) {
// Database#run(sql, [bind1, bind2, ...], [callback])
Database.prototype.run = function(sql) {
var statement = new Statement(this, sql);
statement.run.apply(statement, Array.prototype.slice.call(arguments, 1));
statement.run.apply(statement, Array.prototype.slice.call(arguments, 1)).finalize();
return this;
}

// Database#get(sql, [bind1, bind2, ...], [callback])
Database.prototype.get = function(sql) {
var statement = new Statement(this, sql);
statement.get.apply(statement, Array.prototype.slice.call(arguments, 1));
statement.get.apply(statement, Array.prototype.slice.call(arguments, 1)).finalize();
return this;
}

// Database#all(sql, [bind1, bind2, ...], [callback])
Database.prototype.all = function(sql) {
var statement = new Statement(this, sql);
statement.all.apply(statement, Array.prototype.slice.call(arguments, 1));
statement.all.apply(statement, Array.prototype.slice.call(arguments, 1)).finalize();
return this;
}

Expand Down
57 changes: 48 additions & 9 deletions src/database.cc
Expand Up @@ -12,7 +12,7 @@ using namespace node_sqlite3;

Persistent<FunctionTemplate> Database::constructor_template;

void Database::Init(v8::Handle<Object> target) {
void Database::Init(Handle<Object> target) {
HandleScope scope;

Local<FunctionTemplate> t = FunctionTemplate::New(New);
Expand All @@ -23,9 +23,11 @@ void Database::Init(v8::Handle<Object> target) {
constructor_template->SetClassName(String::NewSymbol("Database"));

NODE_SET_PROTOTYPE_METHOD(constructor_template, "close", Close);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "serialize", Serialize);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "parallelize", Parallelize);

target->Set(v8::String::NewSymbol("Database"),
constructor_template->GetFunction());
target->Set(String::NewSymbol("Database"),
constructor_template->GetFunction());
}

void Database::Process() {
Expand Down Expand Up @@ -57,20 +59,22 @@ void Database::Process() {
return;
}

while (open && !locked && !queue.empty()) {

while (open && (!locked || pending == 0) && !queue.empty()) {
Call* call = queue.front();

if (call->exclusive && pending > 0) {
break;
}

locked = call->exclusive;
call->callback(call->baton);
queue.pop();
delete call;
}
}

void Database::Schedule(EIO_Callback callback, Baton* baton, bool exclusive = false) {
void Database::Schedule(EIO_Callback callback, Baton* baton, bool exclusive) {
if (!open && locked) {
EXCEPTION(String::New("Database is closed"), SQLITE_MISUSE, exception);
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
Expand All @@ -84,10 +88,11 @@ void Database::Schedule(EIO_Callback callback, Baton* baton, bool exclusive = fa
return;
}

if (!open || locked || (exclusive && pending > 0)) {
queue.push(new Call(callback, baton, exclusive));
if (!open || ((locked || exclusive || serialize) && pending > 0)) {
queue.push(new Call(callback, baton, exclusive || serialize));
}
else {
locked = exclusive;
callback(baton);
}
}
Expand Down Expand Up @@ -198,9 +203,7 @@ Handle<Value> Database::Close(const Arguments& args) {

void Database::EIO_BeginClose(Baton* baton) {
assert(baton->db->open);
assert(!baton->db->locked);
assert(baton->db->pending == 0);
baton->db->locked = true;
eio_custom(EIO_Close, EIO_PRI_DEFAULT, EIO_AfterClose, baton);
}

Expand Down Expand Up @@ -255,6 +258,42 @@ int Database::EIO_AfterClose(eio_req *req) {
return 0;
}

Handle<Value> Database::Serialize(const Arguments& args) {
HandleScope scope;
Database* db = ObjectWrap::Unwrap<Database>(args.This());
OPTIONAL_ARGUMENT_FUNCTION(0, callback);

bool before = db->serialize;
db->serialize = true;

if (!callback.IsEmpty() && callback->IsFunction()) {
TRY_CATCH_CALL(args.This(), callback, 0, NULL);
db->serialize = before;
}

db->Process();

return args.This();
}

Handle<Value> Database::Parallelize(const Arguments& args) {
HandleScope scope;
Database* db = ObjectWrap::Unwrap<Database>(args.This());
OPTIONAL_ARGUMENT_FUNCTION(0, callback);

bool before = db->serialize;
db->serialize = false;

if (!callback.IsEmpty() && callback->IsFunction()) {
TRY_CATCH_CALL(args.This(), callback, 0, NULL);
db->serialize = before;
}

db->Process();

return args.This();
}

/**
* Override this so that we can properly close the database when this object
* gets garbage collected.
Expand Down
12 changes: 9 additions & 3 deletions src/database.h
Expand Up @@ -21,7 +21,7 @@ class Database;
class Database : public EventEmitter {
public:
static Persistent<FunctionTemplate> constructor_template;
static void Init(v8::Handle<Object> target);
static void Init(Handle<Object> target);

static inline bool HasInstance(Handle<Value> val) {
if (!val->IsObject()) return false;
Expand Down Expand Up @@ -71,7 +71,8 @@ class Database : public EventEmitter {
handle(NULL),
open(false),
locked(false),
pending(0) {
pending(0),
serialize(false) {

}

Expand All @@ -84,14 +85,17 @@ class Database : public EventEmitter {
static int EIO_Open(eio_req *req);
static int EIO_AfterOpen(eio_req *req);

void Schedule(EIO_Callback callback, Baton* baton, bool exclusive);
void Schedule(EIO_Callback callback, Baton* baton, bool exclusive = false);
void Process();

static Handle<Value> Close(const Arguments& args);
static void EIO_BeginClose(Baton* baton);
static int EIO_Close(eio_req *req);
static int EIO_AfterClose(eio_req *req);

static Handle<Value> Serialize(const Arguments& args);
static Handle<Value> Parallelize(const Arguments& args);

void Wrap (Handle<Object> handle);
inline void MakeWeak();
virtual void Unref();
Expand All @@ -106,6 +110,8 @@ class Database : public EventEmitter {
bool locked;
unsigned int pending;

bool serialize;

std::queue<Call*> queue;
};

Expand Down
10 changes: 10 additions & 0 deletions src/macros.h
Expand Up @@ -135,13 +135,23 @@ const char* sqlite_code_string(int code);
static int EIO_##name(eio_req *req); \
static int EIO_After##name(eio_req *req);

#define STATEMENT_BEGIN(type) \
assert(!baton->stmt->locked); \
assert(!baton->stmt->finalized); \
assert(baton->stmt->prepared); \
baton->stmt->locked = true; \
baton->stmt->db->pending++; \
eio_custom(EIO_##type, EIO_PRI_DEFAULT, EIO_After##type, baton);

#define STATEMENT_INIT(type) \
type* baton = static_cast<type*>(req->data); \
Statement* stmt = baton->stmt;

#define STATEMENT_END() \
stmt->locked = false; \
stmt->db->pending--; \
stmt->Process(); \
stmt->db->Process(); \
delete baton;

#endif
Expand Down
43 changes: 10 additions & 33 deletions src/statement.cc
Expand Up @@ -12,7 +12,7 @@ using namespace node_sqlite3;

Persistent<FunctionTemplate> Statement::constructor_template;

void Statement::Init(v8::Handle<Object> target) {
void Statement::Init(Handle<Object> target) {
HandleScope scope;

Local<FunctionTemplate> t = FunctionTemplate::New(New);
Expand All @@ -29,8 +29,8 @@ void Statement::Init(v8::Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(constructor_template, "reset", Reset);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "finalize", Finalize);

target->Set(v8::String::NewSymbol("Statement"),
constructor_template->GetFunction());
target->Set(String::NewSymbol("Statement"),
constructor_template->GetFunction());
}

void Statement::Process() {
Expand Down Expand Up @@ -102,15 +102,15 @@ Handle<Value> Statement::New(const Arguments& args) {
stmt->Wrap(args.This());
PrepareBaton* baton = new PrepareBaton(db, Local<Function>::Cast(args[2]), stmt);
baton->sql = std::string(*String::Utf8Value(sql));
db->Schedule(EIO_BeginPrepare, baton, false);
db->Schedule(EIO_BeginPrepare, baton);

return args.This();
}


void Statement::EIO_BeginPrepare(Database::Baton* baton) {
assert(baton->db->open);
assert(!baton->db->locked);
baton->db->pending++;
eio_custom(EIO_Prepare, EIO_PRI_DEFAULT, EIO_AfterPrepare, baton);
}

Expand Down Expand Up @@ -157,7 +157,6 @@ int Statement::EIO_AfterPrepare(eio_req *req) {
}

STATEMENT_END();
baton->db->Process();
return 0;
}

Expand Down Expand Up @@ -263,11 +262,7 @@ Handle<Value> Statement::Bind(const Arguments& args) {
}

void Statement::EIO_BeginBind(Baton* baton) {
assert(!baton->stmt->locked);
assert(!baton->stmt->finalized);
assert(baton->stmt->prepared);
baton->stmt->locked = true;
eio_custom(EIO_Bind, EIO_PRI_DEFAULT, EIO_AfterBind, baton);
STATEMENT_BEGIN(Bind);
}

int Statement::EIO_Bind(eio_req *req) {
Expand Down Expand Up @@ -313,11 +308,7 @@ Handle<Value> Statement::Get(const Arguments& args) {
}

void Statement::EIO_BeginGet(Baton* baton) {
assert(!baton->stmt->locked);
assert(!baton->stmt->finalized);
assert(baton->stmt->prepared);
baton->stmt->locked = true;
eio_custom(EIO_Get, EIO_PRI_DEFAULT, EIO_AfterGet, baton);
STATEMENT_BEGIN(Get);
}

int Statement::EIO_Get(eio_req *req) {
Expand Down Expand Up @@ -383,11 +374,7 @@ Handle<Value> Statement::Run(const Arguments& args) {
}

void Statement::EIO_BeginRun(Baton* baton) {
assert(!baton->stmt->locked);
assert(!baton->stmt->finalized);
assert(baton->stmt->prepared);
baton->stmt->locked = true;
eio_custom(EIO_Run, EIO_PRI_DEFAULT, EIO_AfterRun, baton);
STATEMENT_BEGIN(Run);
}

int Statement::EIO_Run(eio_req *req) {
Expand Down Expand Up @@ -444,11 +431,7 @@ Handle<Value> Statement::All(const Arguments& args) {
}

void Statement::EIO_BeginAll(Baton* baton) {
assert(!baton->stmt->locked);
assert(!baton->stmt->finalized);
assert(baton->stmt->prepared);
baton->stmt->locked = true;
eio_custom(EIO_All, EIO_PRI_DEFAULT, EIO_AfterAll, baton);
STATEMENT_BEGIN(All);
}

int Statement::EIO_All(eio_req *req) {
Expand Down Expand Up @@ -529,11 +512,7 @@ Handle<Value> Statement::Reset(const Arguments& args) {
}

void Statement::EIO_BeginReset(Baton* baton) {
assert(!baton->stmt->locked);
assert(!baton->stmt->finalized);
assert(baton->stmt->prepared);
baton->stmt->locked = true;
eio_custom(EIO_Reset, EIO_PRI_DEFAULT, EIO_AfterReset, baton);
STATEMENT_BEGIN(Reset);
}

int Statement::EIO_Reset(eio_req *req) {
Expand Down Expand Up @@ -649,8 +628,6 @@ void Statement::Finalize() {
// error events in case those failed.
sqlite3_finalize(handle);
handle = NULL;
db->pending--;
db->Process();
db->Unref();
}

Expand Down
1 change: 0 additions & 1 deletion src/statement.h
Expand Up @@ -124,7 +124,6 @@ class Statement : public EventEmitter {
prepared(false),
locked(false),
finalized(false) {
db->pending++;
db->Ref();
}

Expand Down

0 comments on commit d9bdb1d

Please sign in to comment.