Skip to content

Commit

Permalink
feat(vhd-lib): merge blocks in parallel for VhdDirectory, throttle me…
Browse files Browse the repository at this point in the history
…rgestate writes
  • Loading branch information
fbeauchamp authored and julien-f committed Jan 24, 2022
1 parent 52d9d13 commit e530307
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- [Backup] Add sanity check of aliases on S3 remotes (PR [#6043](https://github.com/vatesfr/xen-orchestra/pull/6043))
- [Export/Disks] Allow the export of disks in VMDK format (PR [#5982](https://github.com/vatesfr/xen-orchestra/pull/5982))
- [Rolling Pool Update] Automatically pause load balancer plugin during the update [#5711](https://github.com/vatesfr/xen-orchestra/issues/5711)
- [Backup] Speedup merge and cleanup speed for S3 backup by a factor 10 (PR [#6100](https://github.com/vatesfr/xen-orchestra/pull/6100))

### Bug fixes

Expand Down
58 changes: 41 additions & 17 deletions packages/vhd-lib/merge.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,22 @@ const { openVhd } = require('./openVhd')
const { basename, dirname } = require('path')
const { DISK_TYPES } = require('./_constants')
const { Disposable } = require('promise-toolbox')
const { asyncEach } = require('@vates/async-each')
const { VhdDirectory } = require('./Vhd/VhdDirectory')

const { warn } = createLogger('vhd-lib:merge')

function makeThrottledWriter(handler, path, delay) {
let lastWrite = Date.now()
return async json => {
const now = Date.now()
if (now - lastWrite > delay) {
lastWrite = now
await handler.writeFile(path, JSON.stringify(json), { flags: 'w' }).catch(warn)
}
}
}

// Merge vhd child into vhd parent.
//
// TODO: rename the VHD file during the merge
Expand Down Expand Up @@ -43,6 +56,7 @@ module.exports = limitConcurrency(2)(async function merge(
})
const childVhd = yield openVhd(childHandler, childPath)

const concurrency = childVhd instanceof VhdDirectory ? 16 : 1
if (mergeState === undefined) {
assert.strictEqual(childVhd.header.blockSize, parentVhd.header.blockSize)

Expand Down Expand Up @@ -76,30 +90,40 @@ module.exports = limitConcurrency(2)(async function merge(
}

// counts number of allocated blocks
let nBlocks = 0
const toMerge = []
for (let block = mergeState.currentBlock; block < maxTableEntries; block++) {
if (childVhd.containsBlock(block)) {
nBlocks += 1
toMerge.push(block)
}
}

const nBlocks = toMerge.length
onProgress({ total: nBlocks, done: 0 })

// merges blocks
for (let i = 0; i < nBlocks; ++i, ++mergeState.currentBlock) {
while (!childVhd.containsBlock(mergeState.currentBlock)) {
++mergeState.currentBlock
const merging = new Set()
let counter = 0

const mergeStateWriter = makeThrottledWriter(parentHandler, mergeStatePath, 10e3)

await asyncEach(
toMerge,
async blockId => {
merging.add(blockId)
mergeState.mergedDataSize += await parentVhd.coalesceBlock(childVhd, blockId)
merging.delete(blockId)

onProgress({
total: nBlocks,
done: counter + 1,
})
counter++
mergeState.currentBlock = Math.min(...merging)
mergeStateWriter(mergeState)
},
{
concurrency,
}

await parentHandler.writeFile(mergeStatePath, JSON.stringify(mergeState), { flags: 'w' }).catch(warn)

mergeState.mergedDataSize += await parentVhd.coalesceBlock(childVhd, mergeState.currentBlock)
onProgress({
total: nBlocks,
done: i + 1,
})
}

)
onProgress({ total: nBlocks, done: nBlocks })
// some blocks could have been created or moved in parent : write bat
await parentVhd.writeBlockAllocationTable()

Expand Down

0 comments on commit e530307

Please sign in to comment.