forked from vitalif/vitastor
113 lines
3.6 KiB
JavaScript
113 lines
3.6 KiB
JavaScript
// Copyright (c) Vitaliy Filippov, 2019+
|
|
// License: VNPL-1.0 (see README.md for details)
|
|
|
|
module.exports = {
|
|
scale_pg_count,
|
|
};
|
|
|
|
function scale_pg_count(prev_pgs, prev_pg_history, new_pg_history, new_pg_count)
|
|
{
|
|
const old_pg_count = prev_pgs.length;
|
|
// Add all possibly intersecting PGs into the history of new PGs
|
|
if (!(new_pg_count % old_pg_count))
|
|
{
|
|
// New PG count is a multiple of the old PG count
|
|
const mul = (new_pg_count / old_pg_count);
|
|
for (let i = 0; i < new_pg_count; i++)
|
|
{
|
|
const old_i = Math.floor(new_pg_count / mul);
|
|
new_pg_history[i] = JSON.parse(JSON.stringify(prev_pg_history[1+old_i]));
|
|
}
|
|
}
|
|
else if (!(old_pg_count % new_pg_count))
|
|
{
|
|
// Old PG count is a multiple of the new PG count
|
|
const mul = (old_pg_count / new_pg_count);
|
|
for (let i = 0; i < new_pg_count; i++)
|
|
{
|
|
new_pg_history[i] = {
|
|
osd_sets: [],
|
|
all_peers: [],
|
|
epoch: 0,
|
|
};
|
|
for (let j = 0; j < mul; j++)
|
|
{
|
|
new_pg_history[i].osd_sets.push(prev_pgs[i*mul]);
|
|
const hist = prev_pg_history[1+i*mul+j];
|
|
if (hist && hist.osd_sets && hist.osd_sets.length)
|
|
{
|
|
Array.prototype.push.apply(new_pg_history[i].osd_sets, hist.osd_sets);
|
|
}
|
|
if (hist && hist.all_peers && hist.all_peers.length)
|
|
{
|
|
Array.prototype.push.apply(new_pg_history[i].all_peers, hist.all_peers);
|
|
}
|
|
if (hist && hist.epoch)
|
|
{
|
|
new_pg_history[i].epoch = new_pg_history[i].epoch < hist.epoch ? hist.epoch : new_pg_history[i].epoch;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Any PG may intersect with any PG after non-multiple PG count change
|
|
// So, merge ALL PGs history
|
|
let all_sets = {};
|
|
let all_peers = {};
|
|
let max_epoch = 0;
|
|
for (const pg of prev_pgs)
|
|
{
|
|
all_sets[pg.join(' ')] = pg;
|
|
}
|
|
for (const pg in prev_pg_history)
|
|
{
|
|
const hist = prev_pg_history[pg];
|
|
if (hist && hist.osd_sets)
|
|
{
|
|
for (const pg of hist.osd_sets)
|
|
{
|
|
all_sets[pg.join(' ')] = pg;
|
|
}
|
|
}
|
|
if (hist && hist.all_peers)
|
|
{
|
|
for (const osd_num of hist.all_peers)
|
|
{
|
|
all_peers[osd_num] = Number(osd_num);
|
|
}
|
|
}
|
|
if (hist && hist.epoch)
|
|
{
|
|
max_epoch = max_epoch < hist.epoch ? hist.epoch : max_epoch;
|
|
}
|
|
}
|
|
all_sets = Object.values(all_sets);
|
|
all_peers = Object.values(all_peers);
|
|
for (let i = 0; i < new_pg_count; i++)
|
|
{
|
|
new_pg_history[i] = { osd_sets: all_sets, all_peers, epoch: max_epoch };
|
|
}
|
|
}
|
|
// Mark history keys for removed PGs as removed
|
|
for (let i = new_pg_count; i < old_pg_count; i++)
|
|
{
|
|
new_pg_history[i] = null;
|
|
}
|
|
if (old_pg_count < new_pg_count)
|
|
{
|
|
for (let i = new_pg_count-1; i >= 0; i--)
|
|
{
|
|
prev_pgs[i] = prev_pgs[Math.floor(i/new_pg_count*old_pg_count)];
|
|
}
|
|
}
|
|
else if (old_pg_count > new_pg_count)
|
|
{
|
|
for (let i = 0; i < new_pg_count; i++)
|
|
{
|
|
prev_pgs[i] = prev_pgs[Math.round(i/new_pg_count*old_pg_count)];
|
|
}
|
|
prev_pgs.splice(new_pg_count, old_pg_count-new_pg_count);
|
|
}
|
|
}
|