Implement a PG generator for hierarchical failure domains
parent
98077a1712
commit
431f780347
|
@ -539,6 +539,106 @@ function extract_osds(osd_tree, levels, osd_level, osds = {})
|
||||||
return osds;
|
return osds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generate random PGs with hierarchical failure domains, i.e. for example 3 DC each with 2 HOSTS
|
||||||
|
// osd_tree = { level3_id: { level2_id: { level1_id: scalar_value } }, ... }
|
||||||
|
// osd_tree may contain arbitrary number of levels, but level count must be the same across the whole tree
|
||||||
|
// size_per_level = number of items to select on each level, for example [3, 2, 1].
|
||||||
|
// must have the same number of items as the osd_tree level count.
|
||||||
|
// count = PG count to generate
|
||||||
|
// ordered = don't treat (x,y) and (y,x) as equal
|
||||||
|
// seq_layout = true for the [DC1,DC1,DC2,DC2,DC3,DC3] layout, false for [DC1,DC2,DC3,DC1,DC2,DC3] layout
|
||||||
|
function random_hier_combinations(osd_tree, size_per_level, count, ordered, seq_layout)
|
||||||
|
{
|
||||||
|
let seed = 0x5f020e43;
|
||||||
|
const rng = () =>
|
||||||
|
{
|
||||||
|
seed ^= seed << 13;
|
||||||
|
seed ^= seed >> 17;
|
||||||
|
seed ^= seed << 5;
|
||||||
|
return seed + 2147483648;
|
||||||
|
};
|
||||||
|
const get_max_level = (o) =>
|
||||||
|
{
|
||||||
|
let lvl = 0;
|
||||||
|
while (o instanceof Object)
|
||||||
|
{
|
||||||
|
for (const k in o)
|
||||||
|
{
|
||||||
|
lvl++;
|
||||||
|
o = o[k];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lvl;
|
||||||
|
};
|
||||||
|
const max_level = get_max_level(osd_tree);
|
||||||
|
const gen_pg = (select) =>
|
||||||
|
{
|
||||||
|
let pg = [ osd_tree ];
|
||||||
|
for (let level = 0; level < max_level; level++)
|
||||||
|
{
|
||||||
|
let npg = [];
|
||||||
|
for (let i = 0; i < pg.length; i++)
|
||||||
|
{
|
||||||
|
const keys = pg[i] instanceof Object ? Object.keys(pg[i]) : [];
|
||||||
|
const max_keys = keys.length < size_per_level[level] ? keys.length : size_per_level[level];
|
||||||
|
for (let j = 0; j < max_keys; j++)
|
||||||
|
{
|
||||||
|
const r = select(level, i, j, (ordered ? keys.length : (keys.length - (max_keys - j - 1))));
|
||||||
|
const el = pg[i][keys[r]] instanceof Object ? pg[i][keys[r]] : keys[r];
|
||||||
|
npg[seq_layout ? i*size_per_level[level]+j : j*pg.length+i] = el;
|
||||||
|
keys.splice(ordered ? r : 0, ordered ? 1 : (r+1));
|
||||||
|
}
|
||||||
|
for (let j = max_keys; j < size_per_level[level]; j++)
|
||||||
|
npg[seq_layout ? i*size_per_level[level]+j : j*pg.length+i] = NO_OSD;
|
||||||
|
}
|
||||||
|
pg = npg;
|
||||||
|
}
|
||||||
|
return pg;
|
||||||
|
};
|
||||||
|
const r = {};
|
||||||
|
// Generate random combinations including each OSD at least once
|
||||||
|
let has_next = true;
|
||||||
|
let ctr = [];
|
||||||
|
while (has_next)
|
||||||
|
{
|
||||||
|
let pg = gen_pg((level, i, j, n) =>
|
||||||
|
{
|
||||||
|
if (i == 0 && j == 0)
|
||||||
|
{
|
||||||
|
// Select a pre-determined OSD in the first position on each level
|
||||||
|
const r = ctr[level] == null || ctr[level][1] != n ? 0 : ctr[level][0];
|
||||||
|
ctr[level] = [ r, n ];
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return rng() % n;
|
||||||
|
});
|
||||||
|
for (let i = ctr.length-1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
ctr[i][0]++;
|
||||||
|
if (ctr[i][0] < ctr[i][1])
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
ctr[i] = null;
|
||||||
|
}
|
||||||
|
has_next = ctr[0] != null;
|
||||||
|
const cyclic_pgs = [ pg ];
|
||||||
|
if (ordered)
|
||||||
|
for (let i = 1; i < pg.size; i++)
|
||||||
|
cyclic_pgs.push([ ...pg.slice(i), ...pg.slice(0, i) ]);
|
||||||
|
for (const pg of cyclic_pgs)
|
||||||
|
r['pg_'+pg.join('_')] = pg;
|
||||||
|
}
|
||||||
|
// Generate purely random combinations
|
||||||
|
while (count > 0)
|
||||||
|
{
|
||||||
|
let pg = gen_pg((l, i, j, n) => rng() % n);
|
||||||
|
r['pg_'+pg.join('_')] = pg;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
// ordered = don't treat (x,y) and (y,x) as equal
|
// ordered = don't treat (x,y) and (y,x) as equal
|
||||||
function random_combinations(osd_tree, pg_size, count, ordered)
|
function random_combinations(osd_tree, pg_size, count, ordered)
|
||||||
{
|
{
|
||||||
|
@ -758,5 +858,6 @@ module.exports = {
|
||||||
make_int_pgs,
|
make_int_pgs,
|
||||||
align_pgs,
|
align_pgs,
|
||||||
random_combinations,
|
random_combinations,
|
||||||
|
random_hier_combinations,
|
||||||
all_combinations,
|
all_combinations,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue