diff options
Diffstat (limited to 'xlators/cluster/ec/src/ec-data.c')
| -rw-r--r-- | xlators/cluster/ec/src/ec-data.c | 261 | 
1 files changed, 261 insertions, 0 deletions
diff --git a/xlators/cluster/ec/src/ec-data.c b/xlators/cluster/ec/src/ec-data.c new file mode 100644 index 00000000000..0e72fbbd3b6 --- /dev/null +++ b/xlators/cluster/ec/src/ec-data.c @@ -0,0 +1,261 @@ +/* +  Copyright (c) 2012 DataLab, s.l. <http://www.datalab.es> + +  This file is part of the cluster/ec translator for GlusterFS. + +  The cluster/ec translator for GlusterFS is free software: you can +  redistribute it and/or modify it under the terms of the GNU General +  Public License as published by the Free Software Foundation, either +  version 3 of the License, or (at your option) any later version. + +  The cluster/ec translator for GlusterFS 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 General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with the cluster/ec translator for GlusterFS. If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include "ec-mem-types.h" +#include "ec-helpers.h" +#include "ec-common.h" +#include "ec-data.h" + +ec_cbk_data_t * ec_cbk_data_allocate(call_frame_t * frame, xlator_t * this, +                                     ec_fop_data_t * fop, int32_t id, +                                     int32_t idx, int32_t op_ret, +                                     int32_t op_errno) +{ +    ec_cbk_data_t * cbk; +    ec_t * ec = this->private; + +    if (fop->xl != this) +    { +        gf_log(this->name, GF_LOG_ERROR, "Mismatching xlators between request " +                                         "and answer (req=%s, ans=%s).", +                                         fop->xl->name, this->name); + +        return NULL; +    } +    if (fop->frame != frame) +    { +        gf_log(this->name, GF_LOG_ERROR, "Mismatching frames between request " +                                         "and answer (req=%p, ans=%p).", +                                         fop->frame, frame); + +        return NULL; +    } +    if (fop->id != id) +    { +        gf_log(this->name, GF_LOG_ERROR, "Mismatching fops between request " +                                         "and answer (req=%d, ans=%d).", +                                         fop->id, id); + +        return NULL; +    } + +    cbk = mem_get0(ec->cbk_pool); +    if (cbk == NULL) +    { +        gf_log(this->name, GF_LOG_ERROR, "Failed to allocate memory for an " +                                         "answer."); +    } + +    cbk->fop = fop; +    cbk->idx = idx; +    cbk->mask = 1ULL << idx; +    cbk->count = 1; +    cbk->op_ret = op_ret; +    cbk->op_errno = op_errno; + +    LOCK(&fop->lock); + +    list_add_tail(&cbk->answer_list, &fop->answer_list); + +    UNLOCK(&fop->lock); + +    return cbk; +} + +void ec_cbk_data_destroy(ec_cbk_data_t * cbk) +{ +    if (cbk->xdata != NULL) +    { +        dict_unref(cbk->xdata); +    } +    if (cbk->dict != NULL) +    { +        dict_unref(cbk->dict); +    } +    if (cbk->inode != NULL) +    { +        inode_unref(cbk->inode); +    } +    if (cbk->fd != NULL) +    { +        fd_unref(cbk->fd); +    } +    if (cbk->buffers != NULL) +    { +        iobref_unref(cbk->buffers); +    } +    GF_FREE(cbk->vector); + +    mem_put(cbk); +} + +ec_fop_data_t * ec_fop_data_allocate(call_frame_t * frame, xlator_t * this, +                                     int32_t id, uint32_t flags, +                                     uintptr_t target, int32_t minimum, +                                     ec_wind_f wind, ec_handler_f handler, +                                     ec_cbk_t cbks, void * data) +{ +    ec_fop_data_t * fop, * parent; +    ec_t * ec = this->private; + +    fop = mem_get0(ec->fop_pool); +    if (fop == NULL) +    { +        gf_log(this->name, GF_LOG_ERROR, "Failed to allocate memory for a " +                                         "request."); + +        return NULL; +    } + +    fop->xl = this; +    fop->req_frame = frame; + +    /* fops need a private frame to be able to execute some postop operations +     * even if the original fop has completed and reported back to the upper +     * xlator and it has destroyed the base frame. +     * +     * TODO: minimize usage of private frames. Reuse req_frame as much as +     *       possible. +     */ +    if (frame != NULL) +    { +        fop->frame = copy_frame(frame); +    } +    else +    { +        fop->frame = create_frame(this, this->ctx->pool); +    } +    if (fop->frame == NULL) +    { +        gf_log(this->name, GF_LOG_ERROR, "Failed to create a private frame " +                                         "for a request"); + +        mem_put(fop); + +        return NULL; +    } +    fop->id = id; +    fop->refs = 1; + +    fop->flags = flags; +    fop->minimum = minimum; +    fop->mask = target; + +    INIT_LIST_HEAD(&fop->lock_list); +    INIT_LIST_HEAD(&fop->cbk_list); +    INIT_LIST_HEAD(&fop->answer_list); + +    fop->wind = wind; +    fop->handler = handler; +    fop->cbks = cbks; +    fop->data = data; + +    LOCK_INIT(&fop->lock); + +    fop->frame->local = fop; + +    if (frame != NULL) +    { +        parent = frame->local; +        if (parent != NULL) +        { +            LOCK(&parent->lock); + +            parent->jobs++; +            parent->refs++; + +            UNLOCK(&parent->lock); +        } + +        fop->parent = parent; +    } + +    return fop; +} + +void ec_fop_data_acquire(ec_fop_data_t * fop) +{ +    LOCK(&fop->lock); + +    ec_trace("ACQUIRE", fop, ""); + +    fop->refs++; + +    UNLOCK(&fop->lock); +} + +void ec_fop_data_release(ec_fop_data_t * fop) +{ +    ec_cbk_data_t * cbk, * tmp; +    int32_t refs; + +    LOCK(&fop->lock); + +    ec_trace("RELEASE", fop, ""); + +    refs = --fop->refs; + +    UNLOCK(&fop->lock); + +    if (refs == 0) +    { +        fop->frame->local = NULL; +        STACK_DESTROY(fop->frame->root); + +        LOCK_DESTROY(&fop->lock); + +        if (fop->xdata != NULL) +        { +            dict_unref(fop->xdata); +        } +        if (fop->dict != NULL) +        { +            dict_unref(fop->dict); +        } +        if (fop->inode != NULL) +        { +            inode_unref(fop->inode); +        } +        if (fop->fd != NULL) +        { +            fd_unref(fop->fd); +        } +        if (fop->buffers != NULL) +        { +            iobref_unref(fop->buffers); +        } +        GF_FREE(fop->vector); +        GF_FREE(fop->str[0]); +        GF_FREE(fop->str[1]); +        loc_wipe(&fop->loc[0]); +        loc_wipe(&fop->loc[1]); + +        ec_resume_parent(fop, fop->error); + +        list_for_each_entry_safe(cbk, tmp, &fop->answer_list, answer_list) +        { +            list_del_init(&cbk->answer_list); + +            ec_cbk_data_destroy(cbk); +        } + +        mem_put(fop); +    } +}  | 
