Commit d1e52e1b by Konstantin Käfer

make sure node stays running long enough to deliver all async messages

parent 37278a81
...@@ -91,20 +91,28 @@ Statement.prototype.map = function() { ...@@ -91,20 +91,28 @@ Statement.prototype.map = function() {
var isVerbose = false; var isVerbose = false;
Database.prototype.addListener = Database.prototype.on = function(event) { Database.prototype.addListener = Database.prototype.on = function(type) {
if (event === 'trace') { var val = EventEmitter.prototype.addListener.apply(this, arguments);
if (type === 'trace') {
this.configure('trace', true); this.configure('trace', true);
} }
return val;
EventEmitter.prototype.addListener.apply(this, arguments);
}; };
Database.prototype.removeListener = function(event) { Database.prototype.removeListener = function(type) {
if (event === 'trace') { var val = EventEmitter.prototype.removeListener.apply(this, arguments);
if (type === 'trace' && !this._events[type]) {
this.configure('trace', false); this.configure('trace', false);
} }
return val;
};
EventEmitter.prototype.removeListener.apply(this, arguments); Database.prototype.removeAllListeners = function(type) {
var val = EventEmitter.prototype.removeAllListeners.apply(this, arguments);
if (type === 'trace') {
this.configure('trace', false);
}
return val;
}; };
......
...@@ -208,6 +208,12 @@ void Database::EIO_BeginClose(Baton* baton) { ...@@ -208,6 +208,12 @@ void Database::EIO_BeginClose(Baton* baton) {
assert(baton->db->open); assert(baton->db->open);
assert(baton->db->handle); assert(baton->db->handle);
assert(baton->db->pending == 0); assert(baton->db->pending == 0);
if (baton->db->debug_trace) {
delete baton->db->debug_trace;
baton->db->debug_trace = NULL;
}
eio_custom(EIO_Close, EIO_PRI_DEFAULT, EIO_AfterClose, baton); eio_custom(EIO_Close, EIO_PRI_DEFAULT, EIO_AfterClose, baton);
} }
...@@ -215,11 +221,6 @@ int Database::EIO_Close(eio_req *req) { ...@@ -215,11 +221,6 @@ int Database::EIO_Close(eio_req *req) {
Baton* baton = static_cast<Baton*>(req->data); Baton* baton = static_cast<Baton*>(req->data);
Database* db = baton->db; Database* db = baton->db;
if (db->debug_trace) {
delete db->debug_trace;
db->debug_trace = NULL;
}
baton->status = sqlite3_close(db->handle); baton->status = sqlite3_close(db->handle);
if (baton->status != SQLITE_OK) { if (baton->status != SQLITE_OK) {
...@@ -535,6 +536,12 @@ void Database::Unref() { ...@@ -535,6 +536,12 @@ void Database::Unref() {
void Database::Destruct(Persistent<Value> value, void *data) { void Database::Destruct(Persistent<Value> value, void *data) {
Database* db = static_cast<Database*>(data); Database* db = static_cast<Database*>(data);
if (db->debug_trace) {
delete db->debug_trace;
db->debug_trace = NULL;
}
if (db->handle) { if (db->handle) {
eio_custom(EIO_Destruct, EIO_PRI_DEFAULT, EIO_AfterDestruct, db); eio_custom(EIO_Destruct, EIO_PRI_DEFAULT, EIO_AfterDestruct, db);
ev_ref(EV_DEFAULT_UC); ev_ref(EV_DEFAULT_UC);
...@@ -547,11 +554,6 @@ void Database::Destruct(Persistent<Value> value, void *data) { ...@@ -547,11 +554,6 @@ void Database::Destruct(Persistent<Value> value, void *data) {
int Database::EIO_Destruct(eio_req *req) { int Database::EIO_Destruct(eio_req *req) {
Database* db = static_cast<Database*>(req->data); Database* db = static_cast<Database*>(req->data);
if (db->debug_trace) {
delete db->debug_trace;
db->debug_trace = NULL;
}
sqlite3_close(db->handle); sqlite3_close(db->handle);
db->handle = NULL; db->handle = NULL;
......
...@@ -98,6 +98,8 @@ public: ...@@ -98,6 +98,8 @@ public:
} }
inline void add(Item item) { inline void add(Item item) {
// Make sure node runs long enough to deliver the messages.
ev_ref(EV_DEFAULT_UC);
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
data.push_back(item); data.push_back(item);
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
...@@ -108,6 +110,9 @@ public: ...@@ -108,6 +110,9 @@ public:
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
rows.swap(data); rows.swap(data);
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
for (int i = rows.size(); i > 0; i--) {
ev_unref(EV_DEFAULT_UC);
}
return rows; return rows;
} }
...@@ -121,6 +126,7 @@ public: ...@@ -121,6 +126,7 @@ public:
} }
~Async() { ~Async() {
ev_invoke(&watcher, ev_async_pending(&watcher));
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
ev_async_stop(EV_DEFAULT_UC_ &watcher); ev_async_stop(EV_DEFAULT_UC_ &watcher);
} }
......
...@@ -38,4 +38,29 @@ exports['test Database tracing'] = function(beforeExit) { ...@@ -38,4 +38,29 @@ exports['test Database tracing'] = function(beforeExit) {
}); });
}; };
// TODO: test turning tracing off again exports['test disabling tracing #1'] = function(beforeExit) {
var db = new sqlite3.Database(':memory:');
db.on('trace', function(sql) {});
db.removeAllListeners('trace');
db._events['trace'] = function(sql) {
assert.ok(false);
};
db.run("CREATE TABLE foo (id int)");
db.close();
};
exports['test disabling tracing #2'] = function(beforeExit) {
var db = new sqlite3.Database(':memory:');
var trace = function(sql) {};
db.on('trace', trace);
db.removeListener('trace', trace);
db._events['trace'] = function(sql) {
assert.ok(false);
};
db.run("CREATE TABLE foo (id int)");
db.close();
};
...@@ -19,7 +19,7 @@ def configure(conf): ...@@ -19,7 +19,7 @@ def configure(conf):
def build(bld): def build(bld):
obj = bld.new_task_gen("cxx", "shlib", "node_addon") obj = bld.new_task_gen("cxx", "shlib", "node_addon")
obj.cxxflags = ["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", obj.cxxflags = ["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE",
"-DSQLITE_ENABLE_RTREE=1", "-Wall"] "-DSQLITE_ENABLE_RTREE=1", "-pthread", "-Wall"]
obj.target = TARGET obj.target = TARGET
obj.source = "src/sqlite3.cc src/database.cc src/statement.cc" obj.source = "src/sqlite3.cc src/database.cc src/statement.cc"
obj.uselib = "SQLITE3" obj.uselib = "SQLITE3"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment