LD = ld
RM = rm
-all: depend libcrush.o
+all: depend libcrush.o test
clean:
rm -f *.o libcrush.o
libcrush.o: builder.o crush.o mapper.o
$(LD) -i -o $@ $^
+test: test.c libcrush.o
+ $(CC) ${CFLAGS} -lm $^ -o $@
+
.depend:
touch .depend
#include <string.h>
#include <math.h>
#include <stdlib.h>
+#include <stdio.h>
#include "builder.h"
#include "hash.h"
}
+/* uniform bucket */
+
struct crush_bucket_uniform *
crush_make_uniform_bucket(int type, int size,
int *items,
return bucket;
}
+
+/* list bucket */
+
struct crush_bucket_list*
crush_make_list_bucket(int type, int size,
int *items,
bucket->item_weights = malloc(sizeof(__u32)*size);
bucket->sum_weights = malloc(sizeof(__u32)*size);
w = 0;
- for (i=0; i<size; i++) {
+ for (i=size-1; i>=0; i--) {
bucket->h.items[i] = items[i];
bucket->item_weights[i] = weights[i];
w += weights[i];
bucket->sum_weights[i] = w;
+ printf("%d item %d weight %d sum %d\n",
+ i, items[i], weights[i], bucket->sum_weights[i]);
}
bucket->h.weight = w;
return bucket;
}
+
+/* tree bucket */
+
static int height(int n) {
int h = 0;
while ((n & 1) == 0) {
for (i=0; i<size; i++) {
node = ((i+1) << 1)-1;
- bucket->h.items[i] = items[i];
+ bucket->h.items[node] = items[i];
bucket->node_weights[node] = weights[i];
bucket->h.weight += weights[i];
for (j=1; j<depth; j++) {
}
+/* straw bucket */
+
struct crush_bucket_straw *
crush_make_straw_bucket(int type,
int size,
bucket->h.weight += weights[i];
}
- /* reverse sort by weight */
+ /* reverse sort by weight (simple insertion sort) */
reverse = malloc(sizeof(int) * size);
- reverse[0] = items[0];
+ reverse[0] = 0;
for (i=1; i<size; i++) {
for (j=0; j<i; j++) {
if (weights[i] < weights[reverse[j]]) {
/* insert here */
for (k=i; k>j; k--)
reverse[k] = reverse[k-1];
- reverse[j] = items[i];
+ reverse[j] = i;
+ break;
}
}
if (j == i)
- reverse[i] = items[i];
+ reverse[i] = i;
}
numleft = size;
while (i < size) {
/* set this item's straw */
bucket->straws[reverse[i]] = straw * 0x10000;
+ printf("item %d at %d weight %d straw %d (%lf)\n",
+ items[reverse[i]],
+ reverse[i], weights[reverse[i]], bucket->straws[reverse[i]], straw);
i++;
if (i == size) break;
/* same weight as previous? */
- if (weights[reverse[i]] == weights[reverse[i-1]])
+ if (weights[reverse[i]] == weights[reverse[i-1]]) {
+ printf("same as previous\n");
continue;
+ }
/* adjust straw for next guy */
- wbelow += (((double)weights[reverse[i-1]] / (double)0x10000) - lastw) * numleft;
- numleft--;
- wnext = numleft * ((double)(weights[reverse[i]] - weights[reverse[i-1]]) / (double)0x10000);
+ wbelow += ((double)weights[reverse[i-1]] - lastw) * numleft;
+ for (j=i; j<size; j++)
+ if (weights[reverse[j]] == weights[reverse[i]])
+ numleft--;
+ else
+ break;
+ wnext = numleft * (weights[reverse[i]] - weights[reverse[i-1]]);
pbelow = wbelow / (wbelow + wnext);
+ printf("wbelow %lf wnext %lf pbelow %lf\n", wbelow, wnext, pbelow);
- straw *= pow((double)1.0 / pbelow, (double)1.0 / numleft);
+ straw *= pow((double)1.0 / pbelow, (double)1.0 / (double)numleft);
lastw = weights[reverse[i-1]];
}
extern void crush_finalize(struct crush_map *map);
/* rules */
+extern struct crush_rule *crush_make_rule();
extern int crush_add_rule(struct crush_map *map,
int ruleno,
struct crush_rule *rule);
-extern struct crush_rule *crush_make_rule();
extern void crush_rule_add_step(struct crush_rule *rule, int op, int arg1, int arg2);
/* buckets */
__u32 max_buckets;
__u32 max_rules;
- __u32 max_devices;
+ __s32 max_devices;
};
#include "hash.h"
#include <string.h>
+#include <stdio.h>
/** bucket choose methods **/
+/* uniform */
static int
crush_bucket_uniform_choose(struct crush_bucket_uniform *bucket, int x, int r)
{
unsigned o, p, s;
- o = crush_hash32_2(x, bucket->h.id);
+ o = crush_hash32_2(x, bucket->h.id) & 0xffff;
p = bucket->primes[crush_hash32_2(bucket->h.id, x) % bucket->h.size];
s = (x + o + (r+1)*p) % bucket->h.size;
+ /*printf("%d %d %d %d\n", x, o, r, p);*/
return bucket->h.items[s];
}
+
+/* list */
+
static int
crush_bucket_list_choose(struct crush_bucket_list *bucket, int x, int r)
{
__u64 w;
for (i=0; i<bucket->h.size; i++) {
- w = crush_hash32_4(x, bucket->h.items[i], r, bucket->h.id) & 0xffff;
- w = (w * bucket->sum_weights[i]) >> 32;
+ w = crush_hash32_4(x, bucket->h.items[i], r, bucket->h.id);
+ w &= 0xffff;
+ /*printf("%d item %d weight %d sum_weight %d r %lld",
+ i, bucket->h.items[i], bucket->item_weights[i], bucket->sum_weights[i], w);*/
+ w *= bucket->sum_weights[i];
+ w = w >> 16;
+ /*printf(" scaled %lld\n", w);*/
if (w < bucket->item_weights[i])
return bucket->h.items[i];
}
}
+/* tree */
+
static int height(int n) {
int h = 0;
while ((n & 1) == 0) {
return bucket->h.items[n];
}
+
+/* straw */
+
static int
crush_bucket_straw_choose(struct crush_bucket_straw *bucket, int x, int r)
{
int i;
int high = 0;
- unsigned high_draw = 0;
+ __u64 high_draw = 0;
__u64 draw;
for (i=0; i<bucket->h.size; i++) {
- draw = (crush_hash32_3(x, bucket->h.items[i], r) & 0xffff) * bucket->straws[i];
- draw = draw >> 32;
+ draw = crush_hash32_3(x, bucket->h.items[i], r);
+ draw &= 0xffff;
+ draw *= bucket->straws[i];
if (i == 0 || draw > high_draw) {
high = i;
high_draw = draw;
}
}
- return high;
+ return bucket->h.items[high];
}
flocal = 0;
do {
r = rep;
- if (in->type == CRUSH_BUCKET_UNIFORM) {
+ if (in->bucket_type == CRUSH_BUCKET_UNIFORM) {
/* be careful */
if (firstn || numrep >= in->size) {
r += ftotal; /* r' = r + f_total */
}
/* bucket choose */
- switch (in->type) {
+ switch (in->bucket_type) {
case CRUSH_BUCKET_UNIFORM:
item = crush_bucket_uniform_choose((struct crush_bucket_uniform*)in, x, r);
break;
/* keep going? */
if (itemtype != type) {
+ BUG_ON((-1-item) >= map->max_buckets);
in = map->buckets[-1-item];
continue;
}