Esempio n. 1
0
static rs_result rs_patch_s_copy(rs_job_t *job)
{
    rs_long_t  where, len;
    rs_stats_t      *stats;

    where = job->param1;
    len = job->param2;
        
    rs_trace("COPY(where=" PRINTF_FORMAT_U64 ", len=" PRINTF_FORMAT_U64 ")", PRINTF_CAST_U64(where), PRINTF_CAST_U64(len));

    if (len < 0) {
        rs_log(RS_LOG_ERR, "invalid length=" PRINTF_FORMAT_U64 " on COPY command", PRINTF_CAST_U64(len));
        return RS_CORRUPT;
    }

    if (where < 0) {
        rs_log(RS_LOG_ERR, "invalid where=" PRINTF_FORMAT_U64 " on COPY command", PRINTF_CAST_U64(where));
        return RS_CORRUPT;
    }

    job->basis_pos = where;
    job->basis_len = len;

    stats = &job->stats;

    stats->copy_cmds++;
    stats->copy_bytes += len;
    stats->copy_cmdbytes += 1 + job->cmd->len_1 + job->cmd->len_2;

    job->statefn = rs_patch_s_copying;
    return RS_RUNNING;
}
Esempio n. 2
0
char *
rs_format_stats(rs_stats_t const * stats,
		char *buf, size_t size)
{
    char const *op = stats->op;
    int len, sec;
    double mbps_in, mbps_out;

    if (!op)
        op = "noop";

    len = snprintf(buf, size, "%s statistics: ", op);

    if (stats->lit_cmds) {
        len += snprintf(buf+len, size-len,
                        "literal[%d cmds, " PRINTF_FORMAT_U64 " bytes, " PRINTF_FORMAT_U64 " cmdbytes] ",
                        stats->lit_cmds,
                        PRINTF_CAST_U64(stats->lit_bytes),
                        PRINTF_CAST_U64(stats->lit_cmdbytes));
    }

    if (stats->sig_cmds) {
        len += snprintf(buf+len, size-len,
                        "in-place-signature[" PRINTF_FORMAT_U64 " cmds, " PRINTF_FORMAT_U64 " bytes] ",
                        PRINTF_CAST_U64(stats->sig_cmds),
                        PRINTF_CAST_U64(stats->sig_bytes));
    }

    if (stats->copy_cmds || stats->false_matches) {
        len += snprintf(buf+len, size-len,
                        "copy[" PRINTF_FORMAT_U64 " cmds, " PRINTF_FORMAT_U64 " bytes, " PRINTF_FORMAT_U64 " false, " PRINTF_FORMAT_U64 " cmdbytes]",
                        PRINTF_CAST_U64(stats->copy_cmds),
                        PRINTF_CAST_U64(stats->copy_bytes),
                        PRINTF_CAST_U64(stats->false_matches),
                        PRINTF_CAST_U64(stats->copy_cmdbytes));
    }


    if (stats->sig_blocks) {
        len  += snprintf(buf+len, size-len,
                         "signature[" PRINTF_FORMAT_U64 " blocks, " PRINTF_FORMAT_U64 " bytes per block]",
                         PRINTF_CAST_U64(stats->sig_blocks),
                         PRINTF_CAST_U64(stats->block_len));
    }

    sec = (stats->end - stats->start);
    if (sec == 0) sec = 1; // avoid division by zero
    mbps_in = stats->in_bytes / 1e6 / sec;
    mbps_out = stats->out_bytes / 1e6 / sec;
    len += snprintf(buf+len, size-len,
        " speed[%.1f MB (%.1f MB/s) in, %.1f MB (%.1f MB/s) out, %d sec]",
        (stats->in_bytes/1e6), mbps_in,
        (stats->out_bytes/1e6), mbps_out, sec);

    return buf;
}
Esempio n. 3
0
/**
 * Called when we're executing a COPY command and waiting for all the
 * data to be retrieved from the callback.
 */
static rs_result rs_patch_s_copying(rs_job_t *job)
{
    rs_result       result;
    size_t          desired_len, len;
    void            *ptr;
    rs_buffers_t    *buffs = job->stream;

    /* copy only as much as will fit in the output buffer, so that we
     * don't have to block or store the input. */
    desired_len = len = (buffs->avail_out < job->basis_len) ? buffs->avail_out : job->basis_len;

    if (!len)
        return RS_BLOCKED;

    rs_trace("copy " PRINTF_FORMAT_U64 " bytes from basis at offset " PRINTF_FORMAT_U64 "",
             PRINTF_CAST_U64(len), PRINTF_CAST_U64(job->basis_pos));

    ptr = buffs->next_out;

    result = (job->copy_cb)(job->copy_arg, job->basis_pos, &len, &ptr);
    if (result != RS_DONE)
        return result;
    else
        rs_trace("copy callback returned %s", rs_strerror(result));

    rs_trace("got " PRINTF_FORMAT_U64 " bytes back from basis callback", PRINTF_CAST_U64(len));

    if (len > desired_len) {
        rs_trace("warning: copy_cb returned more than the requested length.");
        len = desired_len;
    }

    /* copy back to out buffer only if the callback has used its own buffer */
    if (ptr != buffs->next_out)
        memcpy(buffs->next_out, ptr, len);

    buffs->next_out += len;
    buffs->avail_out -= len;

    job->basis_pos += len;
    job->basis_len -= len;

    if (!job->basis_len) {
        /* Done! */
        job->statefn = rs_patch_s_cmdbyte;
    }

    return RS_RUNNING;
}
Esempio n. 4
0
/** Write a COPY command for given offset and length.
 *
 * There is a choice of variable-length encodings, depending on the
 * size of representation for the parameters. */
void
rs_emit_copy_cmd(rs_job_t *job, rs_long_t where, rs_long_t len)
{
    int            cmd;
    rs_stats_t     *stats = &job->stats;
    const int where_bytes = rs_int_len(where);
    const int len_bytes   = rs_int_len(len);

    /* Commands ascend (1,1), (1,2), ... (8, 8) */
    if (where_bytes == 8) 
        cmd = RS_OP_COPY_N8_N1;
    else if (where_bytes == 4)
        cmd = RS_OP_COPY_N4_N1;
    else if (where_bytes == 2)
        cmd = RS_OP_COPY_N2_N1;
    else if (where_bytes == 1)
        cmd = RS_OP_COPY_N1_N1;
    else {
        rs_fatal("can't encode copy command with where_bytes=%d",
                 where_bytes);
    }

    if (len_bytes == 1)
        ;
    else if (len_bytes == 2)
        cmd += 1;
    else if (len_bytes == 4)
        cmd += 2;
    else if (len_bytes == 8)
        cmd += 3;
    else {
        rs_fatal("can't encode copy command with len_bytes=%d",
                 len_bytes);
    }       

    rs_trace("emit COPY_N%d_N%d(where=" PRINTF_FORMAT_U64
             ", len=" PRINTF_FORMAT_U64 "), cmd_byte=%#x",
             where_bytes, len_bytes, PRINTF_CAST_U64(where), PRINTF_CAST_U64(len), cmd);
    rs_squirt_byte(job, cmd);
    rs_squirt_netint(job, where, where_bytes);
    rs_squirt_netint(job, len, len_bytes);

    stats->copy_cmds++;
    stats->copy_bytes += len;
    stats->copy_cmdbytes += 1 + where_bytes + len_bytes;

    /* TODO: All the stats */
}
Esempio n. 5
0
/**
 * Called when we're executing a COPY command and waiting for all the
 * data to be retrieved from the callback.
 */
static rs_result rs_patch_s_copying(rs_job_t *job)
{
    rs_result       result;
    size_t          len;
    void            *buf, *ptr;
    rs_buffers_t    *buffs = job->stream;

    len = job->basis_len;
    
    /* copy only as much as will fit in the output buffer, so that we
     * don't have to block or store the input. */
    if (len > buffs->avail_out)
        len = buffs->avail_out;

    if (!len)
        return RS_BLOCKED;

    rs_trace("copy " PRINTF_FORMAT_U64 " bytes from basis at offset " PRINTF_FORMAT_U64 "",
             PRINTF_CAST_U64(len), PRINTF_CAST_U64(job->basis_pos));

    ptr = buf = rs_alloc(len, "basis buffer");
    
    result = (job->copy_cb)(job->copy_arg, job->basis_pos, &len, &ptr);
    if (result != RS_DONE)
        return result;
    else
        rs_trace("copy callback returned %s", rs_strerror(result));
    
    rs_trace("got " PRINTF_FORMAT_U64 " bytes back from basis callback", PRINTF_CAST_U64(len));

    memcpy(buffs->next_out, ptr, len);

    buffs->next_out += len;
    buffs->avail_out -= len;

    job->basis_pos += len;
    job->basis_len -= len;

    free(buf);

    if (!job->basis_len) {
        /* Done! */
        job->statefn = rs_patch_s_cmdbyte;
    } 

    return RS_RUNNING;
}
Esempio n. 6
0
char *
rs_format_stats(rs_stats_t const * stats,
		char *buf, size_t size)
{
    char const *op = stats->op;
    int len;

    if (!op)
        op = "noop";
    
    len = snprintf(buf, size, "%s statistics: ", op);

    if (stats->lit_cmds) {
        len += snprintf(buf+len, size-len,
                        "literal[%d cmds, " PRINTF_FORMAT_U64 " bytes, " PRINTF_FORMAT_U64 " cmdbytes] ",
                        stats->lit_cmds,
                        PRINTF_CAST_U64(stats->lit_bytes),
                        PRINTF_CAST_U64(stats->lit_cmdbytes));
    }

    if (stats->sig_cmds) {
        len += snprintf(buf+len, size-len,
                        "in-place-signature[" PRINTF_FORMAT_U64 " cmds, " PRINTF_FORMAT_U64 " bytes] ",
                        PRINTF_CAST_U64(stats->sig_cmds),
                        PRINTF_CAST_U64(stats->sig_bytes));
    }

    if (stats->copy_cmds || stats->false_matches) {
        len += snprintf(buf+len, size-len,
                        "copy[" PRINTF_FORMAT_U64 " cmds, " PRINTF_FORMAT_U64 " bytes, " PRINTF_FORMAT_U64 " false, " PRINTF_FORMAT_U64 " cmdbytes]",
                        PRINTF_CAST_U64(stats->copy_cmds),
                        PRINTF_CAST_U64(stats->copy_bytes),
                        PRINTF_CAST_U64(stats->false_matches),
                        PRINTF_CAST_U64(stats->copy_cmdbytes));
    }
        

    if (stats->sig_blocks) {
        len  += snprintf(buf+len, size-len,
                         "signature[" PRINTF_FORMAT_U64 " blocks, " PRINTF_FORMAT_U64 " bytes per block]",
                         PRINTF_CAST_U64(stats->sig_blocks),
                         PRINTF_CAST_U64(stats->block_len));
    }
    
    return buf;
}
Esempio n. 7
0
/**
 * Flush any accumulating hit or miss, appending it to the delta.
 */
INLINE rs_result rs_appendflush(rs_job_t *job)
{
    /* if last is a match, emit it and reset last by resetting basis_len */
    if (job->basis_len) {
        rs_trace("matched " PRINTF_FORMAT_U64 " bytes at " PRINTF_FORMAT_U64 "!",
                 PRINTF_CAST_U64(job->basis_len),
                 PRINTF_CAST_U64(job->basis_pos));
        rs_emit_copy_cmd(job, job->basis_pos, job->basis_len);
        job->basis_len=0;
        return rs_processmatch(job);
    /* else if last is a miss, emit and process it*/
    } else if (job->scoop_pos) {
        rs_trace("got %ld bytes of literal data", (long) job->scoop_pos);
        rs_emit_literal_cmd(job, job->scoop_pos);
        return rs_processmiss(job);
    }
    /* otherwise, nothing to flush so we are done */
    return RS_DONE;
}
Esempio n. 8
0
rs_result rs_job_iter(rs_job_t *job, rs_buffers_t *buffers)
{
    rs_result       result;
    rs_long_t       orig_in, orig_out;

    orig_in  = buffers->avail_in;
    orig_out = buffers->avail_out;

    result = rs_job_work(job, buffers);

    if (result == RS_BLOCKED  ||  result == RS_DONE)
        if ((orig_in == buffers->avail_in)  &&  (orig_out == buffers->avail_out)
            && orig_in && orig_out) {
            rs_log(RS_LOG_ERR, "internal error: job made no progress "
                   "[orig_in=" PRINTF_FORMAT_U64 ", orig_out=" PRINTF_FORMAT_U64 ", final_in=" PRINTF_FORMAT_U64 ", final_out=" PRINTF_FORMAT_U64 "]",
                   PRINTF_CAST_U64(orig_in), PRINTF_CAST_U64(orig_out), PRINTF_CAST_U64(buffers->avail_in),
                   PRINTF_CAST_U64(buffers->avail_out));
            return RS_INTERNAL_ERROR;
        }

    return result;
}
Esempio n. 9
0
/**
 * Called when trying to copy through literal data.
 */
static rs_result rs_patch_s_literal(rs_job_t *job)
{
    rs_long_t   len = job->param1;
    
    rs_trace("LITERAL(len=" PRINTF_FORMAT_U64 ")", PRINTF_CAST_U64(len));

    if (len < 0) {
        rs_log(RS_LOG_ERR, "invalid length=" PRINTF_FORMAT_U64 " on LITERAL command", PRINTF_CAST_U64(len));
        return RS_CORRUPT;
    }

    job->stats.lit_cmds++;
    job->stats.lit_bytes    += len;
    job->stats.lit_cmdbytes += 1 + job->cmd->len_1;

    rs_tube_copy(job, len);

    job->statefn = rs_patch_s_cmdbyte;
    return RS_RUNNING;
}
Esempio n. 10
0
/**
 * \brief State function that does a slack delta containing only
 * literal data to recreate the input.
 */
static rs_result rs_delta_s_slack(rs_job_t *job)
{
    rs_buffers_t * const stream = job->stream;
    size_t avail = stream->avail_in;

    if (avail) {
        rs_trace("emit slack delta for " PRINTF_FORMAT_U64
                 " available bytes", PRINTF_CAST_U64(avail));
        rs_emit_literal_cmd(job, avail);
        rs_tube_copy(job, avail);
        return RS_RUNNING;
    } else {
        if (rs_job_input_is_ending(job)) {
            job->statefn = rs_delta_s_end;
            return RS_RUNNING;
        } else {                
            return RS_BLOCKED;
        }
    }
}
Esempio n. 11
0
/**
 * State of trying to read the first byte of a command.  Once we've
 * taken that in, we can know how much data to read to get the
 * arguments.
 */
static rs_result rs_patch_s_cmdbyte(rs_job_t *job)
{
    rs_result result;
        
    if ((result = rs_suck_byte(job, &job->op)) != RS_DONE)
        return result;

    job->cmd = &rs_prototab[job->op];
        
    rs_trace("got command byte 0x%02x (%s), len_1=" PRINTF_FORMAT_U64 "", job->op,
             rs_op_kind_name(job->cmd->kind),
             PRINTF_CAST_U64(job->cmd->len_1));

    if (job->cmd->len_1)
        job->statefn = rs_patch_s_params;
    else {
        job->param1 = job->cmd->immediate;
        job->statefn = rs_patch_s_run;
    }

    return RS_RUNNING;
}