Beispiel #1
0
void lease_add(Lease *lease) {
    List *exits = lease->wavefront;

    assert(!lease->isexit || null(exits));

    hash_set(lease_by_root_pathname, lease->pathname, lease);
    for ( ; !null(exits); exits = cdr(exits)) {
        Lease *exit = car(exits);
        assert(exit->isexit);
        hash_set(lease_by_root_pathname, exit->pathname, exit);
    }

    lease->lastchange = now_double();
}
Beispiel #2
0
Lease *lease_new(char *pathname, Address *addr, int isexit, Claim *claim,
        int readonly)
{
    Lease *l = GC_NEW(Lease);
    assert(l != NULL);

    l->wait_for_update = NULL;
    l->inflight = 0;

    l->changeinprogress = 0;
    l->changeexits = NULL;
    l->changefids = NULL;

    l->pathname = pathname;
    l->addr = addr;

    l->wavefront = NULL;

    l->isexit = isexit;

    if (isexit) {
        l->claim = NULL;
        l->fids = NULL;
        l->claim_cache = NULL;
        l->dir_cache = NULL;
    } else {
        l->claim = claim;
        l->claim->lease = l;
        l->fids = hash_create(LEASE_FIDS_HASHTABLE_SIZE,
                (Hashfunc) fid_hash,
                (Cmpfunc) fid_cmp);
        l->claim_cache = hash_create(
                LEASE_CLAIM_HASHTABLE_SIZE,
                (Hashfunc) string_hash,
                (Cmpfunc) strcmp);
        l->dir_cache = hash_create(
                LEASE_DIR_HASHTABLE_SIZE,
                (Hashfunc) dir_block_hash,
                (Cmpfunc) dir_block_cmp);
    }

    l->readonly = readonly;
    l->lastchange = now_double();

    return l;
}
Beispiel #3
0
void lease_remove(Lease *lease) {
    assert(null(lease->wavefront));
    assert(lease->fids == NULL || hash_count(lease->fids) == 0);
    assert(null(lease->changeexits));
    assert(null(lease->changefids));

    if (lease->isexit) {
        lease_unlink_exit(lease);
    } else {
        claim_clear_descendents(lease->claim);
        lease_clear_dir_cache(lease);
    }

    hash_remove(lease_by_root_pathname, lease->pathname);
    lease->pathname = NULL;
    lease->addr = NULL;
    lease->claim = NULL;
    lease->lastchange = now_double();
}
Beispiel #4
0
void lease_merge_exit(Worker *worker, Lease *parent, Lease *child) {
    Claim *claim;
    assert(parent->wait_for_update == worker &&
            child->wait_for_update == worker);
    assert(parent->inflight == 0 && child->inflight == 0);
    assert(!child->isexit && !parent->isexit);
    /* assert(!parent->readonly);
    assert(!child->readonly); */

    /* prevent lookups on the old lease */
    hash_remove(lease_by_root_pathname, child->pathname);

    /* find the immediate parent and add this child */
    claim = claim_find(worker, dirname(child->pathname));
    assert(claim != NULL && claim->lease == parent);
    claim_link_child(claim, child->claim);

    /* merge the fids */
    hash_apply(child->fids, (void (*)(void *, void *, void *)) hash_set,
            parent->fids);
    child->fids = NULL;

    /* merge the claim cache */
    hash_apply(child->claim_cache,
            (void (*)(void *, void *, void *)) lease_merge_iter_claim_cache,
            parent);
    child->claim_cache = NULL;

    /* merge the dir cache */
    hash_apply(child->dir_cache,
            (void (*)(void *, void *, void *)) lease_merge_iter_dir_cache,
            parent);
    child->dir_cache = NULL;

    /* merge in the wavefront */
    for ( ; !null(child->wavefront); child->wavefront = cdr(child->wavefront))
        lease_link_exit((Lease *) car(child->wavefront));

    parent->lastchange = now_double();
}
Beispiel #5
0
int main(int argc, char **argv) {
    test_state tstate = {0};
    nitro_queue_t *q = nitro_queue_new(0, 
    test_state_callback, &tstate);
    TEST("new non-null", q);

    nitro_frame_t *hello = nitro_frame_new_copy(
        "hello", 6);

    nitro_queue_push(q, hello, 1);
    TEST("queue went contents", 
        tstate.got_state_change 
        && tstate.state_was == NITRO_QUEUE_STATE_CONTENTS);
    tstate.got_state_change = 0;

    nitro_frame_t *back = nitro_queue_pull(q, 1);
    TEST("got frame back", 
        back == hello);
    TEST("queue went empty", 
        tstate.got_state_change 
        && tstate.state_was == NITRO_QUEUE_STATE_EMPTY);
    tstate.got_state_change = 0;


    /* Ordering */
    nitro_frame_t *world = nitro_frame_new_copy(
        "world", 6);
    nitro_queue_push(q, hello, 1);
    nitro_queue_push(q, world, 1);

    back = nitro_queue_pull(q, 1);
    TEST("got hello (ordering)", 
        back == hello);
    back = nitro_queue_pull(q, 1);
    TEST("got world (ordering)", 
        back == world);

    nitro_queue_destroy(q);
    q = nitro_queue_new(0, 
    test_state_callback, &tstate);

    /* Wrapping */
    TEST("pre-wrapping empty queue", nitro_queue_count(q) == 0);
    TEST("pre-wrapping internal assumption", q->size == 1024);

    int i;
    for (i=0; i < 1023; i++) {
        nitro_frame_t *hcopy = nitro_frame_copy_partial(hello, NULL);
        nitro_queue_push(q, hcopy, 1);
        back = nitro_queue_pull(q, 1);
        assert(back == hcopy);
        nitro_frame_destroy(back);
    }


    nitro_queue_push(q, hello, 1);
    nitro_queue_push(q, world, 1);

    TEST("wrapping internals, wrap occurred",
    q->tail < q->head);

    back = nitro_queue_pull(q, 1);
    TEST("got hello (wrapping)", 
        back == hello);
    back = nitro_queue_pull(q, 1);
    TEST("got world (wrapping)", 
        back == world);

    TEST("wrapping internals, wrap back to even",
    q->tail == q->head);

    /* Destroy with frames in */

    my_frame_data dt = {0};

    nitro_frame_destroy(world);
    world = nitro_frame_new(
    "hello", 6, my_free, &dt);

    nitro_queue_push(q, world, 1);

    TEST("delete outstanding.. not deleted",
    dt.done == 0);

    nitro_queue_destroy(q);

    TEST("post-queue-delete.. frame free",
    dt.done);

    nitro_frame_destroy(hello);

    /* Queue count */

    q = nitro_queue_new(0,
    test_state_callback, &tstate);

    hello = nitro_frame_new_copy("hello", 6);

    for (i=0; i < 313; i++) {
        back = nitro_frame_copy_partial(hello, NULL);
        nitro_queue_push(q, back, 1);
    }

    nitro_frame_destroy(hello);


    TEST("count basic", nitro_queue_count(q) == 313);

    /* resize */
    nitro_queue_destroy(q);
    q = nitro_queue_new(0,
    test_state_callback, &tstate);
    assert(q->size == 1024);

    /* get the alignment off */
    for (i=0; i < 100; i++) {
        nitro_queue_push(q,
            nitro_frame_new_copy((void*)&i, sizeof(int)), 1);
    }

    for (i=0; i < 100; i++) {
        back = nitro_queue_pull(q, 1);
        nitro_frame_destroy(back);
    }

    TEST("resize misalign reset", nitro_queue_count(q) == 0 &&
    q->head > q->q);

    /* okay, now cause resize */
    for (i=0; i < 1050; i++) {
        nitro_queue_push(q,
            nitro_frame_new_copy((void*)&i, sizeof(int)), 1);
    }

    TEST("was resized", q->size > 1024);

    for (i=0; i < 1050; i++) {
        back = nitro_queue_pull(q, 1);
        if ( *((int*)nitro_frame_data(back)) != i)
            break;
        nitro_frame_destroy(back);
    }

    TEST("order after resize", i == 1050);

    nitro_queue_destroy(q);

    /* Test queue moving */

    /* move 0 -> 0 */
    q = nitro_queue_new(0,
    test_state_callback, &tstate);
    nitro_queue_t *dst = nitro_queue_new(0,
    test_state_callback, &tstate);

    nitro_queue_move(
    q, dst);
    TEST("move(0->0) src empty",
    nitro_queue_count(q) == 0);
    TEST("move(0->0) dest empty",
    nitro_queue_count(dst) == 0);

    /* move N -> 0 */

    for (i=0; i < 5; i++) {
        nitro_queue_push(q,
            nitro_frame_new_copy(
            (void *)&i, sizeof(int)), 1);
    }

    TEST("load 5 into src",
    nitro_queue_count(q) == 5);
    nitro_queue_move(q, dst);
    TEST("move(0->0) src empty",
    nitro_queue_count(q) == 0);
    TEST("move(0->0) dest 5",
    nitro_queue_count(dst) == 5);

    for (i=0; i < 5; i++) {
        back = nitro_queue_pull(dst, 1);
        if ( *((int*)nitro_frame_data(back)) != i)
            break;
        nitro_frame_destroy(back);
    }

    TEST("order after move", i == 5);

    nitro_queue_destroy(q);
    nitro_queue_destroy(dst);

    /* move with fractional wraparound, ugly copies */
    q = nitro_queue_new(0,
    test_state_callback, &tstate);
    dst = nitro_queue_new(0,
    test_state_callback, &tstate);

    for (i=0; i < 300; i++) {
        nitro_queue_push(q,
            nitro_frame_new_copy(
            (void *)&i, sizeof(int)), 1);
    }
    for (i=0; i < 300; i++) {
        nitro_frame_destroy(nitro_queue_pull(q, 1));
    }
    for (i=0; i < 700; i++) {
        nitro_queue_push(q,
            nitro_frame_new_copy(
            (void *)&i, sizeof(int)), 1);
    }

    for (i=0; i < 324; i++) {
        nitro_queue_push(dst,
            nitro_frame_new_copy(
            (void *)&i, sizeof(int)), 1);
    }
    for (i=0; i < 324; i++) {
        nitro_frame_destroy(nitro_queue_pull(dst, 1));
    }
    for (i=0; i < 324; i++) {
        nitro_queue_push(dst,
            nitro_frame_new_copy(
            (void *)&i, sizeof(int)), 1);
    }

    TEST("(ugly move) count 700 src",
    nitro_queue_count(q) == 700);
    TEST("(ugly move) count 324 dst",
    nitro_queue_count(dst) == 324);

    nitro_queue_move(q, dst);
    TEST("(ugly move post) count 0 src",
    nitro_queue_count(q) == 0);
    TEST("(ugly move post) count 1024 dst",
    nitro_queue_count(dst) == 1024);
    assert(dst->size == 1024); /* no resizing! */
    TEST("(ugly move post) head == tail",
    dst->head == dst->tail);

    for (i=0; i < 324; i++) {
        back = nitro_queue_pull(dst, 1);
        if ( *((int*)nitro_frame_data(back)) != i)
            break;
        nitro_frame_destroy(back);
    }
    TEST("(ugly move post) first 324 still there",
    i == 324);
    for (i=0; i < 700; i++) {
        back = nitro_queue_pull(dst, 1);
        if ( *((int*)nitro_frame_data(back)) != i)
            break;
        nitro_frame_destroy(back);
    }
    TEST("(ugly move post) appended 700 there",
    i == 700);
    TEST("(ugly move post) dst emptied",
    nitro_queue_count(dst) == 0);

    nitro_queue_destroy(q);
    nitro_queue_destroy(dst);

    /* move with resize */
    q = nitro_queue_new(0,
    test_state_callback, &tstate);
    dst = nitro_queue_new(0,
    test_state_callback, &tstate);

    for (i=0; i < 1000; i++) {
        nitro_queue_push(q,
            nitro_frame_new_copy(
            (void *)&i, sizeof(int)), 1);
    }

    for (i=0; i < 324; i++) {
        nitro_queue_push(dst,
            nitro_frame_new_copy(
            (void *)&i, sizeof(int)), 1);
    }

    TEST("(resize move) count 1000 src",
    nitro_queue_count(q) == 1000);
    TEST("(resize move) count 324 dst",
    nitro_queue_count(dst) == 324);
    assert(dst->size == 1024);
    nitro_queue_move(q, dst);
    TEST("(resize post-move) size dst is sum",
    nitro_queue_count(dst) == 1324);
    assert(dst->size > 1024);

    for (i=0; i < 324; i++) {
        back = nitro_queue_pull(dst, 1);
        if ( *((int*)nitro_frame_data(back)) != i)
            break;
        nitro_frame_destroy(back);
    }
    TEST("(resize post-move) first 324 still there",
    i == 324);
    for (i=0; i < 1000; i++) {
        back = nitro_queue_pull(dst, 1);
        if ( *((int*)nitro_frame_data(back)) != i)
            break;
        nitro_frame_destroy(back);
    }
    TEST("(resize post-move) appended 1000 there",
    i == 1000);
    TEST("(resize post-move) dst cleared",
    nitro_queue_count(dst) == 0);

    nitro_queue_destroy(q);
    nitro_queue_destroy(dst);

    /* Capacity tests */

    q = nitro_queue_new(5,
    test_state_callback, &tstate);

    for (i=0; i < 5; i++) {
        nitro_queue_push(q,
            nitro_frame_new_copy(
            (void *)&i, sizeof(int)), 1);
    }

    double d1 = now_double();
    pthread_t t1;
    pthread_create(&t1, NULL, take_item, (void*)q);
    nitro_queue_push(q,
        nitro_frame_new_copy(
        (void *)&i, sizeof(int)), 1);
    double d2 = now_double();
    TEST("(capacity) got blocked on push",
    (d2 - d1 > 0.7) && (d2 - d1 < 1.5));

    for (i=1; i < 6; i++) {
        back = nitro_queue_pull(q, 1);
        if ( *((int*)nitro_frame_data(back)) != i)
            break;
        nitro_frame_destroy(back);
    }
    TEST("(capacity) have rest",
    i == 6);
    TEST("(capacity) emptied",
    nitro_queue_count(q) == 0);
    pthread_t t2;

    d1 = now_double();
    pthread_create(&t2, NULL, put_item, (void*)q);
    back = nitro_queue_pull(q, 1);
    d2 = now_double();
    TEST("(capacity) got blocked on empty pull",
    (d2 - d1 > 0.7) && (d2 - d1 < 1.5));
    TEST("(capacity) empty pull got right frame",
    *((int*)nitro_frame_data(back)) == 1337);
    nitro_frame_destroy(back);

    nitro_queue_destroy(q);

    void *unused;
    pthread_join(t1, &unused);
    pthread_join(t2, &unused);


    /* Consume */
    q = nitro_queue_new(0,
    test_state_callback, &tstate);

    gframe = nitro_frame_new_copy("hello", 6);

    /* Traditional test */
    d1 = now_double();
    for (i=0; i < CONSUME_COUNT; i++) {
        nitro_queue_push(q,
            nitro_frame_copy_partial(gframe, NULL), 1);
    }
    d2 = now_double();

    char buf[50];
    snprintf(buf, 50, "(consume-manual) in %.4f",
    d2 - d1);
    TEST(buf, nitro_queue_count(q) == CONSUME_COUNT);
    nitro_queue_destroy(q);

    // vs consume
    i = 0;
    q = nitro_queue_new(0,
    test_state_callback, &tstate);
    d1 = now_double();
    nitro_queue_consume(q,
        make_frames, (void *)&i);
    d2 = now_double();
    snprintf(buf, 50, "(consume-stream) in %.4f",
    d2 - d1);
    TEST(buf, nitro_queue_count(q) == CONSUME_COUNT);
    nitro_queue_destroy(q);

    nitro_frame_destroy(gframe);

    /* Write to file */

    q = nitro_queue_new(0,
    test_state_callback, &tstate);
    for (i=0; i < 50000; i++) {
        nitro_queue_push(q,
            nitro_frame_new_copy(
                "dog", 3), 1);
    }

    int ps[2];
    int r = pipe(ps);
    assert(!r);

    int pread = ps[0];
    int pwrite = ps[1];

    int flag = 1;
    r = ioctl(pread, FIONBIO, &flag);
    assert(r == 0);
    r = ioctl(pwrite, FIONBIO, &flag);
    assert(r == 0);

    int bytes = 0;
    int total = 0;
    nitro_frame_t *remain = NULL;
    pthread_t reader;
    char out[550000];
    pipe_pass pp = {out, pread};
    pthread_create(&reader, NULL, pipe_consume, &pp);
    do {
        errno = 0;
        if (bytes > 0)
            total += bytes;
        bytes = nitro_queue_fd_write(
            q, pwrite, remain, &remain);
    } while (bytes > 0 || errno == EAGAIN || errno == EWOULDBLOCK);
    if (bytes < 0) {
        perror("write to pipe:");
        assert(bytes == 0);
    }

    TEST("(fd write) correct write byte count",
    total == 550000);

    void *t_ret;
    /* wait for reader to finish */
    pthread_join(reader, &t_ret);

    char *ptr = out;
    nitro_protocol_header target_head = {
        1,
        0,
        0,
        0,
        3};

    for (i=0; i < 50000; i++) {
        if (memcmp(ptr, &target_head, sizeof(target_head)) ||
            memcmp(ptr + sizeof(target_head), "dog", 3)) {
            break;
        }
        ptr += 11;
    }

    TEST("(fd write) read data was correct",
    ptr == out + 550000);

    close(pwrite);
    close(pread);


    nitro_queue_destroy(q);

    SUMMARY(0);
    return 1;
}
/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */

#include "chaosutil.h"

static double samples[10000000];
static size_t sample_count = 0;

/* Given command-line parameters <S>, <T>, <D> and <L>:
   Spins the CPU on a single thread until L microseconds have elapsed.
   The test fails if, at some point starting between S and T microseconds,
   we fail to be scheduled for D microseconds */

int main(__attribute__((unused)) int argc, char** argv) {
  double start = now_double();
  double S = atoi(argv[1]) / 1000000.0 + start;
  double T = atoi(argv[2]) / 1000000.0 + start;
  double D = atoi(argv[3]) / 1000000.0;
  double L = atoi(argv[4]) / 1000000.0 + start;
  int k = 0;
  double last = 0;

  atomic_printf("Critical range is %f to %f\n", S, T);

  while (1) {
    int i;
    double t;
    for (i = 0; i < 10000; ++i) {
      k += i * i;
    }
    t = now_double();
    samples[sample_count++] = t;