Exemplo n.º 1
0
void 
dlist_add_back(struct dlist *l, void *ptr) {

  // create the node to be added in
  struct dnode *new_node = dnode_create();
  dnode_setdata(new_node, ptr);

  // update pointers

  if (!l->counter) { // list is empty
    l->front = l->back = new_node;
    new_node->next = new_node->prev = NULL;
  } else {
    struct dnode *n = l->back;
    new_node->prev = n;
    new_node->next = NULL;
    l->back->next = new_node;
    l->back = new_node;
  }

  l->counter++;

#ifdef DEBUG
  printf("counter= %d, %s\n", l->counter, (char *) ptr);
  printf("front= %s\n", (char *) l->front->data);
  printf("back= %s\n\n", (char *) l->back->data);
#endif /* DEBUG */
}
Exemplo n.º 2
0
/// Add a new PathAction into the specified CmdAction.
/// No coalescing is attempted - PA objects are are always added
/// here unless they are truly identical (same pointer == same object).
/// @param[in] ca       the CA object pointer
/// @param[in] pa       the PA object pointer
void
ca_record_pa(ca_o ca, pa_o pa)
{
    dnode_t *dnp;

    _ca_verbosity_pa(pa, ca, "RECORDING");

    // All data is in the key - that's why the value can be null.
    if (!(dnp = dnode_create(NULL))) {
        putil_syserr(2, "dnode_create()");
    }
    dict_insert(ca->ca_raw_pa_dict, dnp, pa);
}
Exemplo n.º 3
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);
}
Exemplo n.º 4
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;
}