Commit 63893a9e by Orlando Vazquez Committed by Orlando Vazquez

Initial stab at using libeio for when doing synchronous io

parent 8a2e0682
......@@ -13,15 +13,18 @@ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sqlite3.h>
#include <string.h>
#include <v8.h>
#include <node.h>
#include <node_events.h>
#include <sqlite3.h>
using namespace v8;
using namespace node;
#define CHECK(rc) { if ((rc) != SQLITE_OK) \
return ThrowException(Exception::Error(String::New( \
sqlite3_errmsg(*db)))); }
......@@ -41,6 +44,12 @@ using namespace node;
String::New("Argument " #I " must be a string"))); \
String::Utf8Value VAR(args[I]->ToString());
#define REQ_FUN_ARG(I, VAR) \
if (args.Length() <= (I) || !args[I]->IsFunction()) \
return ThrowException(Exception::TypeError( \
String::New("Argument " #I " must be a function"))); \
Local<Function> cb = Local<Function>::Cast(args[I]);
#define REQ_EXT_ARG(I, VAR) \
if (args.Length() <= (I) || !args[I]->IsExternal()) \
return ThrowException(Exception::TypeError( \
......@@ -58,8 +67,6 @@ using namespace node;
String::New("Argument " #I " must be an integer"))); \
}
class Sqlite3Db : public EventEmitter
{
public:
......@@ -72,19 +79,20 @@ public:
t->Inherit(EventEmitter::constructor_template);
t->InstanceTemplate()->SetInternalFieldCount(1);
NODE_SET_PROTOTYPE_METHOD(t, "open", Open);
NODE_SET_PROTOTYPE_METHOD(t, "printIt", PrintIt);
NODE_SET_PROTOTYPE_METHOD(t, "changes", Changes);
NODE_SET_PROTOTYPE_METHOD(t, "close", Close);
NODE_SET_PROTOTYPE_METHOD(t, "lastInsertRowid", LastInsertRowid);
NODE_SET_PROTOTYPE_METHOD(t, "prepare", Prepare);
target->Set(v8::String::NewSymbol("DatabaseSync"), t->GetFunction());
target->Set(v8::String::NewSymbol("Database"), t->GetFunction());
Statement::Init(target);
}
protected:
Sqlite3Db(sqlite3* db) : db_(db) {
}
Sqlite3Db() : db_(NULL) { }
~Sqlite3Db() {
sqlite3_close(db_);
......@@ -94,24 +102,120 @@ protected:
operator sqlite3* () const { return db_; }
// Return a pointer to the Sqlite handle pointer so that EIO_Open can
// pass it to sqlite3_open which wants a pointer to an sqlite3 pointer. This
// is because it wants to initialize our original (sqlite3*) pointer to
// point to an valid object.
sqlite3** GetDBPtr(void) { return &db_; }
protected:
static Handle<Value> New(const Arguments& args) {
HandleScope scope;
REQ_STR_ARG(0, filename);
sqlite3* db;
int rc = sqlite3_open(*filename, &db);
if (rc) return ThrowException(Exception::Error(
String::New("Error opening database")));
Sqlite3Db* dbo = new Sqlite3Db(db);
Sqlite3Db* dbo = new Sqlite3Db();
dbo->Wrap(args.This());
return args.This();
}
sqlite3_commit_hook(db, CommitHook, dbo);
sqlite3_rollback_hook(db, RollbackHook, dbo);
sqlite3_update_hook(db, UpdateHook, dbo);
// To pass arguments to the functions that will run in the thread-pool we
// have to pack them into a struct and pass eio_custom a pointer to it.
return args.This();
struct open_request {
Persistent<Function> cb;
Sqlite3Db *dbo;
sqlite3 **dbptr;
char filename[1];
};
static int EIO_AfterOpen(eio_req *req) {
ev_unref(EV_DEFAULT_UC);
HandleScope scope;
struct open_request *open_req = (struct open_request *)(req->data);
printf("EIO_AfterOpen; rc = %d\n", (int) req->result);
printf("result was %d\n", (int) req->result);
Local<Value> argv[1];
bool err = false;
if (req->result) {
err = true;
argv[0] = Exception::Error(String::New("Error opening database"));
}
TryCatch try_catch;
open_req->cb->Call(Context::GetCurrent()->Global(), err && 1, argv);
if (try_catch.HasCaught()) {
FatalException(try_catch);
}
open_req->cb.Dispose();
free(open_req);
return 0;
}
static int EIO_Open(eio_req *req) {
struct open_request *open_req = (struct open_request *)(req->data);
printf("The filename was %s\n", open_req->filename);
printf("before assn %p\n", *(open_req->dbptr));
int rc = sqlite3_open(open_req->filename, open_req->dbptr);
printf("after addr %p\n", *(open_req->dbptr));
sqlite3 *db = *(open_req->dbptr);
sqlite3_commit_hook(db, CommitHook, open_req->dbo);
sqlite3_rollback_hook(db, RollbackHook, open_req->dbo);
sqlite3_update_hook(db, UpdateHook, open_req->dbo);
req->result = rc;
return 0;
}
static Handle<Value> PrintIt(const Arguments& args) {
HandleScope scope;
Sqlite3Db* dbo = ObjectWrap::Unwrap<Sqlite3Db>(args.This());
sqlite3 *db = *dbo;
printf("print it %p\n", db);
return Undefined();
}
static Handle<Value> Open(const Arguments& args) {
HandleScope scope;
REQ_STR_ARG(0, filename);
REQ_FUN_ARG(1, cb);
Sqlite3Db* dbo = ObjectWrap::Unwrap<Sqlite3Db>(args.This());
printf("way before addr %p\n", ((sqlite3*) *dbo));
struct open_request *open_req = (struct open_request *)
calloc(1, sizeof(struct open_request));
if (!open_req) {
V8::LowMemoryNotification();
return ThrowException(Exception::Error(
String::New("Could not allocate enough memory")));
}
open_req->dbptr = dbo->GetDBPtr();
strcpy(open_req->filename, *filename);
open_req->cb = Persistent<Function>::New(cb);
open_req->dbo = dbo;
eio_custom(EIO_Open, EIO_PRI_DEFAULT, EIO_AfterOpen, open_req);
ev_ref(EV_DEFAULT_UC);
dbo->Ref();
return Undefined();
}
//
// JS DatabaseSync bindings
......@@ -195,8 +299,8 @@ protected:
return scope.Close(statement);
}
class Statement : public EventEmitter
{
class Statement : public EventEmitter {
public:
static Persistent<FunctionTemplate> constructor_template;
......@@ -347,15 +451,13 @@ protected:
};
};
Persistent<FunctionTemplate> Sqlite3Db::Statement::constructor_template;
extern "C" void init (v8::Handle<Object> target)
{
extern "C" void init (v8::Handle<Object> target) {
Sqlite3Db::Init(target);
}
var fs = require("fs");
process.mixin(GLOBAL, require("assert"));
process.mixin(GLOBAL, require("sys"));
var sqlite = require("./sqlite3_bindings");
var db = new sqlite.Database();
throws(function () {
db.open();
});
throws(function () {
db.open("my.db");
});
throws(function () {
db.open("/tmp");
});
db.open("my.db", function (err) {
puts(inspect(arguments));
if (err) {
puts("There was an error");
throw err;
}
puts("open callback");
db.printIt();
});
puts("done");
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