Skip to content

Commit

Permalink
Added a connect() method using libuv worker to do it asynchronously
Browse files Browse the repository at this point in the history
  • Loading branch information
atoy40 committed Feb 26, 2015
1 parent 59f5ac6 commit 0a6d0f3
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 21 deletions.
1 change: 1 addition & 0 deletions binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
'target_name': 'libvirt',
'product_prefix': 'lib',
'sources': [
'src/baton.cc',
'src/node_libvirt.cc',
'src/event_impl.cc',
'src/domain.cc',
Expand Down
40 changes: 40 additions & 0 deletions src/baton.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "baton.h"

namespace NodeLibvirt {

Baton::Baton(Hypervisor *hypervisor, Persistent<Function> callback) {
this->hypervisor_ = hypervisor;
this->callback_ = callback;
this->request_.data = this;
this->error_ = NULL;
}

Persistent<Function> Baton::getCallback() {
return this->callback_;
}

Hypervisor* Baton::getHypervisor() {
return this->hypervisor_;
}

uv_work_t* Baton::getHandle() {
return &this->request_;
}

void Baton::setError(virErrorPtr error) {
this->error_ = error;
}

virErrorPtr Baton::getError() {
return this->error_;
}

bool Baton::hasError() {
return this->error_ != NULL;
}

ConnectBaton::ConnectBaton(Hypervisor *hypervisor, Persistent<Function> callback)
: Baton(hypervisor, callback) {
}

}
33 changes: 33 additions & 0 deletions src/baton.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef SRC_BATON_H_
#define SRC_BATON_H_

#include <node.h>
#include <libvirt/virterror.h>
#include "hypervisor.h"

namespace NodeLibvirt {
class Baton {
public:
Baton(Hypervisor *hypervisor, Persistent<Function> callback);
Persistent<Function> getCallback();
Hypervisor* getHypervisor();
uv_work_t* getHandle();
void setError(virErrorPtr error);
virErrorPtr getError();
bool hasError();

private:
uv_work_t request_;
Persistent<Function> callback_;
Hypervisor *hypervisor_;
virErrorPtr error_;
};

class ConnectBaton : public Baton {
public:
ConnectBaton(Hypervisor *hypervisor, Persistent<Function> callback);
virConnectPtr conn_;
};
}

#endif // SRC_BATON_H_
100 changes: 79 additions & 21 deletions src/hypervisor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include "hypervisor.h"
#include "baton.h"

#define GET_LIST_OF(name, numof_function, list_function) \
\
Expand Down Expand Up @@ -103,6 +104,9 @@ namespace NodeLibvirt {
// t->Inherit(EventEmitter::constructor_template);
t->InstanceTemplate()->SetInternalFieldCount(1);

NODE_SET_PROTOTYPE_METHOD(t, "connect",
Hypervisor::Connect);

NODE_SET_PROTOTYPE_METHOD(t, "getBaselineCPU",
Hypervisor::GetBaselineCPU);

Expand Down Expand Up @@ -399,27 +403,11 @@ namespace NodeLibvirt {
bool readonly)
: ObjectWrap() {

static int supported_cred_types[] = {
VIR_CRED_AUTHNAME,
VIR_CRED_PASSPHRASE,
};

this->uri_ = uri;
this->username_ = username;
this->password_ = password;
this->readOnly_ = readonly;

virConnectAuth auth;
auth.credtype = supported_cred_types;
auth.ncredtype = sizeof(supported_cred_types)/sizeof(int);
auth.cb = Hypervisor::auth_callback;
auth.cbdata = this;

conn_ = virConnectOpenAuth( (const char*) uri,
&auth,
readonly ? VIR_CONNECT_RO : 0);

if(conn_ == NULL) {
ThrowException(Error::New(virGetLastError()));
}
}

int Hypervisor::auth_callback( virConnectCredentialPtr cred,
Expand Down Expand Up @@ -473,7 +461,7 @@ namespace NodeLibvirt {

Local<String> uriStr = args[0]->ToString();
String::Utf8Value uri_(uriStr);
uri = *uri_;
uri = strdup(*uri_);

if (argsLen >= 2) {
if (args[1]->IsBoolean()) {
Expand Down Expand Up @@ -509,6 +497,77 @@ namespace NodeLibvirt {
return scope.Close(obj);
}

void Hypervisor::ConnectWorker(uv_work_t* req) {

ConnectBaton *baton = (ConnectBaton*)req->data;
Hypervisor *hypervisor = baton->getHypervisor();

static int supported_cred_types[] = {
VIR_CRED_AUTHNAME,
VIR_CRED_PASSPHRASE,
};

virConnectAuth auth;
auth.credtype = supported_cred_types;
auth.ncredtype = sizeof(supported_cred_types)/sizeof(int);
auth.cb = Hypervisor::auth_callback;
auth.cbdata = baton->getHypervisor();

baton->conn_ = virConnectOpenAuth( (const char*) hypervisor->uri_,
&auth,
hypervisor->readOnly_ ? VIR_CONNECT_RO : 0);

if(baton->conn_ == NULL) {
baton->setError(virGetLastError());
}
}

void Hypervisor::ConnectAfter(uv_work_t* req) {
HandleScope scope;

ConnectBaton *baton = static_cast<ConnectBaton*>(req->data);

if (baton->hasError()) {
Handle<Value> argv[] = { Error::New(baton->getError()) };

TryCatch try_catch;
baton->getCallback()->Call(Context::GetCurrent()->Global(), 1, argv);

if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
} else {
TryCatch try_catch;
baton->getCallback()->Call(Context::GetCurrent()->Global(), 0, NULL);

if (try_catch.HasCaught()) {
node::FatalException(try_catch);
}
}

baton->getCallback().Dispose();
delete baton;
}

Handle<Value> Hypervisor::Connect(const Arguments& args) {
HandleScope scope;

Hypervisor *hypervisor = ObjectWrap::Unwrap<Hypervisor>(args.This());

if (args.Length() == 1 && !args[0]->IsFunction()) {
return ThrowException(Exception::TypeError(
String::New("You must specify a function as first argument")));
}

Local<Function> callback = Local<Function>::Cast(args[0]);

ConnectBaton *baton = new ConnectBaton(hypervisor, Persistent<Function>::New(callback));

uv_queue_work(uv_default_loop(), baton->getHandle(), Hypervisor::ConnectWorker, (uv_after_work_cb)Hypervisor::ConnectAfter);

return scope.Close(Undefined());
}

Handle<Value> Hypervisor::GetCapabilities(const Arguments& args) {
HandleScope scope;
char* capabilities_ = NULL;
Expand Down Expand Up @@ -578,7 +637,7 @@ namespace NodeLibvirt {
return ThrowException(Exception::TypeError(
String::New("Interval must be a number")));
}

if (!args[1]->IsNumber()) {
return ThrowException(Exception::TypeError(
String::New("Count must be a number")));
Expand Down Expand Up @@ -1594,4 +1653,3 @@ namespace NodeLibvirt {
GET_NUM_OF(GetNumberOfActiveStoragePools, virConnectNumOfStoragePools);

} //namespace NodeLibvirt

5 changes: 5 additions & 0 deletions src/hypervisor.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ namespace NodeLibvirt {
protected:
static Handle<Value> New(const Arguments& args);

static Handle<Value> Connect(const Arguments& args);
static void ConnectWorker(uv_work_t* req);
static void ConnectAfter(uv_work_t* req);
static Handle<Value> GetCapabilities(const Arguments& args);
static Handle<Value> GetHostname(const Arguments& args);
static Handle<Value> GetSysinfo(const Arguments& args);
Expand Down Expand Up @@ -95,8 +98,10 @@ namespace NodeLibvirt {

private:
virConnectPtr conn_;
char* uri_;
char* username_;
char* password_;
bool readOnly_;

static void domain_event_free(void *opaque);
static int domain_event_lifecycle_callback( virConnectPtr conn,
Expand Down

0 comments on commit 0a6d0f3

Please sign in to comment.