@@ -13,7 +13,8 @@ const {
13
13
fromStat,
14
14
toStat,
15
15
toMount,
16
- fromMount
16
+ fromMount,
17
+ toDriveStats
17
18
} = require ( 'hyperdrive-daemon-client/lib/common' )
18
19
const { rpc } = require ( 'hyperdrive-daemon-client' )
19
20
@@ -124,6 +125,41 @@ class DriveManager extends EventEmitter {
124
125
this . _sessions . delete ( id )
125
126
}
126
127
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
+
127
163
async get ( key , opts ) {
128
164
key = ( key instanceof Buffer ) ? datEncoding . decode ( key ) : key
129
165
var keyString = this . _generateKeyString ( key , opts )
@@ -224,6 +260,7 @@ function createDriveHandlers (driveManager) {
224
260
const { drive, session } = await driveManager . createSession ( driveOpts . key , driveOpts )
225
261
driveOpts . key = drive . key
226
262
driveOpts . version = drive . version
263
+ driveOpts . writable = drive . writable
227
264
228
265
const rsp = new rpc . drive . messages . GetDriveResponse ( )
229
266
rsp . setId ( session )
@@ -232,6 +269,16 @@ function createDriveHandlers (driveManager) {
232
269
return rsp
233
270
} ,
234
271
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
+
235
282
publish : async ( call ) => {
236
283
const id = call . request . getId ( )
237
284
@@ -256,6 +303,19 @@ function createDriveHandlers (driveManager) {
256
303
return rsp
257
304
} ,
258
305
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
+
259
319
readFile : async ( call ) => {
260
320
const id = call . request . getId ( )
261
321
const path = call . request . getPath ( )
@@ -337,6 +397,61 @@ function createDriveHandlers (driveManager) {
337
397
} )
338
398
} ,
339
399
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
+
340
455
mount : async ( call ) => {
341
456
const id = call . request . getId ( )
342
457
const path = call . request . getPath ( )
@@ -357,15 +472,26 @@ function createDriveHandlers (driveManager) {
357
472
} ,
358
473
359
474
watch : async ( call ) => {
475
+ const id = call . request . getId ( )
476
+ var path = call . request . getPath ( )
360
477
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 )
368
481
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
+ }
369
495
} ,
370
496
371
497
close : async ( call ) => {
0 commit comments