feat(nbd-client): implement getMap based on nbdinfos

This commit is contained in:
Florent BEAUCHAMP
2025-08-26 16:27:51 +00:00
committed by Florent BEAUCHAMP
parent c6d8ccf85a
commit 6c32155327
2 changed files with 48 additions and 0 deletions

View File

@@ -20,6 +20,7 @@ import {
OPTS_MAGIC,
NBD_CMD_DISC,
} from './constants.mjs'
import { spawn } from 'node:child_process'
const { warn } = createLogger('vates:nbd-client')
@@ -358,4 +359,38 @@ export default class NbdClient {
},
})
}
/**
* returns the map of the file with holes, zeros and data, useful to handle efficiently sparse source
* to implement this internally: use structure response if the server supports it, and then ask for BLOCK_STATUS *
*
* @returns {Promise<{ offset: number, length: number, type: number }[]>}
* A promise that resolves to an array where each object represents a segment:
* - `offset` — The byte offset from the start.
* - `length` — The size of the segment in bytes.
* - `type` — A numeric code indicating the segment type ( 0 means no data).
*/
/* async */ getMap() {
return new Promise((resolve, reject) => {
const process = spawn('nbdinfo', [
'--json',
'--map',
`nbd://${this.#serverAddress}:${this.#serverPort}/${encodeURIComponent(this.#exportName)}`,
])
let text = ''
process.stdout.on('data', data => (text += data))
process.on('error', reject)
process.on('close', code => {
if (code !== 0) {
return reject(new Error(`process ended with code ${code}`))
}
try {
const json = JSON.parse(text)
resolve(json)
} catch (error) {
reject(new Error(`${error} ${text}`))
}
})
})
}
}

View File

@@ -129,4 +129,17 @@ export default class MultiNbdClient {
yield readAhead.shift()
}
}
/**
* returns the map of the file with holes, zeros and data, useful to handle efficiently sparse source *
*
* @returns {Promise<{ offset: number, length: number, type: number }[]>}
* A promise that resolves to an array where each object represents a segment:
* - `offset` — The byte offset from the start.
* - `length` — The size of the segment in bytes.
* - `type` — A numeric code indicating the segment type (0 means no data).
*/
async getMap() {
// ask the map from one of the connected client
return this.#clients[Math.floor(this.#clients.length * Math.random())].getMap()
}
}