WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

Re: [Xen-devel] Re: [PATCH V6 3/3] libxl, Introduce a QMP client

On Fri, 2011-07-01 at 16:04 +0100, Anthony PERARD wrote:
> On Fri, Jul 1, 2011 at 09:39, Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx> wrote:
> > On Thu, 2011-06-30 at 18:30 +0100, Anthony PERARD wrote:
> >> QMP stands for QEMU Monitor Protocol and it is used to query information
> >> from QEMU or to control QEMU.
> >>
> >> This implementation will ask QEMU the list of chardevice and store the
> >> path to serial0 in xenstored. So we will be able to use xl console with
> >> QEMU upstream.
> >>
> >> In order to connect to the QMP server, a socket file is created in
> >> /var/run/xen/qmp-$(domid).
> >
> > Should include "libxl" in the name somewhere to differentiate from other
> > potential connections in the future?
> 
> Well, this socket belong to QEMU (the creator). So I'm not sure that
> "libxl" in the name is appropriate.

It's created due to libxl asking it too was how I was thinking about it.

> But did you prefer to see "qmp-libxl-$(domid)" as a socket file name ?

Something like that, yeah.

> [...]
> 
> >> +/*
> >> + * Handler functions
> >> + */
> >> +
> >> +static libxl__qmp_handler *qmp_init_handler(libxl_ctx *ctx, uint32_t 
> >> domid)
> >
> > libxl__qmp_init_handler?
> 
> "libxl__" event if it's intern to this file?

I guess it's not required, I'm just used to seeing it. The use of
libxl__gc for internal functions is more important.

> > Generally internal functions should take a libxl__gc *gc rather than a
> > ctx (applies to a bunch of functions).
> >
> >> +{
> >> +    libxl__qmp_handler *qmp = NULL;
> >> +
> >> +    qmp = calloc(1, sizeof (libxl__qmp_handler));
> >
> > Could be attached to the libxl__gc infrastructure instead of using an
> > explicit free?
> 
> So, I should use the garbage collector for the handler, but also for
> the callback ? For the callback, I know when I can free them because
> they will not be used anymore. But if I use the gc, the callbacks will
> not be freed before the dustman is called by the caller.

I don't think using the gc infrastructure should be mandatory, just do
what leads to the cleanest code IMHO.

> > BTW, I was wondering the same thing as I read the parser stuff in the
> > previous patch but that would involve plumbing a *gc through and careful
> > thought about whether or not a given data field could ever reach the
> > libxl user (e.g. JSON_STRING's could ultimately get returned to the
> > caller).
> 
> Well, a json_string should be strdup because, with or without gc,
> everything malloc for a json_object will be free with this object.
> 
> I will try to use the gc with the json parsing stuff.
> 
> >> +static int qmp_open(libxl__qmp_handler *qmp, const char *qmp_socket_path,
> >> +                    int timeout)
> >> +{
> >> +    int ret;
> >> +    int i = 0;
> >> +
> >> +    qmp->qmp_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
> >> +    if (qmp->qmp_fd < 0) {
> >> +        return -1;
> >> +    }
> >> +
> >> +    memset(&qmp->addr, 0, sizeof (&qmp->addr));
> >> +    qmp->addr.sun_family = AF_UNIX;
> >> +    strncpy(qmp->addr.sun_path, qmp_socket_path,
> >> +            sizeof (qmp->addr.sun_path));
> >> +
> >> +    do {
> >> +        ret = connect(qmp->qmp_fd, (struct sockaddr *) &qmp->addr,
> >> +                      sizeof (qmp->addr));
> >> +        if (ret == 0)
> >> +            break;
> >> +        if (errno == ENOENT || errno == ECONNREFUSED) {
> >> +            /* ENOENT       : Socket may not have shown up yet
> >> +             * ECONNREFUSED : Leftover socket hasn't been removed yet */
> >> +            continue;
> >> +        }
> >> +        return -1;
> >> +    } while ((++i / 5 <= timeout) && (usleep(200 * 1000) <= 0));
> >
> > If we exit this loop because we timed out do we need to set errno to
> > ETIMEDOUT or something similar to indicate this? Or is the existing err
> > errno (one of ENOENT or ECONNREFUSED?) a sufficient indicator?
> 
> I think it's should be a ETIMEDOUT. ENOENT or ECONNREFUSED explain
> just why we timeout.
> 
> >> +
> >> +    return ret;
> >> +}
> >> +
> >> +static void qmp_close(libxl__qmp_handler *qmp)
> >> +{
> >> +    callback_id_pair *pp = NULL;
> >> +    callback_id_pair *tmp = NULL;
> >> +
> >> +    close(qmp->qmp_fd);
> >> +    SIMPLEQ_FOREACH(pp, &qmp->callback_list, next) {
> >> +        if (tmp)
> >> +            free(tmp);
> >> +        tmp = pp;
> >
> > That seems like an odd construct, but I suppose it is necessary to work
> > around the lack of a SIMPLEQ_FOREACH variant which is safe against
> > removing the iterator from the list.
> 
> Yes.
> 
> >> +libxl__qmp_handler *libxl__qmp_initialize(libxl_ctx *ctx, uint32_t domid)
> >> +{
> >> +    int ret = 0;
> >> +    libxl__qmp_handler *qmp = NULL;
> >> +    char *qmp_socket;
> >> +    libxl__gc gc = LIBXL_INIT_GC(ctx);
> >> +
> >> +    qmp = qmp_init_handler(ctx, domid);
> >> +
> >> +    qmp_socket = libxl__sprintf(&gc, "%s/qmp-%d",
> >> +                                libxl_run_dir_path(), domid);
> >> +    if ((ret = qmp_open(qmp, qmp_socket, QMP_SOCKET_CONNECT_TIMEOUT)) < 
> >> 0) {
> >> +        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Connection error");
> >> +        qmp_free_handler(qmp);
> >> +        return NULL;
> >> +    }
> >> +
> >> +    LIBXL__LOG(qmp->ctx, LIBXL__LOG_DEBUG, "connected to %s", qmp_socket);
> >> +
> >> +    /* Wait for the response to qmp_capabilities */
> >> +    while (!qmp->connected) {
> >> +        if ((ret = qmp_next(qmp)) < 0) {
> >> +            break;
> >
> > Is it an error condition not to get in to the connected state? Should we
> > therefore qmp_free_handler and return NULL? That would save callers
> > checking qmp->connected since they can just assume it is true...
> 
> That meen that QEMU did not respond to the "qmp_capabilities" command.
> And it's needed in order send other commands. So yes, it's an error. I
> will return NULL.
> 
> > [...]
> >> +int libxl__qmp_initializations(libxl_ctx *ctx, uint32_t domid)
> >> +{
> >> +    libxl__qmp_handler *qmp = NULL;
> >> +    int ret = 0;
> >> +
> >> +    qmp = libxl__qmp_initialize(ctx, domid);
> >> +    if (!qmp)
> >> +        return -1;
> >> +    if (qmp->connected) {
> >
> > ... like here.
> >
> >> +        ret = libxl__qmp_query_serial(qmp);
> >> +    }
> >> +    libxl__qmp_close(qmp);
> >> +    return ret;
> >> +}
> 



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>