Beispiel #1
0
int
vrt_producer_flush(struct vrt_producer *p)
{
    struct vrt_value  *v;

    if (p->last_produced_id == p->last_claimed_id) {
        /* We don't have any queue entries that we've claimed but haven't used,
         * so there's nothing to flush. */
        return 0;
    }

    /* Claim a value to fill in a FLUSH control message. */
    rii_check(vrt_producer_claim_raw(p->queue, p));
    clog_trace("<%s> Flush %d", p->name, p->last_produced_id);
    v = vrt_queue_get(p->queue, p->last_produced_id);
    v->special = VRT_VALUE_FLUSH;

    /* If we've claimed more value than we've produced, fill in the
     * remainder with holes. */
    if (vrt_mod_lt(p->last_produced_id, p->last_claimed_id)) {
        vrt_value_id  i;
        clog_trace("<%s> Holes %d-%d",
                   p->name, p->last_produced_id + 1, p->last_claimed_id);
        for (i = p->last_produced_id + 1;
             vrt_mod_le(i, p->last_claimed_id); i++) {
            struct vrt_value  *v = vrt_queue_get(p->queue, i);
            v->id = i;
            v->special = VRT_VALUE_HOLE;
        }
        p->last_produced_id = p->last_claimed_id;
    }

    /* Then publish the whole chunk. */
    return p->publish(p->queue, p, p->last_claimed_id);
}
Beispiel #2
0
int main(int argc, char *argv[])
{
  int level = CLOG_DEFAULT;
  const char *lname = "DEFAULT";

  clog_init(stdout, level, CLOG_DEFAULT_TS_FMT);

  if(argc == 2) {
    if(!strcmp("FATAL", argv[1])) { clog_set_level(level = CLOG_FATAL); lname = "FATAL"; }
    if(!strcmp("ERROR", argv[1])) { clog_set_level(level = CLOG_ERROR); lname = "ERROR"; }
    if(!strcmp("WARN", argv[1]))  { clog_set_level(level = CLOG_WARN);  lname = "WARN";  }
    if(!strcmp("INFO", argv[1]))  { clog_set_level(level = CLOG_INFO);  lname = "INFO";  }
    if(!strcmp("DEBUG", argv[1])) { clog_set_level(level = CLOG_DEBUG); lname = "DEBUG"; }
    if(!strcmp("TRACE", argv[1])) { clog_set_level(level = CLOG_TRACE); lname = "TRACE"; }
  }

  fprintf(stdout, "--- %s ---\n", lname);
  clog_fatal("this is %s log",  "fatal");
  clog_error("this is %s log",  "error");
  clog_warn("this is %s log",    "warn");
  clog_info("this is %s log",    "info");
  clog_debug("this is %s log",  "debug");
  clog_trace("this is %s log",  "trace");

  return 0;
}
Beispiel #3
0
static int
vrt_publish_multi_threaded(struct vrt_queue *q, struct vrt_producer *p,
                           vrt_value_id last_published_id)
{
    bool  first = true;
    vrt_value_id  expected_cursor;
    vrt_value_id  current_cursor;

    /* If there are multiple publisherthen we have to wait until all
     * of the values before the chunk that we claimed have been
     * published.  (If we don't, there will be a hole in the sequence of
     * published records.) */
    expected_cursor = last_published_id - p->batch_size;
    current_cursor = vrt_queue_get_cursor(q);
    clog_debug("<%s> Wait for value %d to be published",
               p->name, expected_cursor);

    while (vrt_mod_lt(current_cursor, expected_cursor)) {
        clog_trace("<%s> Last published value is %d (wait)",
                   p->name, current_cursor);
        rii_check(vrt_yield_strategy_yield
                  (p->yield, first, q->name, p->name));
        first = false;
        current_cursor = vrt_queue_get_cursor(q);
    }

    clog_debug("<%s> Last published value is %d", p->name, current_cursor);
    clog_debug("<%s> Signal publication of value %d (multi-threaded)",
               p->name, last_published_id);
    vrt_queue_set_cursor(q, last_published_id);
    return 0;
}
Beispiel #4
0
/* Waits for the slot given by the producer's last_claimed_id to become
 * free.  (This happens when every consumer has finished processing the
 * previous value that would've used the same slot in the ring buffer. */
static int
vrt_wait_for_slot(struct vrt_queue *q, struct vrt_producer *p)
{
    bool  first = true;
    vrt_value_id  wrapped_id = p->last_claimed_id - vrt_queue_size(q);
    if (vrt_mod_lt(q->last_consumed_id, wrapped_id)) {
        clog_debug("<%s> Wait for value %d to be consumed",
                   p->name, wrapped_id);
        vrt_value_id  minimum = vrt_queue_find_last_consumed_id(q);
        while (vrt_mod_lt(minimum, wrapped_id)) {
            clog_trace("<%s> Last consumed value is %d (wait)",
                       p->name, minimum);
            p->yield_count++;
            rii_check(vrt_yield_strategy_yield
                      (p->yield, first, q->name, p->name));
            first = false;
            minimum = vrt_queue_find_last_consumed_id(q);
        }
        p->batch_count++;
        q->last_consumed_id = minimum;
        clog_debug("<%s> Last consumed value is %d", p->name, minimum);
    }

    return 0;
}
Beispiel #5
0
int
vrt_producer_skip(struct vrt_producer *p)
{
    struct vrt_value  *v;
    clog_trace("<%s> Skip %d", p->name, p->last_produced_id);
    v = vrt_queue_get(p->queue, p->last_produced_id);
    v->special = VRT_VALUE_HOLE;
    return vrt_producer_publish(p);
}
Beispiel #6
0
static int
vrt_claim_multi_threaded(struct vrt_queue *q, struct vrt_producer *p)
{
    /* If there are multiple producerwe have to use an atomic
     * increment to claim the next batch of records. */
    p->last_claimed_id =
        vrt_padded_int_atomic_add(&q->last_claimed_id, p->batch_size);
    p->last_produced_id = p->last_claimed_id - p->batch_size;
    if (p->batch_size == 1) {
        clog_trace("<%s> Claim value %d (multi-threaded)",
                   p->name, p->last_claimed_id);
    } else {
        clog_trace("<%s> Claim values %d-%d (multi-threaded)",
                   p->name, p->last_produced_id + 1, p->last_claimed_id);
    }

    /* Then wait until the slots for these new values are free. */
    return vrt_wait_for_slot(q, p);
}
Beispiel #7
0
static int
vrt_claim_single_threaded(struct vrt_queue *q, struct vrt_producer *p)
{
    /* If there's only a single producer, we can just grab the next
     * batch of values in sequence. */
    p->last_claimed_id += p->batch_size;
    if (p->batch_size == 1) {
        clog_trace("<%s> Claim value %d (single-threaded)",
                   p->name, p->last_claimed_id);
    } else {
        clog_trace("<%s> Claim values %d-%d (single-threaded)",
                   p->name, p->last_claimed_id - p->batch_size + 1,
                   p->last_claimed_id);
    }

    /* But we do have to wait until the slots for these new values are
     * free. */
    return vrt_wait_for_slot(q, p);
}
Beispiel #8
0
int
vrt_producer_publish(struct vrt_producer *p)
{
    if (p->last_produced_id == p->last_claimed_id) {
        return p->publish(p->queue, p, p->last_claimed_id);
    } else {
        clog_trace("<%s> Wait to publish %d until end of batch (at %d)",
                   p->name, p->last_produced_id, p->last_claimed_id);
        return 0;
    }
}
Beispiel #9
0
/* Claims the next ID that this producer can fill in.  The new value's
 * ID will be stored in p->last_produced_id.  You can get the value
 * itself using vrt_queue_get. */
static int
vrt_producer_claim_raw(struct vrt_queue *q, struct vrt_producer *p)
{
    if (p->last_produced_id == p->last_claimed_id) {
        rii_check(p->claim(q, p));
    }
    p->last_produced_id++;
    clog_trace("<%s> Claimed value %d (%d is available)\n",
               p->name, p->last_produced_id, p->last_claimed_id);
    return 0;
}
Beispiel #10
0
struct vrt_producer *
vrt_producer_new(const char *name, unsigned int batch_size,
                 struct vrt_queue *q)
{
    struct vrt_producer  *p;
    unsigned int  maximum_batch_size;

    p = cork_new(struct vrt_producer);
    memset(p, 0, sizeof(struct vrt_producer));

    p->name = cork_strdup(name);
    ei_check(vrt_queue_add_producer(q, p));

    if (batch_size == 0) {
        batch_size = DEFAULT_BATCH_SIZE;
    }
    maximum_batch_size = vrt_queue_size(q) / 4;
    if (batch_size > maximum_batch_size) {
        batch_size = maximum_batch_size;
    }
    clog_trace("<%s> Batch size is %u", name, batch_size);

    p->last_produced_id = starting_value;
    p->last_claimed_id = starting_value;
    p->batch_size = batch_size;
    p->yield = NULL;
    p->batch_count = 0;
    p->yield_count = 0;
    return p;

error:
    if (p->name != NULL) {
        cork_strfree(p->name);
    }

    cork_delete(struct vrt_producer, p);
    return NULL;
}
Beispiel #11
0
static struct bz_version *
bz_version_from_rpm_any(const char *rpm_version)
{
    int  cs;
    const char  *p = rpm_version;
    const char  *pe = strchr(rpm_version, '\0');
    const char  *eof = pe;
    struct bz_version  *version;
    enum bz_version_part_kind  kind;
    const char  *start;
    struct cork_buffer  buf = CORK_BUFFER_INIT();

    clog_trace("Parse any RPM version \"%s\"", rpm_version);
    version = bz_version_new();

    
#line 560 "libbuzzy/distro/rpm.c"
static const int rpm_version_any_start = 1;

static const int rpm_version_any_en_main = 1;


#line 566 "libbuzzy/distro/rpm.c"
	{
	cs = rpm_version_any_start;
	}

#line 571 "libbuzzy/distro/rpm.c"
	{
	if ( p == pe )
		goto _test_eof;
	switch ( cs )
	{
case 1:
	if ( 48 <= (*p) && (*p) <= 57 )
		goto tr0;
	goto st0;
st0:
cs = 0;
	goto _out;
tr0:
#line 272 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_RELEASE;
            start = p;
            clog_trace("  Create new release version part");
        }
	goto st2;
tr4:
#line 290 "libbuzzy/distro/rpm.c.rl"
	{
            size_t  size = p - start;
            clog_trace("    String value: %.*s", (int) size, start);
            ei_check(bz_version_add_part(version, kind, start, size));
        }
#line 272 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_RELEASE;
            start = p;
            clog_trace("  Create new release version part");
        }
	goto st2;
st2:
	if ( ++p == pe )
		goto _test_eof2;
case 2:
#line 610 "libbuzzy/distro/rpm.c"
	switch( (*p) ) {
		case 43: goto tr2;
		case 45: goto tr3;
		case 46: goto tr2;
		case 95: goto tr2;
	}
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto tr4;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto tr5;
	} else
		goto tr5;
	goto st0;
tr2:
#line 290 "libbuzzy/distro/rpm.c.rl"
	{
            size_t  size = p - start;
            clog_trace("    String value: %.*s", (int) size, start);
            ei_check(bz_version_add_part(version, kind, start, size));
        }
	goto st3;
st3:
	if ( ++p == pe )
		goto _test_eof3;
case 3:
#line 638 "libbuzzy/distro/rpm.c"
	switch( (*p) ) {
		case 43: goto st3;
		case 46: goto st3;
		case 95: goto st3;
	}
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto tr7;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto tr8;
	} else
		goto tr8;
	goto st0;
tr7:
#line 272 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_RELEASE;
            start = p;
            clog_trace("  Create new release version part");
        }
	goto st4;
tr18:
#line 290 "libbuzzy/distro/rpm.c.rl"
	{
            size_t  size = p - start;
            clog_trace("    String value: %.*s", (int) size, start);
            ei_check(bz_version_add_part(version, kind, start, size));
        }
#line 272 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_RELEASE;
            start = p;
            clog_trace("  Create new release version part");
        }
	goto st4;
st4:
	if ( ++p == pe )
		goto _test_eof4;
case 4:
#line 679 "libbuzzy/distro/rpm.c"
	switch( (*p) ) {
		case 43: goto tr2;
		case 45: goto tr3;
		case 46: goto tr2;
		case 95: goto tr2;
	}
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto st4;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto tr5;
	} else
		goto tr5;
	goto st0;
tr3:
#line 290 "libbuzzy/distro/rpm.c.rl"
	{
            size_t  size = p - start;
            clog_trace("    String value: %.*s", (int) size, start);
            ei_check(bz_version_add_part(version, kind, start, size));
        }
	goto st5;
st5:
	if ( ++p == pe )
		goto _test_eof5;
case 5:
#line 707 "libbuzzy/distro/rpm.c"
	switch( (*p) ) {
		case 48: goto st6;
		case 49: goto tr11;
	}
	if ( 50 <= (*p) && (*p) <= 57 )
		goto tr12;
	goto st0;
st6:
	if ( ++p == pe )
		goto _test_eof6;
case 6:
	if ( (*p) == 46 )
		goto st7;
	goto st0;
st7:
	if ( ++p == pe )
		goto _test_eof7;
case 7:
	if ( 48 <= (*p) && (*p) <= 57 )
		goto tr14;
	goto st0;
tr21:
#line 290 "libbuzzy/distro/rpm.c.rl"
	{
            size_t  size = p - start;
            clog_trace("    String value: %.*s", (int) size, start);
            ei_check(bz_version_add_part(version, kind, start, size));
        }
#line 272 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_RELEASE;
            start = p;
            clog_trace("  Create new release version part");
        }
	goto st10;
tr12:
#line 284 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_POSTRELEASE;
            start = p;
            clog_trace("  Create new postrelease version part");
        }
	goto st10;
tr14:
#line 278 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_PRERELEASE;
            start = p;
            clog_trace("  Create new prerelease version part");
        }
	goto st10;
st10:
	if ( ++p == pe )
		goto _test_eof10;
case 10:
#line 763 "libbuzzy/distro/rpm.c"
	switch( (*p) ) {
		case 43: goto tr20;
		case 46: goto tr20;
		case 95: goto tr20;
	}
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto tr21;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto tr22;
	} else
		goto tr22;
	goto st0;
tr20:
#line 290 "libbuzzy/distro/rpm.c.rl"
	{
            size_t  size = p - start;
            clog_trace("    String value: %.*s", (int) size, start);
            ei_check(bz_version_add_part(version, kind, start, size));
        }
	goto st8;
st8:
	if ( ++p == pe )
		goto _test_eof8;
case 8:
#line 790 "libbuzzy/distro/rpm.c"
	switch( (*p) ) {
		case 43: goto st8;
		case 46: goto st8;
		case 95: goto st8;
	}
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto tr16;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto tr17;
	} else
		goto tr17;
	goto st0;
tr16:
#line 272 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_RELEASE;
            start = p;
            clog_trace("  Create new release version part");
        }
	goto st11;
tr24:
#line 290 "libbuzzy/distro/rpm.c.rl"
	{
            size_t  size = p - start;
            clog_trace("    String value: %.*s", (int) size, start);
            ei_check(bz_version_add_part(version, kind, start, size));
        }
#line 272 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_RELEASE;
            start = p;
            clog_trace("  Create new release version part");
        }
	goto st11;
st11:
	if ( ++p == pe )
		goto _test_eof11;
case 11:
#line 831 "libbuzzy/distro/rpm.c"
	switch( (*p) ) {
		case 43: goto tr20;
		case 46: goto tr20;
		case 95: goto tr20;
	}
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto st11;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto tr22;
	} else
		goto tr22;
	goto st0;
tr17:
#line 272 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_RELEASE;
            start = p;
            clog_trace("  Create new release version part");
        }
	goto st12;
tr22:
#line 290 "libbuzzy/distro/rpm.c.rl"
	{
            size_t  size = p - start;
            clog_trace("    String value: %.*s", (int) size, start);
            ei_check(bz_version_add_part(version, kind, start, size));
        }
#line 272 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_RELEASE;
            start = p;
            clog_trace("  Create new release version part");
        }
	goto st12;
st12:
	if ( ++p == pe )
		goto _test_eof12;
case 12:
#line 872 "libbuzzy/distro/rpm.c"
	switch( (*p) ) {
		case 43: goto tr20;
		case 46: goto tr20;
		case 95: goto tr20;
	}
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto tr24;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto st12;
	} else
		goto st12;
	goto st0;
tr11:
#line 284 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_POSTRELEASE;
            start = p;
            clog_trace("  Create new postrelease version part");
        }
	goto st13;
st13:
	if ( ++p == pe )
		goto _test_eof13;
case 13:
#line 899 "libbuzzy/distro/rpm.c"
	switch( (*p) ) {
		case 43: goto tr20;
		case 46: goto tr20;
		case 95: goto tr20;
	}
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto tr21;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto tr22;
	} else
		goto tr22;
	goto st0;
tr8:
#line 272 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_RELEASE;
            start = p;
            clog_trace("  Create new release version part");
        }
	goto st9;
tr5:
#line 290 "libbuzzy/distro/rpm.c.rl"
	{
            size_t  size = p - start;
            clog_trace("    String value: %.*s", (int) size, start);
            ei_check(bz_version_add_part(version, kind, start, size));
        }
#line 272 "libbuzzy/distro/rpm.c.rl"
	{
            kind = BZ_VERSION_RELEASE;
            start = p;
            clog_trace("  Create new release version part");
        }
	goto st9;
st9:
	if ( ++p == pe )
		goto _test_eof9;
case 9:
#line 940 "libbuzzy/distro/rpm.c"
	switch( (*p) ) {
		case 43: goto tr2;
		case 45: goto tr3;
		case 46: goto tr2;
		case 95: goto tr2;
	}
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto tr18;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto st9;
	} else
		goto st9;
	goto st0;
	}
	_test_eof2: cs = 2; goto _test_eof; 
	_test_eof3: cs = 3; goto _test_eof; 
	_test_eof4: cs = 4; goto _test_eof; 
	_test_eof5: cs = 5; goto _test_eof; 
	_test_eof6: cs = 6; goto _test_eof; 
	_test_eof7: cs = 7; goto _test_eof; 
	_test_eof10: cs = 10; goto _test_eof; 
	_test_eof8: cs = 8; goto _test_eof; 
	_test_eof11: cs = 11; goto _test_eof; 
	_test_eof12: cs = 12; goto _test_eof; 
	_test_eof13: cs = 13; goto _test_eof; 
	_test_eof9: cs = 9; goto _test_eof; 

	_test_eof: {}
	if ( p == eof )
	{
	switch ( cs ) {
	case 10: 
	case 11: 
	case 12: 
#line 290 "libbuzzy/distro/rpm.c.rl"
	{
            size_t  size = p - start;
            clog_trace("    String value: %.*s", (int) size, start);
            ei_check(bz_version_add_part(version, kind, start, size));
        }
	break;
#line 984 "libbuzzy/distro/rpm.c"
	}
	}

	_out: {}
	}

#line 337 "libbuzzy/distro/rpm.c.rl"


    /* A hack to suppress some unused variable warnings */
    (void) rpm_version_any_en_main;

    if (CORK_UNLIKELY(cs < 
#line 998 "libbuzzy/distro/rpm.c"
10
#line 342 "libbuzzy/distro/rpm.c.rl"
)) {
        goto error;
    }

    bz_version_finalize(version);
    cork_buffer_done(&buf);
    return version;

error:
    cork_buffer_done(&buf);
    bz_version_free(version);
    return NULL;
}
Beispiel #12
0
/* Retrieves the next value from the consumer's queue.  When this
 * returns c->current_id will be the ID of the next value.  You can
 * retrieve the value using vrt_queue_get. */
static int
vrt_consumer_next_raw(struct vrt_queue *q, struct vrt_consumer *c)
{
    /* We've just finished processing the current_id'th value. */
    vrt_value_id  last_consumed_id = c->current_id++;

    /* If we know there are values available that we haven't yet
     * consumed, go ahead and return one. */
    if (vrt_mod_le(c->current_id, c->last_available_id)) {
        clog_trace("<%s> Next value is %d (already available)",
                   c->name, c->current_id);
        return 0;
    }

    /* We've run out of values that we know can been processed.  Notify
     * the world how much we've processed so far. */
    clog_debug("<%s> Signal consumption of %d", c->name, last_consumed_id);
    vrt_consumer_set_cursor(c, last_consumed_id);

    /* Check to see if there are any more values that we can process. */
    if (cork_array_is_empty(&c->dependencies)) {
        bool  first = true;
        vrt_value_id  last_available_id;
        clog_debug("<%s> Wait for value %d", c->name, c->current_id);

        /* If we don't have any dependencies check the queue itself to see how
         * many values have been published. */
        last_available_id = vrt_queue_get_cursor(q);
        while (vrt_mod_le(last_available_id, last_consumed_id)) {
            clog_trace("<%s> Last available value is %d (wait)",
                       c->name, last_available_id);
            c->yield_count++;
            rii_check(vrt_yield_strategy_yield
                      (c->yield, first, q->name, c->name));
            first = false;
            last_available_id = vrt_queue_get_cursor(q);
        }
        c->last_available_id = last_available_id;
        clog_debug("<%s> Last available value is %d",
                   c->name, last_available_id);
    } else {
        bool  first = true;
        vrt_value_id  last_available_id;
        clog_debug("<%s> Wait for value %d from dependencies",
                   c->name, c->current_id);

        /* If there are dependencies we can only process what they've *all*
         * finished processing. */
        last_available_id = vrt_consumer_find_last_dependent_id(c);
        while (vrt_mod_le(last_available_id, last_consumed_id)) {
            clog_trace("<%s> Last available value is %d (wait)",
                       c->name, last_available_id);
            c->yield_count++;
            rii_check(vrt_yield_strategy_yield
                      (c->yield, first, q->name, c->name));
            first = false;
            last_available_id = vrt_consumer_find_last_dependent_id(c);
        }
        c->last_available_id = last_available_id;
        clog_debug("<%s> Last available value is %d",
                   c->name, last_available_id);
    }

    c->batch_count++;

    /* Once we fall through to here, we know that there are additional
     * values that we can process. */
    clog_trace("<%s> Next value is %d", c->name, c->current_id);
    return 0;
}