Skip to content

Commit 7ec87c6

Browse files
committed
Added stats methods
1 parent ab1ec3a commit 7ec87c6

File tree

3 files changed

+138
-9
lines changed

3 files changed

+138
-9
lines changed

index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ class HyperdriveDaemon extends EventEmitter {
3737

3838
const corestoreOpts = {
3939
storage: path => raf(`${storage}/cores/${path}`),
40-
sparse: true
40+
sparse: true,
41+
// Collect networking statistics.
42+
stats: true
4143
}
4244
this.corestore = corestore(corestoreOpts.storage, corestoreOpts)
4345
// The root corestore should be bootstrapped with an empty default feed.

lib/drives/index.js

Lines changed: 134 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ const {
1313
fromStat,
1414
toStat,
1515
toMount,
16-
fromMount
16+
fromMount,
17+
toDriveStats
1718
} = require('hyperdrive-daemon-client/lib/common')
1819
const { rpc } = require('hyperdrive-daemon-client')
1920

@@ -124,6 +125,41 @@ class DriveManager extends EventEmitter {
124125
this._sessions.delete(id)
125126
}
126127

128+
async getAllStats () {
129+
const allStats = []
130+
for (const [keyString, drive] of this._drives) {
131+
const driveStats = await this.getDriveStats(drive)
132+
allStats.push(driveStats)
133+
}
134+
return allStats
135+
}
136+
137+
async getDriveStats (drive) {
138+
const mounts = await drive.getAllMounts({ memory: true })
139+
const stats = []
140+
141+
for (const { path, metadata, content} of mounts) {
142+
stats.push({
143+
path,
144+
metadata: getCoreStats(metadata),
145+
content: getCoreStats(content)
146+
})
147+
}
148+
149+
return stats
150+
151+
function getCoreStats (core) {
152+
const stats = core.stats
153+
return {
154+
key: core.key,
155+
peers: stats.peers.length,
156+
uploadedBytes: stats.totals.uploadedBytes,
157+
downloadedBytes: stats.totals.downloadedBytes
158+
// TODO: Store comulative totals across restarts
159+
}
160+
}
161+
}
162+
127163
async get (key, opts) {
128164
key = (key instanceof Buffer) ? datEncoding.decode(key) : key
129165
var keyString = this._generateKeyString(key, opts)
@@ -224,6 +260,7 @@ function createDriveHandlers (driveManager) {
224260
const { drive, session } = await driveManager.createSession(driveOpts.key, driveOpts)
225261
driveOpts.key = drive.key
226262
driveOpts.version = drive.version
263+
driveOpts.writable = drive.writable
227264

228265
const rsp = new rpc.drive.messages.GetDriveResponse()
229266
rsp.setId(session)
@@ -232,6 +269,16 @@ function createDriveHandlers (driveManager) {
232269
return rsp
233270
},
234271

272+
allStats: async (call) => {
273+
var stats = await driveManager.getAllStats()
274+
stats = stats.map(driveStats => toDriveStats(driveStats))
275+
276+
const rsp = new rpc.drive.messages
277+
rsp.setStats(stats)
278+
279+
return rsp
280+
},
281+
235282
publish: async (call) => {
236283
const id = call.request.getId()
237284

@@ -256,6 +303,19 @@ function createDriveHandlers (driveManager) {
256303
return rsp
257304
},
258305

306+
stats: async (call) => {
307+
const id = call.request.getId()
308+
309+
if (!id) throw new Error('A stats request must specify a session ID.')
310+
const drive = driveManager.driveForSession(id)
311+
312+
const stats = await driveManager.getDriveStats(drive)
313+
314+
const rsp = new rpc.drive.messages.DriveStatsResponse()
315+
rsp.setStats(toDriveStats(stats))
316+
return rsp
317+
},
318+
259319
readFile: async (call) => {
260320
const id = call.request.getId()
261321
const path = call.request.getPath()
@@ -337,6 +397,61 @@ function createDriveHandlers (driveManager) {
337397
})
338398
},
339399

400+
mkdir: async (call) => {
401+
const id = call.request.getId()
402+
const path = call.request.getPath()
403+
const mode = call.request.getMode()
404+
405+
if (!id) throw new Error('A mkdir request must specify a session ID.')
406+
if (!path) throw new Error('A mkdir request must specify a directory path.')
407+
const drive = driveManager.driveForSession(id)
408+
409+
return new Promise((resolve, reject) => {
410+
drive.mkdir(path, mode, err => {
411+
if (err) return reject(err)
412+
413+
const rsp = new rpc.drive.messages.MkdirResponse()
414+
return resolve(rsp)
415+
})
416+
})
417+
},
418+
419+
rmdir: async (call) => {
420+
const id = call.request.getId()
421+
const path = call.request.getPath()
422+
423+
if (!id) throw new Error('A rmdir request must specify a session ID.')
424+
if (!path) throw new Error('A rmdir request must specify a directory path.')
425+
const drive = driveManager.driveForSession(id)
426+
427+
return new Promise((resolve, reject) => {
428+
drive.rmdir(path, err => {
429+
if (err) return reject(err)
430+
431+
const rsp = new rpc.drive.messages.RmdirResponse()
432+
return resolve(rsp)
433+
})
434+
})
435+
},
436+
437+
unlink: async (call) => {
438+
const id = call.request.getId()
439+
const path = call.request.getPath()
440+
441+
if (!id) throw new Error('An unlink request must specify a session ID.')
442+
if (!path) throw new Error('An unlink request must specify a path.')
443+
const drive = driveManager.driveForSession(id)
444+
445+
return new Promise((resolve, reject) => {
446+
drive.unlink(path, err => {
447+
if (err) return reject(err)
448+
449+
const rsp = new rpc.drive.messages.UnlinkResponse()
450+
return resolve(rsp)
451+
})
452+
})
453+
},
454+
340455
mount: async (call) => {
341456
const id = call.request.getId()
342457
const path = call.request.getPath()
@@ -357,15 +472,26 @@ function createDriveHandlers (driveManager) {
357472
},
358473

359474
watch: async (call) => {
475+
const id = call.request.getId()
476+
var path = call.request.getPath()
360477

361-
},
362-
363-
listen: async (call) => {
364-
365-
},
366-
367-
unwatch: async (call) => {
478+
if (!id) throw new Error('A watch request must specify a session ID.')
479+
if (!path) path = '/'
480+
const drive = driveManager.driveForSession(id)
368481

482+
const watcher = drive.watch(path, () => {
483+
const rsp = new rpc.drive.messages.WatchResponse()
484+
call.write(rsp)
485+
})
486+
call.on('close', onclose)
487+
call.on('finish', onclose)
488+
call.on('error', onclose)
489+
490+
function onclose (err) {
491+
watcher.destroy()
492+
log.debug({ id, path }, 'unregistering watcher')
493+
if (err && !call.destroyed) call.destroy(err)
494+
}
369495
},
370496

371497
close: async (call) => {

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
},
2626
"homepage": "https://github.com/andrewosh/hyperdrive-daemon#readme",
2727
"dependencies": {
28+
"@grpc/grpc-js": "^0.5.1",
2829
"buffer-json-encoding": "^1.0.2",
2930
"chalk": "^2.4.2",
3031
"collect-stream": "^1.2.1",

0 commit comments

Comments
 (0)