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; }
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; }