XenDomainWatcher::XenDomainWatcher( LogHelper *logHelper )
    : xsh_( NULL ), xci_( NULL ), introduceToken_( "introduce" ), releaseToken_( "release" ), logHelper_( logHelper )
{
	xsh_ = xs_open( 0 );

	if ( !xsh_ )
		throw Exception( "xs_open() failed" );

	if ( !xs_watch( xsh_, "@introduceDomain", introduceToken_.c_str() ) ) {
		xs_close( xsh_ );
		throw Exception( "xs_watch() failed" );
	}

	if ( !xs_watch( xsh_, "@releaseDomain", releaseToken_.c_str() ) ) {
		xs_unwatch( xsh_, "@introduceDomain", introduceToken_.c_str() );
		xs_close( xsh_ );
		throw Exception( "xs_watch() failed" );
	}

	xci_ = xc_interface_open( NULL, NULL, 0 );

	if ( !xci_ ) {
		xs_unwatch( xsh_, "@introduceDomain", introduceToken_.c_str() );
		xs_unwatch( xsh_, "@releaseDomain", releaseToken_.c_str() );
		xs_close( xsh_ );
		throw Exception( "xc_interface_init() failed" );
	}
}
XenDomainWatcher::~XenDomainWatcher()
{
	xs_unwatch( xsh_, "@introduceDomain", introduceToken_.c_str() );
	xs_unwatch( xsh_, "@releaseDomain", releaseToken_.c_str() );
	xs_close( xsh_ );

	xc_interface_close( xci_ );
}
Exemple #3
0
char* clickos_read_handler(int domid, char *elem, char *attr)
{
	char *ctrlpath = NULL, *elempath = NULL;
	char *rpath = NULL, *wpath = NULL;
	char *value;
	int err;
	unsigned int len = 0;
	struct pollfd fds[1];

	if (!xs) {
		xenstore_init(domid);
	}

	asprintf(&ctrlpath, "/local/domain/%d/clickos/0/control", domid);
	asprintf(&elempath, "/local/domain/%d/clickos/0/elements", domid);
	asprintf(&wpath, "%s/read/%s/%s", ctrlpath, elem, attr);
	asprintf(&rpath, "%s/%s/%s", elempath, elem, attr);

	th = xs_transaction_start(xs);
	xenstore_write(wpath, " ");
	xs_transaction_end(xs, th, 0);

	err = xs_watch(xs, rpath, "lock");
	if (!err) {
		printf("Error setting a watch\n");
		return NULL;
	}

	fds[0].fd = xs_fileno(xs);
	fds[0].events = (POLLIN);
	while (len <= 0) {
	   if (poll(fds, 1, 1000) <= 0) {
		   continue;
	   }

retry_wh:
	   th = xs_transaction_start(xs);
	   //value = xenstore_read(rpath);
	   value = xs_read(xs, XBT_NULL, rpath, &len);
	   //printf("read: len %d value %s\n", len, value);
	   if (!xs_transaction_end(xs, th, 0)) {
			if (errno == EAGAIN)
				goto retry_wh;
	   }
	   usleep(5000);
	}

	err = xs_unwatch(xs, rpath, "lock");
	th = xs_transaction_start(xs);
	xs_write(xs, th, rpath, "", 0);
	err = xs_transaction_end(xs, th, 0);
	return value;
}
Exemple #4
0
static void release_shutdown_watch(checkpoint_state* s) {
  char buf[16];

  if (!s->xsh)
      return;
  if (!s->watching_shutdown)
      return;

  snprintf(buf, sizeof(buf), "%u", s->domid);
  if (!xs_unwatch(s->xsh, "@releaseDomain", buf))
    fprintf(stderr, "Could not release shutdown watch\n");

  s->watching_shutdown = 0;
}
Exemple #5
0
void xs_node_unwatch(struct xs_handle *xsh, const char *node,
                     const char *key, const char *token, Error **errp)
{
    char *path;

    path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) :
        g_strdup(key);

    trace_xs_node_unwatch(path);

    if (!xs_unwatch(xsh, path, token)) {
        error_setg_errno(errp, errno, "failed to unwatch node '%s'", path);
    }

    g_free(path);
}
Exemple #6
0
/* Helper to determine if a backend device is in Created state */
static int xenfb_backend_created(struct xenfb_device *dev)
{
	unsigned int state;
	unsigned int dummy;
	char **vec;
	vec = xs_read_watch(dev->xenfb->xsh, &dummy);
	if (!vec)
		return -1;
	free(vec);

	state = xenfb_read_state(dev->xenfb->xsh, dev->nodename);

	if (!((1 <<state) & ((1 << XenbusStateUnknown)
			     | (1 << XenbusStateInitialising)
			     | (1 << XenbusStateClosed)
#if 1 /* TODO fudging state to permit restarting; to be removed */
			     | (1 << XenbusStateInitWait)
			     | (1 << XenbusStateConnected)
			     | (1 << XenbusStateClosing)
#endif
			     ))) {
		fprintf(stderr, "FB: Carry on waiting\n");
		return 1;
	}

	xs_unwatch(dev->xenfb->xsh, dev->nodename, "");

        switch (state) {
#if 1
        case XenbusStateInitWait:
        case XenbusStateConnected:
                printf("Fudging state to %d\n", XenbusStateInitialising); /* FIXME */
#endif
        case XenbusStateInitialising:
        case XenbusStateClosing:
        case XenbusStateClosed:
                break;
        default:
                fprintf(stderr, "Wrong state %d\n", state);
                return -1;
        }
        xenfb_switch_state(dev, XenbusStateInitWait);
        if (xenfb_hotplug(dev) < 0)
                return -1;

        return 0;
}
Exemple #7
0
/*
 * Unsubscribe from a subscription to the status of a hotplug variable of
 * a device.
 */
int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle,
                                             const char *devtype,
                                             const char *inst,
                                             const char *token)
{
    int rc = 0;
    char *path;
    path = get_device_variable_path(devtype, inst, "hotplug-status");
    if (path == NULL)
        return -1;

    if (0 == xs_unwatch(handle, path, token))
        rc = -2;

    free(path);

    return rc;
}
Exemple #8
0
/* adapted from the eponymous function in xc_save */
static int switch_qemu_logdirty(checkpoint_state *s, int enable)
{
    char path[128];
    char *tail, *cmd, *response;
    char **vec;
    unsigned int len;

    sprintf(path, "/local/domain/0/device-model/%u/logdirty/", s->domid);
    tail = path + strlen(path);

    strcpy(tail, "ret");
    if (!xs_watch(s->xsh, path, "qemu-logdirty-ret")) {
       s->errstr = "error watching qemu logdirty return";
       return -1;
    }
    /* null fire. XXX unify with shutdown watch! */
    vec = xs_read_watch(s->xsh, &len);
    free(vec);

    strcpy(tail, "cmd");
    cmd = enable ? "enable" : "disable";
    if (!xs_write(s->xsh, XBT_NULL, path, cmd, strlen(cmd))) {
       s->errstr = "error signalling qemu logdirty";
       return -1;
    }

    vec = xs_read_watch(s->xsh, &len);
    free(vec);

    strcpy(tail, "ret");
    xs_unwatch(s->xsh, path, "qemu-logdirty-ret");

    response = xs_read(s->xsh, XBT_NULL, path, &len);
    if (!len || strcmp(response, cmd)) {
       if (len)
           free(response);
       s->errstr = "qemu logdirty command failed";
       return -1;
    }
    free(response);
    fprintf(stderr, "qemu logdirty mode: %s\n", cmd);

    return 0;
}
Exemple #9
0
/* Helper to determine if a frontend device is in Initialized state */
static int xenfb_frontend_initialized(struct xenfb_device *dev)
{
	unsigned int state;
	unsigned int dummy;
	char **vec;
	vec = xs_read_watch(dev->xenfb->xsh, &dummy);
	if (!vec)
		return -1;
	free(vec);

	state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);

	if (!((1 << state) & ((1 << XenbusStateUnknown)
			      | (1 << XenbusStateInitialised)
#if 1 /* TODO fudging state to permit restarting; to be removed */
			      | (1 << XenbusStateConnected)
#endif
			      ))) {
		fprintf(stderr, "FB: Carry on waiting\n");
		return 1;
	}

	xs_unwatch(dev->xenfb->xsh, dev->otherend, "");

	switch (state) {
#if 1
	case XenbusStateConnected:
                printf("Fudging state to %d\n", XenbusStateInitialised); /* FIXME */
#endif
        case XenbusStateInitialised:
                break;
        default:
                return -1;
        }

	if (xenfb_bind(dev) < 0)
		return -1;

	return 0;
}
Exemple #10
0
static void
test_many_watches(void)
{
    HANDLE events[64];
    int handles[64];
    int i;
    char buf[64];

    for (i = 0; i < 64; i++) {
        events[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (events[i] == INVALID_HANDLE_VALUE)
            win_err(0, "CreateEvent() %d in test_many_watches", i);
    }
    for (i = 0; i < 64; i++) {
        sprintf(buf, "data/test/key%d", i);
        handles[i] = xs_watch(xs_handle, buf, events[i]);
        if (handles[i] == -1) {
            fail_test(__LINE__, "couldn't watch %s: %d", buf,
                      GetLastError());
        } else {
            /* Wait for the watch to go idle. */
            while (WaitForSingleObject(events[i], 100) != WAIT_TIMEOUT)
                ;
        }
    }
    /* Make sure that the watches all fire. */
    for (i = 0; i < 64; i++) {
        sprintf(buf, "data/test/key%d", i);
        xs_write(xs_handle, buf, "foo");
        if (WaitForSingleObject(events[i], 100) != WAIT_OBJECT_0)
            fail_test(__LINE__, "Watch %d on %s failed to fire", i, buf);
    }

    /* Cancel the watches and close the events. */
    for (i = 0; i < 64; i++) {
        if (handles[i] >= 0)
            xs_unwatch(xs_handle, handles[i]);
        CloseHandle(events[i]);
    }
}
Exemple #11
0
/*
 * The caller must hold the lock on the privateData
 * associated with the 'conn' parameter.
 */
int
xenStoreRemoveWatch(virConnectPtr conn, const char *path, const char *token)
{
    size_t i;
    xenStoreWatchListPtr list;
    xenUnifiedPrivatePtr priv = conn->privateData;

    if (priv->xshandle == NULL)
        return -1;

    list = priv->xsWatchList;
    if (!list)
        return -1;

    for (i = 0; i < list->count; i++) {
        if (STREQ(list->watches[i]->path, path) &&
            STREQ(list->watches[i]->token, token)) {

            if (!xs_unwatch(priv->xshandle,
                       list->watches[i]->path,
                       list->watches[i]->token))
            {
                VIR_DEBUG("WARNING: Could not remove watch");
                /* Not fatal, continue */
            }

            VIR_FREE(list->watches[i]->path);
            VIR_FREE(list->watches[i]->token);
            VIR_FREE(list->watches[i]);

            VIR_DELETE_ELEMENT(list->watches, i, list->count);
            return 0;
        }
    }
    return -1;
}
bool XenDomainWatcher::waitForDomainsOrTimeout( std::list<DomainInfo> &domains, int ms )
{
	struct pollfd fd;
	bool ret = false;

	fd.revents = 0;
	fd.fd = xs_fileno( xsh_ );
	fd.events = POLLIN | POLLERR;

	int rc = poll( &fd, 1, ms );

	domains.clear();

	if ( rc == 0 )
		return false; // timeout

	if ( fd.revents & POLLIN ) {

		unsigned int num;
		char **vec = xs_read_watch( xsh_, &num );

		if ( vec && introduceToken_ == vec[XS_WATCH_TOKEN] ) {

			int domid = 1;
			xc_dominfo_t dominfo;
			int err = -1;

			while ( ( err = xc_domain_getinfo( xci_, domid, 1, &dominfo ) ) == 1 ) {
				domid = dominfo.domid + 1;

				if ( xs_is_domain_introduced( xsh_, dominfo.domid ) ) {

					// New domain
					if ( domIds_.find( dominfo.domid ) == domIds_.end() ) {

						domIds_.insert( dominfo.domid );

						std::stringstream ss;
						ss << "/local/domain/" << dominfo.domid << "/name";

						std::string path = ss.str();

						errno = 0;
						char *name = static_cast<char *>(
						        xs_read_timeout( xsh_, XBT_NULL, path.c_str(), NULL, 1 ) );

						if ( !name && errno && logHelper_ )
							logHelper_->error( std::string( "xs_read() error reading " ) +
							                   ss.str() + ": " + strerror( errno ) );

						if ( name ) { // domain running or new domain w name set

							ss.str( "" );
							ss << "/local/domain/" << dominfo.domid << "/console/tty";
							path = ss.str();

							DomainInfo domain;

							errno = 0;
							void *console = xs_read_timeout( xsh_, XBT_NULL, path.c_str(),
							                                 NULL, 1 );

							if ( !console && errno && logHelper_ )
								logHelper_->error(
								        std::string( "xs_read() error reading " ) +
								        ss.str() + ": " + strerror( errno ) );

							if ( console ) {
								free( console );
								domain.isAlreadyRunning = true;
							}
							else {
								domain.isAlreadyRunning = false;
							}

							domain.name = name;
							free( name );

							domains.push_back( domain );
							ret = true;
						}
						else { // new domain, name not yet set
							ss.str( "" );
							ss << "dom" << dominfo.domid;
							xs_watch( xsh_, path.c_str(), ss.str().c_str() );
						}
					}
				}
			}

			if ( err == -1 && ( errno == EACCES || errno == EPERM ) )
				throw Exception( "access denied for xc_domain_getinfo()" );
		}

		if ( vec && releaseToken_ == vec[XS_WATCH_TOKEN] ) {

			int domid = 1;
			xc_dominfo_t dominfo;

			while ( xc_domain_getinfo( xci_, domid, 1, &dominfo ) == 1 ) {
				domid = dominfo.domid + 1;

				if ( !xs_is_domain_introduced( xsh_, dominfo.domid ) )
					domIds_.erase( dominfo.domid );
			}
		}

		if ( vec && !strncmp( vec[XS_WATCH_TOKEN], "dom", 3 ) ) {

			int domid = 1;
			if ( sscanf( vec[XS_WATCH_TOKEN], "dom%u", &domid ) == 1 ) {

				char *name = static_cast<char *>(
				        xs_read_timeout( xsh_, XBT_NULL, vec[XS_WATCH_PATH], NULL, 1 ) );

				if ( name ) {
					DomainInfo domain;
					domain.isAlreadyRunning = false;
					domain.name = name;
					free( name );

					domains.push_back( domain );
					xs_unwatch( xsh_, vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN] );

					ret = true;
				}
			}
		}

		free( vec );
	}

	return ret;
}
Exemple #13
0
libvchan_t *libvchan_client_init(int domain, int port) {
    char xs_path[255];
    char xs_path_watch[255];
    libvchan_t *ctrl;
    xc_interface *xc_handle;
    struct xs_handle *xs;
    char **vec;
    unsigned int count, len;
    char *dummy = NULL;
    char *own_domid = NULL;

    xc_handle = xc_interface_open(NULL, NULL, 0);
    if (!xc_handle) {
        /* error already logged by xc_interface_open */
        goto err;
    }

    /* wait for server to appear */
    xs = xs_open(0);
    if (!xs) {
        perror("xs_open");
        goto err_xc;
    }

    len = 0;

    if (!xs_watch(xs, "domid", "domid")) {
        fprintf(stderr, "Cannot setup xenstore watch\n");
        goto err_xs;
    }
    if (!xs_watch(xs, "@releaseDomain", "release")) {
        fprintf(stderr, "Cannot setup xenstore watch\n");
        goto err_xs;
    }
    while (!dummy || !len) {
        vec = xs_read_watch(xs, &count);
        if (vec) {
            if (strcmp(vec[XS_WATCH_TOKEN], "domid") == 0) {
                /* domid have changed */
                if (own_domid) {
                    free(own_domid);
                    own_domid = NULL;
                    xs_unwatch(xs, xs_path_watch, xs_path_watch);
                }
            }
            free(vec);
        }
        if (!own_domid) {
            /* construct xenstore path on first iteration and on every domid
             * change detected (save+restore case) */
            own_domid = xs_read(xs, 0, "domid", &len);
            if (!own_domid) {
                fprintf(stderr, "Cannot get own domid\n");
                goto err_xs;
            }
            if (atoi(own_domid) == domain) {
                fprintf(stderr, "Loopback vchan connection not supported\n");
                free(own_domid);
                goto err_xs;
            }

            snprintf(xs_path, sizeof(xs_path), "/local/domain/%d/data/vchan/%s/%d",
                    domain, own_domid, port);
            /* watch on this key as we might not have access to the whole directory */
            snprintf(xs_path_watch, sizeof(xs_path_watch), "%s/event-channel", xs_path);

            if (!xs_watch(xs, xs_path_watch, xs_path_watch)) {
                fprintf(stderr, "Cannot setup watch on %s\n", xs_path_watch);
                free(own_domid);
                goto err_xs;
            }
        }

        dummy = xs_read(xs, 0, xs_path_watch, &len);
        if (dummy)
            free(dummy);
        else {
            if (!libvchan__check_domain_alive(xc_handle, domain)) {
                fprintf(stderr, "domain dead\n");
                goto err_xs;
            }
        }
    }

    if (own_domid)
        free(own_domid);
    xs_close(xs);

    ctrl = malloc(sizeof(*ctrl));
    if (!ctrl)
        return NULL;
    ctrl->xs_path = NULL;
    ctrl->xenvchan = libxenvchan_client_init(NULL, domain, xs_path);
    if (!ctrl->xenvchan) {
        free(ctrl);
        return NULL;
    }
    ctrl->xenvchan->blocking = 1;
    /* notify server */
    xc_evtchn_notify(ctrl->xenvchan->event, ctrl->xenvchan->event_port);
    ctrl->remote_domain = domain;
    ctrl->xc_handle = xc_handle;
    return ctrl;

err_xs:
    xs_close(xs);
err_xc:
    xc_interface_close(xc_handle);
err:
    return NULL;
}
Exemple #14
0
Fichier : xslib.c Projet : euanh/sm
int remove_base_watch(struct xs_handle *h)
{
	if (!xs_unwatch(h, "/vss", "vss"))
		return -EINVAL;
	return 0;
}
Exemple #15
0
int __cdecl
main()
{
    char *vm_path, *uuid, *t;
    size_t l;
    char **contents;
    unsigned count;
    HANDLE xs_handle2;
    HANDLE event;
    HANDLE event2;
    int watch_h;
    int watch_h2;
    int i;
    DWORD status;

    xs_handle = xs_domain_open();
    if (!xs_handle)
        win_err(1, "openning xenstore interface");

    /* Try to give ourselves a clean place to start */
    xs_remove(xs_handle, "data/test");

    /* Check basic xenstore reads with relative path... */
    vm_path = xs_read(xs_handle, "vm", NULL);
    if (!vm_path)
        win_err(1, "reading vm path");
    if (vm_path[0] != '/') {
        fail_test(__LINE__, "expected vm path to be absolute, got %s",
                  vm_path);
    }

    /* and with an absolute path. */
    uuid = gather_read(&l, vm_path, "uuid", NULL);
    if (!uuid)
        win_err(1, "reading uuid");
    if (l != 36) {
        fail_test(__LINE__, "uuid length was %d bytes, expected 36");
    }
    if (strlen(uuid) != 36) {
        fail_test(__LINE__,
                  "uuid was %s, not right length (%d, should be 36), returned length %d",
                  uuid,
                  strlen(uuid),
                  l);
    }

    /* Make sure read error sets a suitable code. */
    xs_read_expected_error(__LINE__, "non_existent", ERROR_FILE_NOT_FOUND);
    xs_read_expected_error(__LINE__, "invalid\\path",
                           ERROR_INVALID_PARAMETER);
    xs_read_expected_error(__LINE__, "/local/domain/0/name",
                           ERROR_ACCESS_DENIED);

    /* Test basic xs_write functionality. */
    if (!xs_write(xs_handle, "data/test/key1", "data1")) {
        fail_test(__LINE__, "write data/test/key1 failed with %lx",
                  GetLastError());
    } else {
        t = xs_read(xs_handle, "data/test/key1", &l);
        if (!t) {
            fail_test(__LINE__, "error reading from data/test/key1: %lx",
                      GetLastError());
        } else {
            if (l != 5) {
                fail_test(__LINE__,
                          "manifest length wrong reading data/test/key1: %d should be 5.",
                          l);
            }
            if (strcmp(t, "data1")) {
                fail_test(__LINE__,
                          "got wrong data reading data/test/key1: %s should be data1.",
                          t);
            }
            free(t);
        }
    }

    xs_write_expected_error(__LINE__, "foo", "bar", ERROR_ACCESS_DENIED);
    xs_write_expected_error(__LINE__, "/foo", "bar", ERROR_ACCESS_DENIED);

    /* Try a very large write and make sure that it fails in the
       expected way. */
    t = malloc(65536);
    memset(t, 'a', 65536);
    t[65535] = 0;
    xs_write_expected_error(__LINE__,"data/test/key1", t,
                            ERROR_DISK_FULL);
    free(t);

    /* Test that read and write work for keys containing nul bytes. */
    if (!xs_write_bin(xs_handle, "data/test/key1", "xxx\0yyy", 7)) {
        fail_test(__LINE__, "failed to write nul bytes (%d)",
                  GetLastError());
    }
    t = xs_read(xs_handle, "data/test/key1", &l);
    if (!t) {
        fail_test(__LINE__, "failed to read nul bytes (%d)",
                  GetLastError());
    } else {
        if (l != 7) {
            fail_test(__LINE__, "read with nuls: expected 7, got %d.\n", l);
        } else if (memcmp(t, "xxx\0yyy", 7)) {
            fail_test(__LINE__, "bad data from read with nuls: %s",
                      t);
        }
        free(t);
    }

    if (!xs_remove(xs_handle, "data/test/key1")) {
        fail_test(__LINE__, "failed to remove data/test/key1 (%d)",
                  GetLastError());
    }

    xs_read_expected_error(__LINE__, "data/test/key1", ERROR_FILE_NOT_FOUND);

    xs_ls_expected_error(__LINE__, "data/test/key1", ERROR_FILE_NOT_FOUND);

    if (!xs_write(xs_handle, "data/test/key1", "data1")) {
        fail_test(__LINE__, "failed to rewrite data/test/key1");
    }

    contents = xs_directory(xs_handle, "data/test/key1", &count);
    if (!contents) {
        fail_test(__LINE__, "failed to ls data/test/key1: %x",
                  GetLastError());
    } else if (count != 0) {
        fail_test(__LINE__, "ls data/test/key1 had %d items", count);
        free(contents);
    } else {
        free(contents);
    }

    if (!xs_write(xs_handle, "data/test/key1/key2", "data2")) {
        fail_test(__LINE__, "failed to rewrite data/test/key1/key2");
    }

    contents = xs_directory(xs_handle, "data/test/key1", &count);
    if (!contents) {
        fail_test(__LINE__, "failed to ls data/test/key1: %x",
                  GetLastError());
    } else if (count != 1) {
        fail_test(__LINE__, "ls data/test/key1 had %d items", count);
        free(contents);
    } else if (strcmp(contents[0], "key2")) {
        fail_test(__LINE__, "ls data/test/key1 gave unexpected result %s",
                  contents[0]);
    }

    xs_remove(xs_handle, "data/test");

    /* Looks like most of the basic functionality works.  Try
     * transactions. */
    xs_handle2 = xs_domain_open();
    if (!xs_handle2) win_err(1, "couldn't re-open domain interface");

    if (!xs_write(xs_handle, "data/test/key1", "before"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction on second handle");
    if (!xs_write(xs_handle2, "data/test/key1", "after"))
        fail_test(__LINE__, "failed to write to data/test/key1 under transaction: %x",
                  GetLastError());
    if (!xs_transaction_end(xs_handle2, FALSE))
        fail_test(__LINE__, "failed to write to end transaction: %x",
                  GetLastError());
    if (strcmp(xs_read(xs_handle, "data/test/key1", NULL), "after"))
        fail_test(__LINE__, "transaction didn't stick");

    /* Now try aborting the transaction. */
    if (!xs_write(xs_handle, "data/test/key1", "before"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction on second handle");
    if (!xs_write(xs_handle2, "data/test/key1", "after"))
        fail_test(__LINE__, "failed to write to data/test/key1 under transaction: %x",
                  GetLastError());
    if (!xs_transaction_end(xs_handle2, TRUE))
        fail_test(__LINE__, "failed to write to end transaction: %x",
                  GetLastError());
    if (strcmp(xs_read(xs_handle, "data/test/key1", NULL), "before"))
        fail_test(__LINE__, "transaction didn't abort");

    /* Try to arrange that the transaction fails. */
    if (!xs_write(xs_handle, "data/test/key1", "before"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction on second handle");
    if (!xs_write(xs_handle2, "data/test/key1", "after"))
        fail_test(__LINE__, "failed to write to data/test/key1 under transaction: %x",
                  GetLastError());
    if (!xs_write(xs_handle, "data/test/key1", "other"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (xs_transaction_end(xs_handle2, FALSE))
        fail_test(__LINE__, "transaction succeeded when it shouldn't",
                  GetLastError());
    if (strcmp(xs_read(xs_handle, "data/test/key1", NULL), "other"))
        fail_test(__LINE__, "transaction did something strange");


    if (!xs_write(xs_handle, "data/test/key1", "before1"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (!xs_write(xs_handle, "data/test/key2", "before2"))
        fail_test(__LINE__, "failed to write to data/test/key2: %x",
                  GetLastError());
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction on second handle");
    if (!xs_write(xs_handle2, "data/test/key1", "after"))
        fail_test(__LINE__, "failed to write to data/test/key1 under transaction: %x",
                  GetLastError());
    t = xs_read(xs_handle2, "data/test/key2", NULL);
    if (!t) {
        fail_test(__LINE__,
                  "failed to read data/test/key2 under transaction: %x",
                  GetLastError());
    } else {
        if (strcmp(t, "before2"))
            fail_test(__LINE__,
                      "got wrong thing reading dtaa/test/key2 (%s)",
                      t);
        free(t);
    }
    if (!xs_write(xs_handle, "data/test/key2", "other"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (xs_transaction_end(xs_handle2, FALSE))
        fail_test(__LINE__, "transaction succeeded when it shouldn't",
                  GetLastError());
    if (strcmp(xs_read(xs_handle, "data/test/key1", NULL), "before1"))
        fail_test(__LINE__, "transaction did something strange");

    xs_daemon_close(xs_handle2);

    /* Try a couple of transaction error cases. */
    xs_handle2 = xs_domain_open();
    if (!xs_handle2) win_err(1, "couldn't re-open domain interface a second time");
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction for re-test");
    if (xs_transaction_start(xs_handle2)) {
        fail_test(__LINE__, "openned two transactions on same handle");
    }
    xs_daemon_close(xs_handle2);

    xs_handle2 = xs_domain_open();
    if (!xs_handle2) win_err(1, "couldn't re-open domain interface a third time");
    if (xs_transaction_end(xs_handle2, FALSE)) {
        fail_test(__LINE__, "ended transaction without starting it");
    }
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction for re-test");
    if (!xs_transaction_end(xs_handle2, FALSE))
        fail_test(__LINE__, "failed to end transaction");
    if (xs_transaction_end(xs_handle2, FALSE)) {
        fail_test(__LINE__, "double-ended transaction");
    }
    xs_daemon_close(xs_handle2);


    /* Transactions appear to be working, at least in their most basic
       form.  Have a go at watches. */
    event = CreateEvent(NULL, FALSE, FALSE, NULL);
    watch_h = xs_watch(xs_handle, "data/test/key1", event);
    if (watch_h < 0) {
        fail_test(__LINE__, "couldn't watch data/test/key1");
    } else {
        while (WaitForSingleObject(event, 100) != WAIT_TIMEOUT)
            ;
        xs_write(xs_handle, "data/test/key1", "foo");
        if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
            fail_test(__LINE__, "failed wait for data/test/key1: %x",
                      GetLastError());
        xs_write(xs_handle, "data/test/key1", "foo");
        if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
            fail_test(__LINE__, "failed wait for data/test/key1: %x",
                      GetLastError());
        xs_write(xs_handle, "data/test/key1", "foo");
        if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
            fail_test(__LINE__, "failed wait for data/test/key1: %x",
                      GetLastError());
        status = WaitForSingleObject(event, 2000);
        if (status != WAIT_TIMEOUT)
            fail_test(__LINE__,
                      "should have timed out waiting for data/test/key1 (%d, %d)",
                      status,
                      GetLastError());

        if (!xs_unwatch(xs_handle, watch_h))
            fail_test(__LINE__, "failed to unwatch");
    }

    /* Create two watches on the same key, kill one of them, and then
       make sure that the other one still works. */
    watch_h = xs_watch(xs_handle, "data/test/key1/subkey", event);
    if (watch_h < 0) {
        fail_test(__LINE__, "couldn't watch data/test/key1/subkey");
    } else {
        event2 = CreateEvent(NULL, FALSE, FALSE, NULL);
        watch_h2 = xs_watch(xs_handle, "data/test/key1/subkey", event);
        if (watch_h2 < 0) {
            fail_test(__LINE__, "couldn't double watch data/test/key1/subkey");
        } else {
            if (!xs_unwatch(xs_handle, watch_h2))
                fail_test(__LINE__, "failed to unwatch h2");
            ResetEvent(event);
            xs_remove(xs_handle, "data/test/key1");
            if (WaitForSingleObject(event, 5000) != WAIT_OBJECT_0)
                fail_test(__LINE__, "failed wait for data/test/key1: %x",
                          GetLastError());
            if (!xs_unwatch(xs_handle, watch_h))
                fail_test(__LINE__, "failed to unwatch");
        }
    }

    /* Watch a node, then modify it in a transaction, and check that
       the watch fires. */
    watch_h = xs_watch(xs_handle, "data/test/key1", event);
    if (watch_h < 0) {
        fail_test(__LINE__, "couldn't watch data/test/key1");
    } else {
        for (i = 0; i < 100; i++) {
            ResetEvent(event);
            do {
                if (!xs_transaction_start(xs_handle))
                    win_err(1, "couldn't open a transaction for watch test");
                xs_write(xs_handle, "data/test/key1", "foo");
            } while (!xs_transaction_end(xs_handle, FALSE));
            if (WaitForSingleObject(event, 5000) != WAIT_OBJECT_0)
                fail_test(__LINE__, "failed wait for data/test/key1(%d): %x",
                          i, GetLastError());
        }
        if (!xs_unwatch(xs_handle, watch_h))
            fail_test(__LINE__, "failed to unwatch");
    }

    /* Make a lot of watches, make sure they all work. */
    test_many_watches();

    /* Try some different sized requests */
    test_write_sizes(4096);

    xs_daemon_close(xs_handle);

    run_stress();

    if (failed) {
        printf("failed\n");
        return 1;
    } else {
        printf("passed\n");
        return 0;
    }
}
Exemple #16
0
static int xenpaging_wait_for_event_or_timeout(struct xenpaging *paging)
{
    xc_interface *xch = paging->xc_handle;
    xc_evtchn *xce = paging->vm_event.xce_handle;
    char **vec, *val;
    unsigned int num;
    struct pollfd fd[2];
    int port;
    int rc;
    int timeout;

    /* Wait for event channel and xenstore */
    fd[0].fd = xc_evtchn_fd(xce);
    fd[0].events = POLLIN | POLLERR;
    fd[1].fd = xs_fileno(paging->xs_handle);
    fd[1].events = POLLIN | POLLERR;

    /* No timeout while page-out is still in progress */
    timeout = paging->use_poll_timeout ? 100 : 0;
    rc = poll(fd, 2, timeout);
    if ( rc < 0 )
    {
        if (errno == EINTR)
            return 0;

        PERROR("Poll exited with an error");
        return -1;
    }

    /* First check for guest shutdown */
    if ( rc && fd[1].revents & POLLIN )
    {
        DPRINTF("Got event from xenstore\n");
        vec = xs_read_watch(paging->xs_handle, &num);
        if ( vec )
        {
            DPRINTF("path '%s' token '%s'\n", vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]);
            if ( strcmp(vec[XS_WATCH_TOKEN], watch_token) == 0 )
            {
                /* If our guest disappeared, set interrupt flag and fall through */
                if ( xs_is_domain_introduced(paging->xs_handle, paging->vm_event.domain_id) == false )
                {
                    xs_unwatch(paging->xs_handle, "@releaseDomain", watch_token);
                    interrupted = SIGQUIT;
                    /* No further poll result processing */
                    rc = 0;
                }
            }
            else if ( strcmp(vec[XS_WATCH_PATH], watch_target_tot_pages) == 0 )
            {
                int ret, target_tot_pages;
                val = xs_read(paging->xs_handle, XBT_NULL, vec[XS_WATCH_PATH], NULL);
                if ( val )
                {
                    ret = sscanf(val, "%d", &target_tot_pages);
                    if ( ret > 0 )
                    {
                        /* KiB to pages */
                        target_tot_pages >>= 2;
                        if ( target_tot_pages < 0 || target_tot_pages > paging->max_pages )
                            target_tot_pages = paging->max_pages;
                        paging->target_tot_pages = target_tot_pages;
                        /* Disable poll() delay while new target is not yet reached */
                        paging->use_poll_timeout = 0;
                        DPRINTF("new target_tot_pages %d\n", target_tot_pages);
                    }
                    free(val);
                }
            }