Example #1
0
int main(int argc, char ** argv) {
    pyrebloomctxt ctxt;
    uint32_t i;
    time_t start, end;
    uint32_t count = 1000000;

    init_pyrebloom(&ctxt, "bloom", count, 0.01, "localhost", 6379, "", 0);
    int L=0;
    
    srand(0);
    time(&start);
    for (i = 0; i < count; ++i) {
        int r = rand();
        char c[32];
        sprintf(c, "%08X", r);
        // printf("%s", c);
        L += strlen(c);
        add(&ctxt, c, strlen(c));
    }
    add_complete(&ctxt, count);
    time(&end);
    printf("ADD %f\n", difftime(end,start));
    
    // printf("\n");
    // printf("----------------------------\n");
    // printf("size: %d\n", L);
    // printf("----------------------------\n");

    // srand(0);
    time(&start);
    for (i = 0; i < count; ++i) {
        int r = rand();
        // rand();
        char c[32];
        sprintf(c, "%08X", r);
        // printf("%s", c);
        check(&ctxt, c, strlen(c));
    }

    int cnt = 0;
    for (i = 0; i < count; ++i) {
        int res = check_next(&ctxt);
        if(res) cnt++; 
    }
    time(&end);
    printf("CHECK %f\n", difftime(end,start));

    printf("count: %d false positive:%d prob: %f %%\n", count, cnt, 100.0/count*cnt);
    //delete(&ctxt);
    free_pyrebloom(&ctxt);

    // time(&start);
    // for (i = 0; i < count; ++i) {
    //     redisAppendCommand(ctxt.ctxt, "SADD testing2 hello");
    // }
    // add_complete(&ctxt, count / 4);
    // time(&end);
    // printf("sadd      : %f\n", difftime(end, start));

    return 0;
}
Example #2
0
int init_pyrebloom(pyrebloomctxt *ctxt, char *key, uint32_t capacity, double error,
    char *host, uint32_t port, char *password, uint32_t db)
    {
    ctxt->capacity = capacity;
    ctxt->bits     = (uint64_t)(-(log(error) * capacity) / (log(2) * log(2)));
    ctxt->hashes   = (uint32_t)(ceil(log(2) * ctxt->bits / capacity));
    ctxt->error    = error;
    ctxt->key      = malloc(strlen(key));
    strncpy(ctxt->key, key, strlen(key));
    ctxt->seeds    = malloc(ctxt->hashes * sizeof(uint32_t));
    ctxt->password = malloc(strlen(password));
    strncpy(ctxt->password, password, strlen(password));

    /* We'll need a certain number of strings here */
    ctxt->num_keys = (uint32_t)(
        ceil((float)(ctxt->bits) / max_bits_per_key));
    ctxt->keys = malloc(ctxt->num_keys * sizeof(char*));
    for (uint32_t i = 0; i < ctxt->num_keys; ++i) {
        size_t length = strlen(key) + 10;
        ctxt->keys[i] = malloc(length);
        snprintf(ctxt->keys[i], length, "%s.%i", key, i);
    }

    /* The implementation here used to rely on srand(1) and then repeated
     * calls to rand(), but I no longer trust that to provide correct behavior
     * when working between different platforms. As such, We'll be using a LCG
     *
     *     http://en.wikipedia.org/wiki/Linear_congruential_generator
     *
     * Hopefully this will be the last of interoperability issues. Note that
     * updating to this version will unfortunately require rebuilding old
     * bloom filters.
     *
     * Our m is implicitly going to be 2^32 by storing the result into a
     * uint32_t */
    uint32_t a = 1664525;
    uint32_t c = 1013904223;
    uint32_t x = 314159265;
    for (uint32_t i = 0; i < ctxt->hashes; ++i) {
        ctxt->seeds[i] = x;
        x = a * x + c;
    }

    // Now for the redis context
    struct timeval timeout = { 1, 500000 };
    ctxt->ctxt = redisConnectWithTimeout(host, port, timeout);
    if (ctxt->ctxt->err != 0) {
        return PYREBLOOM_ERROR;
    }

    /* And now if a password was provided, then */
    if (strlen(password) != 0) {
        redisReply * reply = NULL;
        reply = redisCommand(ctxt->ctxt, "AUTH %s", password);
        if (reply->type == REDIS_REPLY_ERROR) {
            /* We'll copy the error into the context's error string */
            strncpy(ctxt->ctxt->errstr, reply->str, errstr_size);
            freeReplyObject(reply);
            return PYREBLOOM_ERROR;
        } else {
            freeReplyObject(reply);
            return PYREBLOOM_OK;
        }
    } else {
        /* Make sure that we can ping the host */
        redisReply * reply = NULL;
        reply = redisCommand(ctxt->ctxt, "PING");
        if (reply->type == REDIS_REPLY_ERROR) {
            strncpy(ctxt->ctxt->errstr, reply->str, errstr_size);
            freeReplyObject(reply);
            return PYREBLOOM_ERROR;
        }
        /* And now, finally free this reply object */
        freeReplyObject(reply);
    }

    /* Select the appropriate DB */
    redisReply * reply = NULL;
    reply = redisCommand(ctxt->ctxt, "SELECT %i", db);
    if (reply->type == REDIS_REPLY_ERROR) {
        strncpy(ctxt->ctxt->errstr, reply->str, errstr_size);
        freeReplyObject(reply);
        /* Shut it down. */
        free_pyrebloom(ctxt);
        return PYREBLOOM_ERROR;
    }
    freeReplyObject(reply);

    /* If we've made it this far, we're ok. */
    return PYREBLOOM_OK;
}