| 39 | } |
| 40 | |
| 41 | ring_t *ch_ring_create_ring(int n_server, double *weight) { |
| 42 | vnode_t *vnodes = |
| 43 | (vnode_t *)malloc(sizeof(vnode_t) * n_server * N_VNODE_PER_SERVER); |
| 44 | |
| 45 | ring_t *ring = (ring_t *)malloc(sizeof(ring_t)); |
| 46 | ring->n_server = n_server; |
| 47 | ring->n_point = n_server * N_VNODE_PER_SERVER; |
| 48 | ring->vnodes = vnodes; |
| 49 | |
| 50 | int i; |
| 51 | unsigned int k, cnt = 0; |
| 52 | |
| 53 | for (i = 0; i < n_server; i++) { |
| 54 | // default all servers have the same weight |
| 55 | unsigned int ks = N_VNODE_PER_SERVER / 4; |
| 56 | if (weight != NULL) |
| 57 | ks = (unsigned int)floorf(weight[i] * (float)n_server * |
| 58 | (N_VNODE_PER_SERVER / 4)); |
| 59 | |
| 60 | for (k = 0; k < ks; k++) { |
| 61 | /* 40 hashes, 4 numbers per hash = 160 points per server */ |
| 62 | char ss[30]; |
| 63 | unsigned char digest[16]; |
| 64 | |
| 65 | sprintf(ss, "%u-%u", i, k); |
| 66 | md5_digest(ss, digest); |
| 67 | |
| 68 | /* Use successive 4-bytes from hash as numbers for the points on the |
| 69 | * circle: */ |
| 70 | int h; |
| 71 | for (h = 0; h < 4; h++) { |
| 72 | // printf("%d i %d k %d h %d %d %d\n", cnt, i, k, h, ring->n_server, |
| 73 | // ring->n_point); |
| 74 | vnodes[cnt].point = (digest[3 + h * 4] << 24) | |
| 75 | (digest[2 + h * 4] << 16) | |
| 76 | (digest[1 + h * 4] << 8) | digest[h * 4]; |
| 77 | |
| 78 | vnodes[cnt].server_id = i; |
| 79 | cnt++; |
| 80 | } |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | /* Sorts in ascending order of "point" */ |
| 85 | qsort((void *)vnodes, cnt, sizeof(vnode_t), ch_ring_compare); |
| 86 | |
| 87 | // for (i=0; i< 200; i++) |
| 88 | // printf("%u %u\n", vnodes[i].point, vnodes[i].server_id); |
| 89 | return ring; |
| 90 | } |
| 91 | |
| 92 | int ch_ring_get_vnode_idx(const char *const key, const ring_t *const ring) { |
| 93 | unsigned int h = ketama_hash(key); |
no test coverage detected