@@ -7,7 +7,14 @@ const collectStream = require('stream-collector')
7
7
const bjson = require ( 'buffer-json-encoding' )
8
8
const datEncoding = require ( 'dat-encoding' )
9
9
10
- const { fromHyperdriveOptions, toHyperdriveOptions } = require ( 'hyperdrive-daemon-client/lib/common' )
10
+ const {
11
+ fromHyperdriveOptions,
12
+ toHyperdriveOptions,
13
+ fromStat,
14
+ toStat
15
+ } = require ( 'hyperdrive-daemon-client/lib/common' )
16
+ const { rpc } = require ( 'hyperdrive-daemon-client' )
17
+
11
18
const log = require ( '../log' ) . child ( { component : 'drive-manager' } )
12
19
13
20
class DriveManager extends EventEmitter {
@@ -30,6 +37,8 @@ class DriveManager extends EventEmitter {
30
37
// TODO: Replace with an LRU cache.
31
38
this . _drives = new Map ( )
32
39
this . _sessions = new Map ( )
40
+ this . _watchers = new Map ( )
41
+ this . _sessionCounter = 0
33
42
34
43
this . _ready = new Promise ( async resolve => {
35
44
await this . _reseed ( )
@@ -97,6 +106,22 @@ class DriveManager extends EventEmitter {
97
106
return keyString
98
107
}
99
108
109
+ driveForSession ( sessionId ) {
110
+ const drive = this . _sessions . get ( sessionId )
111
+ if ( ! drive ) throw new Error ( 'Session does not exist.' )
112
+ return drive
113
+ }
114
+
115
+ async createSession ( key , opts ) {
116
+ const drive = await this . get ( key , opts )
117
+ this . _sessions . set ( ++ this . _sessionCounter , drive )
118
+ return { drive, session : this . _sessionCounter }
119
+ }
120
+
121
+ async closeSession ( id ) {
122
+ this . _sessions . delete ( id )
123
+ }
124
+
100
125
async get ( key , opts ) {
101
126
key = ( key instanceof Buffer ) ? datEncoding . decode ( key ) : key
102
127
var keyString = this . _generateKeyString ( key , opts )
@@ -121,7 +146,7 @@ class DriveManager extends EventEmitter {
121
146
} )
122
147
123
148
key = datEncoding . encode ( drive . key )
124
- keyString = this . _generateKeystring ( key , opts )
149
+ keyString = this . _generateKeyString ( key , opts )
125
150
126
151
127
152
if ( drive . writable ) {
@@ -192,12 +217,117 @@ function createDriveHandlers (driveManager) {
192
217
var driveOpts = call . request . getOpts ( )
193
218
if ( driveOpts ) driveOpts = fromHyperdriveOptions ( driveOpts )
194
219
195
- const drive = await driveManager . get ( driveOpts . key , driveOpts )
220
+ const { drive, session } = await driveManager . createSession ( driveOpts . key , driveOpts )
196
221
driveOpts . key = drive . key
197
222
driveOpts . version = drive . version
198
223
199
- const rsp = new rpc . drive . messages . GetResponse ( )
200
- rsp . setOpts ( driveOpts )
224
+ const rsp = new rpc . drive . messages . GetDriveResponse ( )
225
+ rsp . setId ( session )
226
+ rsp . setOpts ( toHyperdriveOptions ( driveOpts ) )
227
+
228
+ return rsp
229
+ } ,
230
+
231
+ readFile : async ( call ) => {
232
+ const id = call . request . getId ( )
233
+ const path = call . request . getPath ( )
234
+
235
+ if ( ! id ) throw new Error ( 'A readFile request must specify a session ID.' )
236
+ if ( ! path ) throw new Error ( 'A writeFile request must specify a path.' )
237
+ const drive = driveManager . driveForSession ( id )
238
+
239
+ return new Promise ( ( resolve , reject ) => {
240
+ drive . readFile ( path , ( err , content ) => {
241
+ if ( err ) return reject ( err )
242
+
243
+ const rsp = new rpc . drive . messages . ReadFileResponse ( )
244
+ rsp . setContent ( content )
245
+
246
+ return resolve ( rsp )
247
+ } )
248
+ } )
249
+ } ,
250
+
251
+ writeFile : async ( call ) => {
252
+ const id = call . request . getId ( )
253
+ const path = call . request . getPath ( )
254
+ const contents = Buffer . from ( call . request . getContent ( ) )
255
+
256
+ if ( ! id ) throw new Error ( 'A writeFile request must specify a session ID.' )
257
+ if ( ! path ) throw new Error ( 'A writeFile request must specify a path.' )
258
+ if ( ! contents ) throw new Error ( 'A writeFile request must specify contents.' )
259
+ const drive = driveManager . driveForSession ( id )
260
+
261
+ return new Promise ( ( resolve , reject ) => {
262
+ drive . writeFile ( path , contents , ( err ) => {
263
+ if ( err ) return reject ( err )
264
+ const rsp = new rpc . drive . messages . WriteFileResponse ( )
265
+ return resolve ( rsp )
266
+ } )
267
+ } )
268
+ } ,
269
+
270
+ stat : async ( call ) => {
271
+ const id = call . request . getId ( )
272
+ const path = call . request . getPath ( )
273
+ const lstat = call . request . getLstat ( )
274
+
275
+ if ( ! id ) throw new Error ( 'A stat request must specify a session ID.' )
276
+ if ( ! path ) throw new Error ( 'A stat request must specify a path. ' )
277
+ const drive = driveManager . driveForSession ( id )
278
+
279
+ return new Promise ( ( resolve , reject ) => {
280
+ drive . stat ( path , { followLink : lstat } , ( err , stat ) => {
281
+ if ( err ) return reject ( err )
282
+
283
+ const rsp = new rpc . drive . messages . StatResponse ( )
284
+ rsp . setStat ( toStat ( stat ) )
285
+
286
+ return resolve ( rsp )
287
+ } )
288
+ } )
289
+ } ,
290
+
291
+ readdir : async ( call ) => {
292
+ const id = call . request . getId ( )
293
+ const path = call . request . getPath ( )
294
+ const recursive = call . request . getRecursive ( )
295
+
296
+ if ( ! id ) throw new Error ( 'A readdir request must specify a session ID.' )
297
+ if ( ! path ) throw new Error ( 'A readdir request must specify a path. ' )
298
+ const drive = driveManager . driveForSession ( id )
299
+
300
+ return new Promise ( ( resolve , reject ) => {
301
+ drive . readdir ( path , { recursive } , ( err , files ) => {
302
+ if ( err ) return reject ( err )
303
+
304
+ const rsp = new rpc . drive . messages . ReadDirectoryResponse ( )
305
+ console . log ( 'FILES:' , files )
306
+ rsp . setFilesList ( files )
307
+
308
+ return resolve ( rsp )
309
+ } )
310
+ } )
311
+ } ,
312
+
313
+ watch : async ( call ) => {
314
+
315
+ } ,
316
+
317
+ listen : async ( call ) => {
318
+
319
+ } ,
320
+
321
+ unwatch : async ( call ) => {
322
+
323
+ } ,
324
+
325
+ closeSession : async ( call ) => {
326
+ const id = call . request . getId ( )
327
+
328
+ const drive = driveManager . driveForSession ( id )
329
+ driveManager . closeSession ( id )
330
+ const rsp = new rpc . drive . messages . CloseSessionResponse ( )
201
331
202
332
return rsp
203
333
}
0 commit comments