示例#1
0
/// Clear out the raw set and cooked sets. Destroy the entire
/// cooked data structure but leave the raw one present though
/// empty. This is the same as the initial (post-creation) state.
/// @param[in] ca       the object pointer
void
ca_clear_pa(ca_o ca)
{
    dict_t *dict;
    dnode_t *dnp, *next;
    pa_o pa;

    if ((dict = ca->ca_raw_pa_dict)) {
        for (dnp = dict_first(dict); dnp;) {
            next = dict_next(dict, dnp);

            pa = (pa_o)dnode_getkey(dnp);
            dict_delete(dict, dnp);
            dnode_destroy(dnp);
            pa_destroy(pa);
            dnp = next;
        }
    }

    if ((dict = ca->ca_cooked_pa_dict)) {
        for (dnp = dict_first(dict); dnp;) {
            next = dict_next(dict, dnp);

            pa = (pa_o)dnode_getkey(dnp);
            dict_delete(dict, dnp);
            dnode_destroy(dnp);
            pa_destroy(pa);
            dnp = next;
        }
        dict_destroy(ca->ca_cooked_pa_dict);
        ca->ca_cooked_pa_dict = NULL;
    }
}
示例#2
0
文件: dlist.c 项目: jcomo/allocator
void *
dlist_remove_back(struct dlist *l) {

  if (l->counter) {
    struct dnode *remove = l->back;
    l->back = l->back->prev;
    if (l->back) l->back->next = NULL;

    l->counter--;
    return dnode_destroy(remove);
  } else {
    return NULL;
  }
}
示例#3
0
文件: dlist.c 项目: jcomo/allocator
void *
dlist_remove_front(struct dlist *l) {

  if (l->counter) {
    struct dnode *remove = l->front;
    l->front = l->front->next;
    if (l->front) l->front->prev = NULL; // account for case with
                                         // 1 element in list

    l->counter--;
    return dnode_destroy(remove);
  } else {
    return NULL;
  }
}
示例#4
0
/// Merge two CmdActions, a 'leader' and a 'donor', together. The donor
/// is then redundant.
/// @param[in] leader   the leader object pointer
/// @param[in] donor    the donor object pointer
void
ca_merge(ca_o leader, ca_o donor)
{
    CCS sub;
    dict_t *dict;
    dnode_t *dnp, *next;
    pa_o pa;

    // ASSUMPTION: aggregated CAs are composed from
    // commands run serially - i.e. any parallelism
    // is above the build-script level.

    // Stringify the donor and leave that string representation in
    // the leader for the record.
    sub = ca_format_header(donor);
    if (leader->ca_subs) {
        leader->ca_subs = (CCS)putil_realloc((void *)leader->ca_subs,
                                             (strlen(leader->ca_subs) +
                                              strlen(sub) +
                                              1) * CHARSIZE);
        strcat((CS)leader->ca_subs, sub);
    } else {
        leader->ca_subs = (CCS)putil_malloc((strlen(sub) + 1) * CHARSIZE);
        strcpy((CS)leader->ca_subs, sub);
    }
    putil_free(sub);

    // Traverse the donor's raw list of PA's and move them into the leader's.
    if ((dict = donor->ca_raw_pa_dict)) {
        for (dnp = dict_first(dict); dnp;) {
            next = dict_next(dict, dnp);

            pa = (pa_o)dnode_getkey(dnp);
            ca_record_pa(leader, pa);
            dict_delete(dict, dnp);
            dnode_destroy(dnp);
            dnp = next;
        }
        dict_destroy(donor->ca_raw_pa_dict);
        donor->ca_raw_pa_dict = NULL;
    }
}
示例#5
0
static void construct(dict_t *d)
{
    input_t in;
    int done = 0;
    dict_load_t dl;
    dnode_t *dn;
    char *tok1, *tok2, *val;
    const char *key;
    char *help =
        "p                      turn prompt on\n"
        "q                      finish construction\n"
        "a <key> <val>          add new entry\n";

    if (!dict_isempty(d))
        puts("warning: dictionary not empty!");

    dict_load_begin(&dl, d);

    while (!done) {
        if (prompt)
            putchar('>');
        fflush(stdout);

        if (!fgets(in, sizeof(input_t), stdin))
            break;

        switch (in[0]) {
            case '?':
                puts(help);
                break;
            case 'p':
                prompt = 1;
                break;
            case 'q':
                done = 1;
                break;
            case 'a':
                if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
                    puts("what?");
                    break;
                }
                key = dupstring(tok1);
                val = dupstring(tok2);
                dn = dnode_create(val);

                if (!key || !val || !dn) {
                    puts("out of memory");
                    free((void *) key);
                    free(val);
                    if (dn)
                        dnode_destroy(dn);
                }

                dict_load_next(&dl, dn, key);
                break;
            default:
                putchar('?');
                putchar('\n');
                break;
        }
    }

    dict_load_end(&dl);
}
示例#6
0
/// Convert all raw PAs in the group into a single set of "cooked" PAs
/// under the leader.
/// @param[in] ca       the object pointer
void
ca_coalesce(ca_o ca)
{
    dict_t *dict_raw, *dict_cooked;
    dnode_t *dnpr, *dnpc, *next;

    dict_raw = ca->ca_raw_pa_dict;

    assert(!ca->ca_cooked_pa_dict);
    if ((dict_cooked = dict_create(DICTCOUNT_T_MAX, pa_cmp_by_pathname))) {
        ca->ca_cooked_pa_dict = dict_cooked;
    } else {
        putil_syserr(2, "dict_create()");
    }

    for (dnpr = dict_first(dict_raw); dnpr;) {
        pa_o raw_pa, ckd_pa;

        next = dict_next(dict_raw, dnpr);

        raw_pa = (pa_o)dnode_getkey(dnpr);

        _ca_verbosity_pa(raw_pa, ca, "COALESCING");

        // All data is in the key - that's why the value can be null.
        if ((dnpc = dict_lookup(dict_cooked, raw_pa))) {
            int keep_cooked = 0;

            ckd_pa = (pa_o)dnode_getkey(dnpc);

            if (!pa_is_read(raw_pa) && !pa_is_read(ckd_pa)) {
                moment_s raw_timestamp, ckd_timestamp;

                // If they're both destructive ops (non-read) then we
                // need to consider timestamps and use the later one.

                if (pa_has_timestamp(raw_pa) && pa_has_timestamp(ckd_pa)) {
                    // If the PA's have their own timestamps, use them.
                    raw_timestamp = pa_get_timestamp(raw_pa);
                    ckd_timestamp = pa_get_timestamp(ckd_pa);
                } else {
                    // Otherwise key off the file times. This is for
                    // support of "dummy" PAs as used in shopping.
                    raw_timestamp = pa_get_moment(raw_pa);
                    ckd_timestamp = pa_get_moment(ckd_pa);
                }

                if (moment_cmp(raw_timestamp, ckd_timestamp, NULL) <= 0) {
                    // Cooked write op is newer and can stay.
                    keep_cooked = 1;
                }
            } else if (pa_is_read(raw_pa)) {
                // There's no point replacing a read with another read,
                // so regardless of whether the current cooked PA is a
                // read or write, it can stay.
                keep_cooked = 1;
            } else {
                // A write always beats a read.
            }

            if (!keep_cooked) {
                dict_delete(dict_cooked, dnpc);
                dnode_destroy(dnpc);
                _ca_verbosity_pa(ckd_pa, ca, "REMOVING");
                pa_destroy(ckd_pa);
                if (!(dnpc = dnode_create(NULL))) {
                    putil_syserr(2, "dnode_create()");
                }
                ckd_pa = pa_copy(raw_pa);
                dict_insert(dict_cooked, dnpc, ckd_pa);
            }
        } else {
            if (!(dnpc = dnode_create(NULL))) {
                putil_syserr(2, "dnode_create()");
            }
            ckd_pa = pa_copy(raw_pa);
            dict_insert(dict_cooked, dnpc, ckd_pa);
        }

        // Clean up the raw set as we move PAs to the cooked one.
        dict_delete(dict_raw, dnpr);
        dnode_destroy(dnpr);
        dnpr = next;
    }

    return;
}