/*
 * Persistent reservation manager abstract class
 *
 * Copyright (c) 2017 Red Hat, Inc.
 *
 * Author: Paolo Bonzini <pbonzini@redhat.com>
 *
 * This code is licensed under the LGPL.
 *
 */

#include "qemu/osdep.h"
#include <scsi/sg.h>

#include "qapi/error.h"
#include "qemu/aio.h"
#include "block/thread-pool.h"
#include "scsi/pr-manager.h"
#include "trace.h"
#include "qapi/qapi-types-block.h"
#include "qemu/module.h"
#include "qapi/qapi-commands-block.h"

#define PR_MANAGER_PATH     "objects"

typedef struct PRManagerData {
    PRManager *pr_mgr;
    struct sg_io_hdr *hdr;
    int fd;
} PRManagerData;

static int pr_manager_worker(void *opaque)
{
    PRManagerData *data = opaque;
    PRManager *pr_mgr = data->pr_mgr;
    PRManagerClass *pr_mgr_class =
        PR_MANAGER_GET_CLASS(pr_mgr);
    struct sg_io_hdr *hdr = data->hdr;
    int fd = data->fd;
    int r;

    trace_pr_manager_run(fd, hdr->cmdp[0], hdr->cmdp[1]);

    /* The reference was taken in pr_manager_execute.  */
    r = pr_mgr_class->run(pr_mgr, fd, hdr);
    object_unref(OBJECT(pr_mgr));
    return r;
}


int coroutine_fn pr_manager_execute(PRManager *pr_mgr, AioContext *ctx, int fd,
                                    struct sg_io_hdr *hdr)
{
    PRManagerData data = {
        .pr_mgr = pr_mgr,
        .fd     = fd,
        .hdr    = hdr,
    };

    trace_pr_manager_execute(fd, hdr->cmdp[0], hdr->cmdp[1]);

    /* The matching object_unref is in pr_manager_worker.  */
    object_ref(OBJECT(pr_mgr));
    return thread_pool_submit_co(pr_manager_worker, &data);
}

bool pr_manager_is_connected(PRManager *pr_mgr)
{
    PRManagerClass *pr_mgr_class =
        PR_MANAGER_GET_CLASS(pr_mgr);

    return !pr_mgr_class->is_connected || pr_mgr_class->is_connected(pr_mgr);
}

static const TypeInfo pr_manager_info = {
    .parent = TYPE_OBJECT,
    .name = TYPE_PR_MANAGER,
    .class_size = sizeof(PRManagerClass),
    .abstract = true,
    .interfaces = (const InterfaceInfo[]) {
        { TYPE_USER_CREATABLE },
        { }
    }
};

PRManager *pr_manager_lookup(const char *id, Error **errp)
{
    Object *obj;
    PRManager *pr_mgr;

    obj = object_resolve_path_component(object_get_objects_root(), id);
    if (!obj) {
        error_setg(errp, "No persistent reservation manager with id '%s'", id);
        return NULL;
    }

    pr_mgr = (PRManager *)
        object_dynamic_cast(obj,
                            TYPE_PR_MANAGER);
    if (!pr_mgr) {
        error_setg(errp,
                   "Object with id '%s' is not a persistent reservation manager",
                   id);
        return NULL;
    }

    return pr_mgr;
}

static void
pr_manager_register_types(void)
{
    type_register_static(&pr_manager_info);
}

static int query_one_pr_manager(Object *object, void *opaque)
{
    PRManagerInfoList ***tail = opaque;
    PRManagerInfo *info;
    PRManager *pr_mgr;

    pr_mgr = (PRManager *)object_dynamic_cast(object, TYPE_PR_MANAGER);
    if (!pr_mgr) {
        return 0;
    }

    info = g_new0(PRManagerInfo, 1);
    info->id = g_strdup(object_get_canonical_path_component(object));
    info->connected = pr_manager_is_connected(pr_mgr);
    QAPI_LIST_APPEND(*tail, info);
    return 0;
}

PRManagerInfoList *qmp_query_pr_managers(Error **errp)
{
    PRManagerInfoList *head = NULL;
    PRManagerInfoList **prev = &head;
    Object *container = object_get_container(PR_MANAGER_PATH);

    object_child_foreach(container, query_one_pr_manager, &prev);
    return head;
}

type_init(pr_manager_register_types);
