Codebase list virt-viewer / debian/0.5.5-3_1368724584 src / virt-viewer-events.c
debian/0.5.5-3_1368724584

Tree @debian/0.5.5-3_1368724584 (Download .tar.gz)

virt-viewer-events.c @debian/0.5.5-3_1368724584

67b0e98
 
 
e2a8e17
67b0e98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e2a8e17
67b0e98
 
 
 
 
 
 
8d9bbb8
67b0e98
8d9bbb8
67b0e98
 
 
 
 
 
 
 
 
 
 
 
 
 
8d9bbb8
67b0e98
 
8d9bbb8
e2a8e17
 
67b0e98
8d9bbb8
67b0e98
 
 
 
 
 
 
 
 
 
 
8d9bbb8
67b0e98
 
 
 
 
 
 
 
8d9bbb8
e2a8e17
 
 
 
67b0e98
8d9bbb8
67b0e98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8d9bbb8
67b0e98
 
 
8d9bbb8
67b0e98
 
 
 
 
 
 
8d9bbb8
 
67b0e98
 
 
 
 
 
 
 
 
 
8d9bbb8
e2a8e17
67b0e98
8d9bbb8
67b0e98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8d9bbb8
67b0e98
 
 
 
 
 
 
 
 
 
 
 
032178c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67b0e98
8d9bbb8
67b0e98
8d9bbb8
67b0e98
 
 
 
 
 
8d9bbb8
67b0e98
032178c
 
 
67b0e98
 
 
 
032178c
67b0e98
 
 
8d9bbb8
67b0e98
 
 
 
 
 
 
 
 
 
 
 
8d9bbb8
67b0e98
 
8d9bbb8
67b0e98
8d9bbb8
 
67b0e98
 
 
 
 
 
8d9bbb8
e2a8e17
 
 
67b0e98
8d9bbb8
67b0e98
 
 
 
 
 
 
 
 
 
 
 
8d9bbb8
67b0e98
 
 
 
8d9bbb8
67b0e98
 
 
 
 
8d9bbb8
 
67b0e98
 
 
 
 
 
 
 
 
 
 
8d9bbb8
e2a8e17
67b0e98
8d9bbb8
67b0e98
 
 
 
 
 
8d9bbb8
67b0e98
 
 
 
 
 
 
8d9bbb8
67b0e98
 
 
 
 
 
 
 
 
 
032178c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67b0e98
8d9bbb8
67b0e98
8d9bbb8
67b0e98
 
 
 
 
 
8d9bbb8
67b0e98
 
 
 
 
 
 
032178c
67b0e98
 
 
 
8d9bbb8
 
 
 
 
 
 
67b0e98
 
e2a8e17
 
 
 
 
 
 
/*
 * events.c: event loop integration
 *
 * Copyright (C) 2008-2012 Daniel P. Berrange
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

#include <config.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <glib.h>
#include <libvirt/libvirt.h>

#include "virt-viewer-events.h"

struct virt_viewer_events_handle
{
    int watch;
    int fd;
    int events;
    int enabled;
    GIOChannel *channel;
    guint source;
    virEventHandleCallback cb;
    void *opaque;
    virFreeCallback ff;
};

static int nextwatch = 1;
static unsigned int nhandles = 0;
static struct virt_viewer_events_handle **handles = NULL;

static gboolean
virt_viewer_events_dispatch_handle(GIOChannel *source G_GNUC_UNUSED,
                                   GIOCondition condition,
                                   gpointer opaque)
{
    struct virt_viewer_events_handle *data = opaque;
    int events = 0;

    if (condition & G_IO_IN)
        events |= VIR_EVENT_HANDLE_READABLE;
    if (condition & G_IO_OUT)
        events |= VIR_EVENT_HANDLE_WRITABLE;
    if (condition & G_IO_HUP)
        events |= VIR_EVENT_HANDLE_HANGUP;
    if (condition & G_IO_ERR)
        events |= VIR_EVENT_HANDLE_ERROR;

    DEBUG_LOG("Dispatch handler %d %d %p", data->fd, events, data->opaque);

    (data->cb)(data->watch, data->fd, events, data->opaque);

    return TRUE;
}


static
int virt_viewer_events_add_handle(int fd,
                                  int events,
                                  virEventHandleCallback cb,
                                  void *opaque,
                                  virFreeCallback ff)
{
    struct virt_viewer_events_handle *data;
    GIOCondition cond = 0;

    handles = g_realloc(handles, sizeof(*handles)*(nhandles+1));
    data = g_malloc(sizeof(*data));
    memset(data, 0, sizeof(*data));

    if (events & VIR_EVENT_HANDLE_READABLE)
        cond |= G_IO_IN;
    if (events & VIR_EVENT_HANDLE_WRITABLE)
        cond |= G_IO_OUT;

    data->watch = nextwatch++;
    data->fd = fd;
    data->events = events;
    data->cb = cb;
    data->opaque = opaque;
    data->channel = g_io_channel_unix_new(fd);
    data->ff = ff;

    DEBUG_LOG("Add handle %d %d %p", data->fd, events, data->opaque);

    data->source = g_io_add_watch(data->channel,
                                  cond,
                                  virt_viewer_events_dispatch_handle,
                                  data);

    handles[nhandles++] = data;

    return data->watch;
}

static struct virt_viewer_events_handle *
virt_viewer_events_find_handle(int watch)
{
    unsigned int i;
    for (i = 0 ; i < nhandles ; i++)
        if (handles[i]->watch == watch)
            return handles[i];

    return NULL;
}

static void
virt_viewer_events_update_handle(int watch,
                                 int events)
{
    struct virt_viewer_events_handle *data = virt_viewer_events_find_handle(watch);

    if (!data) {
        DEBUG_LOG("Update for missing handle watch %d", watch);
        return;
    }

    if (events) {
        GIOCondition cond = 0;
        if (events == data->events)
            return;

        if (data->source)
            g_source_remove(data->source);

        cond |= G_IO_HUP;
        if (events & VIR_EVENT_HANDLE_READABLE)
            cond |= G_IO_IN;
        if (events & VIR_EVENT_HANDLE_WRITABLE)
            cond |= G_IO_OUT;
        data->source = g_io_add_watch(data->channel,
                                      cond,
                                      virt_viewer_events_dispatch_handle,
                                      data);
        data->events = events;
    } else {
        if (!data->source)
            return;

        g_source_remove(data->source);
        data->source = 0;
        data->events = 0;
    }
}


static gboolean
virt_viewer_events_cleanup_handle(gpointer user_data)
{
    struct virt_viewer_events_handle *data = user_data;

    DEBUG_LOG("Cleanup of handle %p", data);
    g_return_val_if_fail(data != NULL, FALSE);

    if (data->ff)
        (data->ff)(data->opaque);

    free(data);
    return FALSE;
}


static int
virt_viewer_events_remove_handle(int watch)
{
    struct virt_viewer_events_handle *data = virt_viewer_events_find_handle(watch);

    if (!data) {
        DEBUG_LOG("Remove of missing watch %d", watch);
        return -1;
    }

    DEBUG_LOG("Remove handle %d %d", watch, data->fd);

    if (!data->source)
        return -1;

    g_source_remove(data->source);
    data->source = 0;
    data->events = 0;

    g_idle_add(virt_viewer_events_cleanup_handle, data);
    return 0;
}

struct virt_viewer_events_timeout
{
    int timer;
    int interval;
    guint source;
    virEventTimeoutCallback cb;
    void *opaque;
    virFreeCallback ff;
};


static int nexttimer = 1;
static unsigned int ntimeouts = 0;
static struct virt_viewer_events_timeout **timeouts = NULL;

static gboolean
virt_viewer_events_dispatch_timeout(void *opaque)
{
    struct virt_viewer_events_timeout *data = opaque;
    DEBUG_LOG("Dispatch timeout %p %p %d %p", data, data->cb, data->timer, data->opaque);
    (data->cb)(data->timer, data->opaque);

    return TRUE;
}

static int
virt_viewer_events_add_timeout(int interval,
                               virEventTimeoutCallback cb,
                               void *opaque,
                               virFreeCallback ff)
{
    struct virt_viewer_events_timeout *data;

    timeouts = g_realloc(timeouts, sizeof(*timeouts)*(ntimeouts+1));
    data = g_malloc(sizeof(*data));
    memset(data, 0, sizeof(*data));

    data->timer = nexttimer++;
    data->interval = interval;
    data->cb = cb;
    data->opaque = opaque;
    data->ff = ff;
    if (interval >= 0)
        data->source = g_timeout_add(interval,
                                     virt_viewer_events_dispatch_timeout,
                                     data);

    timeouts[ntimeouts++] = data;

    DEBUG_LOG("Add timeout %p %d %p %p %d", data, interval, cb, opaque, data->timer);

    return data->timer;
}


static struct virt_viewer_events_timeout *
virt_viewer_events_find_timeout(int timer)
{
    unsigned int i;
    for (i = 0 ; i < ntimeouts ; i++)
        if (timeouts[i]->timer == timer)
            return timeouts[i];

    return NULL;
}


static void
virt_viewer_events_update_timeout(int timer,
                                  int interval)
{
    struct virt_viewer_events_timeout *data = virt_viewer_events_find_timeout(timer);

    if (!data) {
        DEBUG_LOG("Update of missing timer %d", timer);
        return;
    }

    DEBUG_LOG("Update timeout %p %d %d", data, timer, interval);

    if (interval >= 0) {
        if (data->source)
            return;

        data->interval = interval;
        data->source = g_timeout_add(data->interval,
                                     virt_viewer_events_dispatch_timeout,
                                     data);
    } else {
        if (!data->source)
            return;

        g_source_remove(data->source);
        data->source = 0;
    }
}


static gboolean
virt_viewer_events_cleanup_timeout(gpointer user_data)
{
    struct virt_viewer_events_timeout *data = user_data;

    DEBUG_LOG("Cleanup of timeout %p", data);
    g_return_val_if_fail(data != NULL, FALSE);

    if (data->ff)
        (data->ff)(data->opaque);

    free(data);
    return FALSE;
}


static int
virt_viewer_events_remove_timeout(int timer)
{
    struct virt_viewer_events_timeout *data = virt_viewer_events_find_timeout(timer);

    if (!data) {
        DEBUG_LOG("Remove of missing timer %d", timer);
        return -1;
    }

    DEBUG_LOG("Remove timeout %p %d", data, timer);

    if (!data->source)
        return -1;

    g_source_remove(data->source);
    data->source = 0;

    g_idle_add(virt_viewer_events_cleanup_timeout, data);
    return 0;
}


void virt_viewer_events_register(void) {
    virEventRegisterImpl(virt_viewer_events_add_handle,
                         virt_viewer_events_update_handle,
                         virt_viewer_events_remove_handle,
                         virt_viewer_events_add_timeout,
                         virt_viewer_events_update_timeout,
                         virt_viewer_events_remove_timeout);
}

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  indent-tabs-mode: nil
 * End:
 */