Skip to content

Commit

Permalink
Merge pull request #46 from atoy40/async-refactor-update
Browse files Browse the repository at this point in the history
Libvirt event implementation improvements
  • Loading branch information
atoy40 committed Apr 22, 2015
2 parents 37cbe6c + 9051d46 commit 65337f2
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 51 deletions.
5 changes: 3 additions & 2 deletions src/domain.cc
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,9 @@ NLV_WORKER_EXECUTE(Domain, GetId)
{
NLV_WORKER_ASSERT_DOMAIN();

int result = virDomainGetID(Handle().ToDomain());
if (result == -1) {
unsigned int result = virDomainGetID(Handle().ToDomain());
if (result == -1u) {
data_ = -1;
SetVirError(virGetLastError());
return;
}
Expand Down
186 changes: 138 additions & 48 deletions src/event_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,37 @@

namespace NodeLibvirt {

struct nodeEventHandle
class nodeEventHandle
{
public:
int watch;
virEventHandleCallback cb;
void *opaque;
int event;
int running;
int newEvent;
int toDelete;
int deleted;
int fd;
uv_poll_t watcher;
};

struct nodeEventTimeout
class nodeEventTimeout
{
public:
int timer;
int frequency;
int newFrequency;
virEventTimeoutCallback cb;
void *opaque;
int toDelete;
int deleted;
uv_timer_t timerWatcher;
uv_check_t checkWatcher;
};


uv_check_t updateHandleChecker;
uv_mutex_t lock;
int EventImpl::nextWatch = 1;
int EventImpl::nextTimeout = 1;
std::vector<nodeEventHandle*> EventImpl::handles;
Expand All @@ -44,6 +51,11 @@ void EventImpl::Initialize(Handle<Object> exports)
NAN_METHOD(EventImpl::SetupEvent)
{
NanScope();

uv_mutex_init(&lock);
uv_check_init(uv_default_loop(), &updateHandleChecker);
uv_check_start(&updateHandleChecker, EventImpl::UpdateHandlesOnce);

virEventRegisterImpl(
AddHandle, UpdateHandle, RemoveHandle,
AddTimeout, UpdateTimeout, RemoveTimeout
Expand All @@ -52,35 +64,116 @@ NAN_METHOD(EventImpl::SetupEvent)
NanReturnUndefined();
}

#if UV_VERSION_MAJOR < 1
void EventImpl::UpdateHandlesOnce(uv_check_t* handle, int status)
#else
void EventImpl::UpdateHandlesOnce(uv_check_t* handle)
#endif
{
uv_mutex_lock(&lock);

for (std::vector<nodeEventHandle*>::iterator it = handles.begin() ; it != handles.end(); ++it) {
nodeEventHandle *handle = *it;

if (handle->deleted || (handle->newEvent == handle->event && !handle->toDelete))
continue;

if (handle->toDelete) {
//fprintf(stderr, " CLOSE POLL, watch=%d event=%d\n", handle->watch, handle->newEvent);
handle->toDelete = 0;
uv_poll_stop(&handle->watcher);
uv_close((uv_handle_t*)&handle->watcher, EventImpl::ClosePollCallback);
} else if (EventToUV(handle->newEvent) == 0) {
//fprintf(stderr, " STOP POLL, watch=%d event=%d\n", handle->watch, handle->newEvent);
uv_poll_stop(&handle->watcher);
} else {
//fprintf(stderr, " START POLL, watch=%d event=%d\n", handle->watch, handle->newEvent);
uv_poll_start(&handle->watcher, EventToUV(handle->newEvent), EventImpl::HandleCallback);
}

handle->event = handle->newEvent;
}

for (std::vector<nodeEventTimeout*>::iterator it = timeouts.begin() ; it != timeouts.end(); ++it) {
nodeEventTimeout *timeout = *it;

if (timeout->deleted || (timeout->newFrequency == timeout->frequency && !timeout->toDelete))
continue;

//fprintf(stderr, "CHANGE FREQ, freq=%d\n", timeout->newFrequency);
uv_timer_stop(&timeout->timerWatcher);
uv_check_stop(&timeout->checkWatcher);

if (timeout->toDelete) {
timeout->deleted = 1;
} else if (timeout->newFrequency == 0) {
uv_check_start(&timeout->checkWatcher, CheckCallback);
} else if (timeout->newFrequency >= 0) {
uv_timer_start(&timeout->timerWatcher, TimerCallback, timeout->newFrequency, timeout->newFrequency);
}

timeout->frequency = timeout->newFrequency;
}

uv_mutex_unlock(&lock);
}

void EventImpl::HandleCallback(uv_poll_t* handle, int status, int events)
{
//fprintf(stderr, "dispatch handle=%d status=%d, events=%d\n", h->watch, status, events);

nodeEventHandle *h = (nodeEventHandle*) handle->data;
virEventHandleCallback cb = h->cb;

(cb)(h->watch, h->fd, EventImpl::EventFromUV(events), h->opaque);
}

#if UV_VERSION_MAJOR < 1
void EventImpl::CheckCallback(uv_check_t* handle, int status)
#else
void EventImpl::CheckCallback(uv_check_t* handle)
#endif
{
TimeoutCallback((uv_handle_s*)handle);
}

#if UV_VERSION_MAJOR < 1
void EventImpl::TimerCallback(uv_timer_t* handle, int status)
#else
void EventImpl::TimerCallback(uv_timer_t* handle)
#endif
{
TimeoutCallback((uv_handle_s*)handle);
}

void EventImpl::TimeoutCallback(uv_handle_s* handle)
{
//fprintf(stderr, "dispatch timer=%d\n", t->timer);

nodeEventTimeout *t = (nodeEventTimeout*) handle->data;
virEventTimeoutCallback cb = t->cb;

(cb)(t->timer, t->opaque);

}

void EventImpl::ClosePollCallback(uv_handle_t* handle) {
//fprintf(stderr, "close handle cb\n");

uv_mutex_lock(&lock);

nodeEventHandle *h = (nodeEventHandle*) handle->data;
h->deleted = 1;

uv_mutex_unlock(&lock);
}

int EventImpl::AddHandle(int fd, int event, virEventHandleCallback cb, void *opaque,
virFreeCallback ff)
{
//fprintf(stderr, "Adding handle, fd=%d, event=%d\n", fd, event);

uv_mutex_lock(&lock);
nodeEventHandle *handle;

handle = FindDeletedHandle();
Expand All @@ -93,7 +186,8 @@ int EventImpl::AddHandle(int fd, int event, virEventHandleCallback cb, void *opa
handle->cb = cb;
handle->fd = fd;
handle->event = event;
handle->running = 0;
handle->newEvent = event;
handle->toDelete = 0;
handle->deleted = 0;
handle->opaque = opaque;

Expand All @@ -102,46 +196,41 @@ int EventImpl::AddHandle(int fd, int event, virEventHandleCallback cb, void *opa

if (event) {
uv_poll_start(&handle->watcher, EventToUV(event), HandleCallback);
handle->running = 1;
}

uv_mutex_unlock(&lock);

return handle->watch;
}

void EventImpl::UpdateHandle(int watch, int event)
{
//fprintf(stderr, "Update handle, watch=%d, event=%d\n", watch, event);

uv_mutex_lock(&lock);

nodeEventHandle* handle;
handle = FindHandle(watch);
if (handle != NULL)
handle->newEvent = event;

if (handle == NULL)
return;

if (!event && handle->running) {
//fprintf(stderr, " STOP POLL, watch=%d event=%d\n", watch, event);
uv_poll_stop(&handle->watcher);
handle->running = 0;
} else if (event && handle->event == event && !handle->running) {
//fprintf(stderr, " RESTART POLL, watch=%d event=%d\n", watch, event);
uv_poll_start(&handle->watcher, EventToUV(event), HandleCallback);
handle->running = 1;
} else if (event && handle->event != event) {
//fprintf(stderr, " MODIFYING POLL, watch=%d event=%d\n", watch, event);
uv_poll_start(&handle->watcher, EventToUV(event), HandleCallback);
handle->event = event;
handle->running = 1;
}
uv_mutex_unlock(&lock);
}

int EventImpl::RemoveHandle(int watch)
{
uv_mutex_lock(&lock);

nodeEventHandle* handle;
handle = FindHandle(watch);

if (handle == NULL)
return -1;
if (handle != NULL) {
handle->newEvent = 0;
handle->toDelete = 1;
}

uv_mutex_unlock(&lock);

uv_poll_stop(&handle->watcher);
handle->deleted = 1;
return 0;
}

Expand Down Expand Up @@ -171,23 +260,31 @@ int EventImpl::AddTimeout(int frequency, virEventTimeoutCallback cb, void *opaqu
virFreeCallback ff)
{
//fprintf(stderr, "Adding timeout, freq=%d\n", frequency);

uv_mutex_lock(&lock);

nodeEventTimeout *timeout;

timeout = FindDeletedTimeout();
if (timeout == NULL) {
timeout = new nodeEventTimeout();
timeout->timer = nextTimeout++;

uv_check_init(uv_default_loop(), &timeout->checkWatcher);
uv_timer_init(uv_default_loop(), &timeout->timerWatcher);
timeout->checkWatcher.data = timeout;
timeout->timerWatcher.data = timeout;

timeouts.push_back(timeout);
}

timeout->cb = cb;
timeout->frequency = frequency;
timeout->newFrequency = frequency;
timeout->toDelete = 0;
timeout->deleted = 0;
timeout->opaque = opaque;

uv_check_init(uv_default_loop(), &timeout->checkWatcher);
uv_timer_init(uv_default_loop(), &timeout->timerWatcher);

timeout->checkWatcher.data = timeout;
timeout->timerWatcher.data = timeout;

Expand All @@ -197,43 +294,36 @@ int EventImpl::AddTimeout(int frequency, virEventTimeoutCallback cb, void *opaqu
uv_timer_start(&timeout->timerWatcher, TimerCallback, frequency, frequency);
}

uv_mutex_unlock(&lock);

return timeout->timer;
}

void EventImpl::UpdateTimeout(int timer, int frequency)
{
//fprintf(stderr, "update timeout, timer=%d timeout=%d\n", timer, frequency);
nodeEventTimeout* timeout = FindTimeout(timer);

if (timeout == NULL)
return;
uv_mutex_lock(&lock);

if (frequency == timeout->frequency)
return;

uv_timer_stop(&timeout->timerWatcher);
uv_check_stop(&timeout->checkWatcher);
nodeEventTimeout* timeout = FindTimeout(timer);

timeout->frequency = frequency;
if (timeout != NULL)
timeout->newFrequency = frequency;

if (frequency == 0) {
uv_check_start(&timeout->checkWatcher, CheckCallback);
} else if (frequency >= 0) {
uv_timer_start(&timeout->timerWatcher, TimerCallback, frequency, frequency);
}
uv_mutex_unlock(&lock);
}

int EventImpl::RemoveTimeout(int timer)
{
//fprintf(stderr, "remove timeout, timer=%d\n", timer);
uv_mutex_lock(&lock);

nodeEventTimeout* timeout = FindTimeout(timer);

if (timeout == NULL)
return -1;
if (timeout != NULL)
timeout->toDelete = 1;

uv_timer_stop(&timeout->timerWatcher);
uv_check_stop(&timeout->checkWatcher);
timeout->deleted = 1;
uv_mutex_unlock(&lock);

return 0;
}
Expand Down
10 changes: 9 additions & 1 deletion src/event_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace NodeLibvirt {

class nodeEventHandle;
class nodeEventTimeout;

class EventImpl
{
public:
Expand All @@ -26,9 +27,17 @@ class EventImpl
static int RemoveTimeout(int timer);

static void HandleCallback(uv_poll_t* handle, int status, int events);
#if UV_VERSION_MAJOR < 1
static void UpdateHandlesOnce(uv_check_t* handle, int status);
static void CheckCallback(uv_check_t* handle, int status);
static void TimerCallback(uv_timer_t* handle, int status);
#else
static void UpdateHandlesOnce(uv_check_t* handle);
static void CheckCallback(uv_check_t* handle);
static void TimerCallback(uv_timer_t* handle);
#endif
static void TimeoutCallback(uv_handle_s* handle);
static void ClosePollCallback(uv_handle_t* handle);

static int EventToUV(int);
static int EventFromUV(int);
Expand All @@ -47,4 +56,3 @@ class EventImpl
} //namespace NodeLibvirt

#endif // SRC_EVENTIMPL_H

0 comments on commit 65337f2

Please sign in to comment.