Exemplo n.º 1
0
/**
 * \brief Subscribe for a given type of message.
 *
 * \param[in] function Handler function in case a matching record is
 * published.
 * \param[in] state State passed on to handler function.
 * \param[out] id Id of the subscription. In case of the value is undefined.
 * \param query What type of records you want to subscribe.
 * \param ... Additional arguments to format the record using vsprintf.
 *
 * \retval SYS_ERR_OK
 * \retval OCT_ERR_MAX_SUBSCRIPTIONS
 * \retval OCT_ERR_PARSER_FAIL
 * \retval OCT_ERR_ENGINE_FAIL
 */
errval_t oct_subscribe(subscription_handler_fn function, const void *state,
        subscription_t *id, const char *query, ...)
{
    assert(function != NULL);
    assert(query != NULL);
    assert(id != NULL);

    va_list args;
    errval_t err = SYS_ERR_OK;

    char* buf = NULL;
    FORMAT_QUERY(query, args, buf);

    // send to skb
    struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
    errval_t error_code;

    uint64_t fl_function = 0;
    uint64_t fl_state = 0;

    fl_function = (uint64_t)(uintptr_t)function;
    fl_state = (uint64_t)(uintptr_t)state;

    err = cl->call_seq.subscribe(cl, buf, fl_function,
            fl_state, id, &error_code); // XXX: Sending Pointer as uint64
    if (err_is_ok(err)) {
        err = error_code;
    }

    free(buf);
    return err;
}
Exemplo n.º 2
0
/**
 * \brief Client enters a barrier. Blocks until all clients have entered the
 * barrier.
 *
 * Each client creates a (sequential record) based on the provided name.
 * Once a client sees the specified amount (wait_for) of records it
 * creates a record that wakes up all waiting clients.
 *
 * \param[in] name Name of the barrier.
 * \param[out] barrier_record Record created for each client.
 * \param[in] wait_for Number of clients entering the barrier.
 */
errval_t oct_barrier_enter(const char* name, char** barrier_record, size_t wait_for)
{
    errval_t err;
    errval_t exist_err;
    char* record = NULL;
    char** names = NULL;
    uint64_t mode = 0;
    uint64_t state = 0;
    uint64_t fn = 0;
    octopus_trigger_id_t tid;
    size_t current_barriers = 0;
    octopus_trigger_t t = oct_mktrigger(OCT_ERR_NO_RECORD, octopus_BINDING_RPC,
            OCT_ON_SET, NULL, NULL);

    err = oct_set_get(SET_SEQUENTIAL, barrier_record,
            "%s_ { barrier: '%s' }", name, name);
    err = oct_get_names(&names, &current_barriers, "_ { barrier: '%s' }",
            name);
    oct_free_names(names, current_barriers);
    if (err_is_fail(err)) {
        return err;
    }
    //debug_printf("current_barriers: %lu wait_for: %lu\n", current_barriers,
    //        wait_for);

    if (current_barriers != wait_for) {
        struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
        err = cl->call_seq.exists(cl, name, t, &tid, &exist_err);
        if (err_is_fail(err)) {
            return err;
        }
        err = exist_err;

        if (err_is_ok(err)) {
            // Barrier already exists
        }
        if (err_no(err) == OCT_ERR_NO_RECORD) {
            // Wait until barrier record is created
            err = cl->recv.trigger(cl, &tid, &fn, &mode, &record, &state);
            free(record);
            assert(mode & OCT_REMOVED);

            err = SYS_ERR_OK;
        }
        else {
            // Some other error happend, return it
        }
    }
    else {
        // We are the last to enter the barrier,
        // wake up the others
        err = oct_set(name);
    }

    return err;
}
Exemplo n.º 3
0
/**
 * \brief looks up the name and registers a callback
 *
 * \param iface     Name of the domain
 * \param retdomid  returns the Xeon Phi Domain ID
 */
errval_t domain_wait(const char *iface,
                     struct xnode *node,
                     void *state,
                     xphi_dom_id_t *retdom)
{
    errval_t err;

    struct octopus_thc_client_binding_t* c = oct_get_thc_client();
    if (c == NULL) {
        return LIB_ERR_NAMESERVICE_NOT_BOUND;
    }

    struct wait_state *ws = malloc(sizeof(*ws));
    if (ws == NULL) {
        return LIB_ERR_MALLOC_FAIL;
    }

    ws->usr_state = state;
    ws->node = node;

    octopus_mode_t m = OCT_ON_SET;
    octopus_trigger_t iface_set_trigger = oct_mktrigger(
                    OCT_ERR_NO_RECORD, octopus_BINDING_EVENT, m,
                    domain_wait_trigger_handler, ws);

    char* record = NULL;
    errval_t error_code;
    err = c->call_seq.get(c, iface, iface_set_trigger, &record, &ws->tid,
                      &error_code);

    if (err_is_fail(err)) {
        free(record);
        return err;
    }

    if (err_is_fail(error_code)) {
        free(record);
        return error_code;
    }

    free(ws);

    xphi_dom_id_t domid = 0;
    err = oct_read(record, "_ { domid: %d }", &domid);
    if (err_is_fail(err) || domid == 0) {
        err = err_push(err, XEON_PHI_ERR_CLIENT_DOMAIN_VOID);
        free(record);
        return err;
    }

    if (retdom) {
        *retdom = domid;
    }

    return err;
}
Exemplo n.º 4
0
/**
 * \brief Unsubscribes a subscription.
 *
 * \param id Id of the subscription (as provided by oct_subscribe).
 *
 * \retval SYS_ERR_OK
 * \retval OCT_ERR_PARSER_FAIL
 * \retval OCT_ERR_ENGINE_FAIL
 */
errval_t oct_unsubscribe(subscription_t id)
{
    // send to skb
    struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
    errval_t error_code;
    errval_t err = cl->call_seq.unsubscribe(cl, id, &error_code);
    if (err_is_ok(err)) {
        err = error_code;
    }

    return err;
}
Exemplo n.º 5
0
errval_t oct_sem_wait(uint32_t id)
{
    errval_t err = SYS_ERR_OK;
    char* result = NULL;
    octopus_trigger_id_t tid;
    octopus_trigger_t t = oct_mktrigger(OCT_ERR_NO_RECORD,
            octopus_BINDING_RPC, OCT_ON_SET, NULL, NULL);
    struct octopus_thc_client_binding_t* cl = oct_get_thc_client();

    char query[100];
    snprintf(query, 99, "r'sem\\.%"PRIu32"\\.[0-9]+' { sem: %"PRIu32" }", id, id);

    char lock_name[100];
    snprintf(lock_name, 99, "sem.%"PRIu32"", id);

    // XXX: The current implementation suffers from a herd effect,
    // may be worth it to use locks for this critical section
    while (1) {
        cl->call_seq.get(cl, query, t, &result, &tid, &err);

        if (err_is_ok(err)) {
            errval_t del_err = oct_del(result);
            free(result);
            result = NULL;

            if (err_is_ok(del_err)) {
                break; // Decreased successfully
            }
            else if (err_no(del_err) == OCT_ERR_NO_RECORD) {
                continue; // Need to start over
            }
            else {
                err = del_err;
                break; // Unexpected error
            }
        }
        else if (err_no(err) == OCT_ERR_NO_RECORD) {
            // No record found, wait until one is posted
            char* trigger_result = NULL;
            uint64_t fn, mode, state;
            cl->recv.trigger(cl, &tid, &fn, &mode, &trigger_result, &state);
            free(trigger_result);
        }
        else {
            break; // Unexpected error
        }
    }

    free(result);
    return err;
}
Exemplo n.º 6
0
/**
 * \brief Publishes a record.
 *
 * \param record The record to publish.
 * \param ... Additional arguments to format the record using vsprintf.
 *
 * \retval SYS_ERR_OK
 * \retval OCT_ERR_PARSER_FAIL
 * \retval OCT_ERR_ENGINE_FAIL
 */
errval_t oct_publish(const char *record, ...)
{
    assert(record != NULL);

    va_list args;
    errval_t err = SYS_ERR_OK;

    char *buf = NULL;
    FORMAT_QUERY(record, args, buf);

    struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
    errval_t error_code;
    err = cl->call_seq.publish(cl, buf, &error_code);
    if(err_is_ok(err)) {
        err = error_code;
    }

    free(buf);
    return err;
}
Exemplo n.º 7
0
/**
 * \brief Leave a barrier. Blocks until all involved parties have
 * called oct_barrier_leave().
 *
 * Client deletes its barrier record. In case the client
 * was the last one we delete the special record which
 * wakes up all other clients.
 *
 * \param barrier_record Clients own record as provided by
 * oct_barrier_enter.
 */
errval_t oct_barrier_leave(const char* barrier_record)
{
    errval_t exist_err;
    errval_t err;
    char* rec_name = NULL;
    char* barrier_name = NULL;
    char* record = NULL;
    char** names = NULL;
    size_t remaining_barriers = 0;
    uint64_t mode = 0;
    uint64_t state = 0;
    uint64_t fn = 0;
    octopus_trigger_id_t tid;
    octopus_trigger_t t = oct_mktrigger(SYS_ERR_OK, octopus_BINDING_RPC,
            OCT_ON_DEL, NULL, NULL);

    //debug_printf("leaving: %s\n", barrier_record);
    err = oct_read(barrier_record, "%s { barrier: %s }", &rec_name,
            &barrier_name);
    if (err_is_ok(err)) {
        err = oct_del(rec_name);
        if (err_is_fail(err)) {
            goto out;
        }

        err = oct_get_names(&names, &remaining_barriers, "_ { barrier: '%s' }",
                barrier_name);
        oct_free_names(names, remaining_barriers);

        //debug_printf("remaining barriers is: %lu\n", remaining_barriers);

        if (err_is_ok(err)) {
            struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
            err = cl->call_seq.exists(cl, barrier_name, t, &tid, &exist_err);
            if (err_is_fail(err)) {
                goto out;
            }
            err = exist_err;

            if (err_is_ok(err)) {
                // Wait until everyone has left the barrier
                err = cl->recv.trigger(cl, &tid, &fn, &mode, &record, &state);
                assert(mode & OCT_REMOVED);
            }
            else if (err_no(err) == OCT_ERR_NO_RECORD) {
                // barrier already deleted
                err = SYS_ERR_OK;
            }
        }
        else if (err_no(err) == OCT_ERR_NO_RECORD) {
            // We are the last one to leave the barrier,
            // wake-up all others
            err = oct_del("%s", barrier_name);
        }
        else {
            // Just return the error
        }
    }

out:
    free(record);
    free(rec_name);
    free(barrier_name);
    return err;
}
Exemplo n.º 8
0
int main(int argc, char *argv[])
{
    oct_init();
    errval_t err = SYS_ERR_OK;
    octopus_trigger_id_t tid;
    size_t received = 0;

    err = oct_set("obj1 { attr: 1 }");
    ASSERT_ERR_OK(err);
    err = oct_set("obj2 { attr: 2 }");
    ASSERT_ERR_OK(err);
    err = oct_set("obj3 { attr: 3 }");
    ASSERT_ERR_OK(err);

    struct octopus_thc_client_binding_t* c = oct_get_thc_client();

    octopus_trigger_t record_deleted = oct_mktrigger(SYS_ERR_OK,
            octopus_BINDING_EVENT, OCT_ON_DEL, trigger_handler, &received);

    errval_t error_code = SYS_ERR_OK;
    char* output = NULL;
    err = c->call_seq.get(c, "r'^obj.$' { attr: 3 } ", record_deleted, &output,
            &tid, &error_code);
    ASSERT_ERR_OK(err);
    ASSERT_ERR_OK(error_code);
    ASSERT_STRING(output, "obj3 { attr: 3 }");
    debug_printf("tid is: %lu\n", tid);
    free(output);

    oct_del("obj3");
    while (received != 1) {
        messages_wait_and_handle_next();
    }

    received = 0;
    tid = 0;
    octopus_mode_t m = OCT_ON_SET | OCT_ON_DEL | OCT_PERSIST;
    octopus_trigger_t ptrigger = oct_mktrigger(SYS_ERR_OK,
            octopus_BINDING_EVENT, m, persistent_trigger, &received);
    output = NULL;
    err = c->call_seq.get(c, "obj2", ptrigger, &output,
            &tid, &error_code);
    ASSERT_ERR_OK(err);
    ASSERT_ERR_OK(error_code);
    debug_printf("tid is: %lu\n", tid);
    ASSERT_STRING(output, "obj2 { attr: 2 }");

    oct_del("obj2");
    while (received != 1) {
        messages_wait_and_handle_next();
    }

    received = 0;
    oct_set("obj2 { attr: 'asdf' }");
    while (received != 1) {
        messages_wait_and_handle_next();
    }

    received = 0;
    err = oct_remove_trigger(tid);
    DEBUG_ERR(err, "remove trigger");
    ASSERT_ERR_OK(err);
    while (received != 1) {
        messages_wait_and_handle_next();
    }

    printf("d2trigger SUCCESS!\n");
    return EXIT_SUCCESS;
}