wao 0.11.0 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/aoconnect-base.js +1 -1
- package/cjs/armem-base.js +91 -69
- package/cjs/armem-web.js +1 -2
- package/cjs/armem.js +1 -2
- package/cjs/bao.js +8 -7
- package/cjs/compress.js +0 -1
- package/cjs/wao.js +61 -1
- package/cjs/waosm/waosm.js +19 -48
- package/cjs/waosm-node/waosm_bg.js +19 -48
- package/cjs/weavedrive.js +299 -370
- package/esm/aoconnect-base.js +1 -1
- package/esm/armem-base.js +26 -9
- package/esm/armem-web.js +2 -2
- package/esm/armem.js +2 -2
- package/esm/bao.js +2 -2
- package/esm/compress.js +0 -1
- package/esm/wao.js +19 -1
- package/esm/waosm/README.md +7 -3
- package/esm/waosm/waosm.d.ts +6 -12
- package/esm/waosm/waosm.js +11 -35
- package/esm/waosm/waosm_bg.wasm +0 -0
- package/esm/waosm/waosm_bg.wasm.d.ts +4 -6
- package/esm/waosm-node/README.md +7 -3
- package/esm/waosm-node/waosm.d.ts +2 -6
- package/esm/waosm-node/waosm_bg.js +11 -35
- package/esm/waosm-node/waosm_bg.wasm +0 -0
- package/esm/waosm-node/waosm_bg.wasm.d.ts +4 -6
- package/esm/weavedrive.js +145 -249
- package/package.json +1 -1
package/esm/weavedrive.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const KB = 1024
|
|
2
2
|
const MB = KB * 1024
|
|
3
|
-
const CACHE_SZ = 32 * KB
|
|
4
|
-
const CHUNK_SZ =
|
|
5
|
-
const
|
|
3
|
+
const CACHE_SZ = 32 * KB // Keep small cache size
|
|
4
|
+
const CHUNK_SZ = 1 * MB // Reduced from 128MB to 1MB for better memory management
|
|
5
|
+
const STREAM_CHUNK = 256 * KB // Added smaller streaming chunk size
|
|
6
6
|
const log = console.log
|
|
7
7
|
|
|
8
8
|
export default class WeaveDrive {
|
|
@@ -10,50 +10,43 @@ export default class WeaveDrive {
|
|
|
10
10
|
this.ext = (mod, FS) => {
|
|
11
11
|
return {
|
|
12
12
|
reset(fd) {
|
|
13
|
-
//console.log("WeaveDrive: Resetting fd: ", fd)
|
|
14
13
|
FS.streams[fd].node.position = 0
|
|
15
14
|
FS.streams[fd].node.cache = new Uint8Array(0)
|
|
16
15
|
},
|
|
17
16
|
|
|
18
17
|
async create(id) {
|
|
19
|
-
var properties = { isDevice: false, contents: null }
|
|
20
|
-
|
|
21
|
-
//console.log("WeaveDrive: Arweave ID is not admissable! ", id)
|
|
22
18
|
if (!(await this.checkAdmissible(id))) return 0
|
|
23
19
|
|
|
24
|
-
// Create the file in the emscripten FS
|
|
25
|
-
|
|
26
20
|
if (!FS.analyzePath("/data/").exists) FS.mkdir("/data/")
|
|
27
21
|
|
|
22
|
+
var properties = { isDevice: false, contents: null }
|
|
28
23
|
var node = FS.createFile("/", "data/" + id, properties, true, false)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
|
|
25
|
+
let bytesLength = 0
|
|
26
|
+
try {
|
|
27
|
+
let data = await ar.data(id)
|
|
28
|
+
bytesLength = data?.length ?? 0
|
|
29
|
+
} catch (e) {
|
|
30
|
+
console.error("Failed to get data length:", e)
|
|
31
|
+
return 0
|
|
32
|
+
}
|
|
33
|
+
|
|
37
34
|
node.total_size = Number(bytesLength)
|
|
38
35
|
node.cache = new Uint8Array(0)
|
|
39
36
|
node.position = 0
|
|
37
|
+
node.chunks = new Map() // Add chunk cache
|
|
40
38
|
|
|
41
|
-
// Add a function that defers querying the file size until it is asked the first time.
|
|
42
39
|
Object.defineProperties(node, {
|
|
43
40
|
usedBytes: { get: () => bytesLength },
|
|
44
41
|
})
|
|
45
42
|
|
|
46
|
-
// Now we have created the file in the emscripten FS, we can open it as a stream
|
|
47
43
|
var stream = FS.open("/data/" + id, "r")
|
|
48
|
-
|
|
49
|
-
//console.log("JS: Created file: ", id, " fd: ", stream.fd);
|
|
50
44
|
return stream
|
|
51
45
|
},
|
|
46
|
+
|
|
52
47
|
async createBlockHeader(id) {
|
|
53
48
|
var result = ""
|
|
54
49
|
try {
|
|
55
|
-
// todo: implement indep_hash
|
|
56
|
-
// fetch(`/block/height/${id}`)
|
|
57
50
|
const block = ar.mem.blockmap[ar.mem.blocks[id]]
|
|
58
51
|
if (block) {
|
|
59
52
|
result = JSON.stringify({
|
|
@@ -77,9 +70,9 @@ export default class WeaveDrive {
|
|
|
77
70
|
var stream = FS.open("/block/" + id, "r")
|
|
78
71
|
return stream
|
|
79
72
|
},
|
|
73
|
+
|
|
80
74
|
async createTxHeader(id) {
|
|
81
75
|
var result = ""
|
|
82
|
-
// fetch(`/tx/${id}`)
|
|
83
76
|
try {
|
|
84
77
|
let tx = ar.mem.txs[id]
|
|
85
78
|
if (tx) result = JSON.stringify(tx)
|
|
@@ -94,6 +87,7 @@ export default class WeaveDrive {
|
|
|
94
87
|
var stream = FS.open("/tx/" + id, "r")
|
|
95
88
|
return stream
|
|
96
89
|
},
|
|
90
|
+
|
|
97
91
|
async createDataItemTxHeader(id) {
|
|
98
92
|
let result = (
|
|
99
93
|
await ar.gql.txs({
|
|
@@ -124,255 +118,98 @@ export default class WeaveDrive {
|
|
|
124
118
|
var stream = FS.open("/tx2/" + id, "r")
|
|
125
119
|
return stream
|
|
126
120
|
},
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
FS.createPath("/", "tx2", true, false)
|
|
144
|
-
if (FS.analyzePath(filename).exists) {
|
|
145
|
-
var stream = FS.open(filename, "r")
|
|
146
|
-
if (stream.fd) return stream.fd
|
|
147
|
-
return 0
|
|
148
|
-
} else {
|
|
149
|
-
const stream = await this.createDataItemTxHeader(id)
|
|
150
|
-
if (stream.fd) return stream.fd
|
|
151
|
-
return 0
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
if (pathCategory === "block") {
|
|
155
|
-
FS.createPath("/", "block", true, false)
|
|
156
|
-
if (FS.analyzePath(filename).exists) {
|
|
157
|
-
var stream = FS.open(filename, "r")
|
|
158
|
-
if (stream.fd) return stream.fd
|
|
159
|
-
return 0
|
|
160
|
-
} else {
|
|
161
|
-
const stream = await this.createBlockHeader(id)
|
|
162
|
-
return stream.fd
|
|
163
|
-
}
|
|
121
|
+
|
|
122
|
+
// Chunk management helpers
|
|
123
|
+
getChunkKey(position) {
|
|
124
|
+
return Math.floor(position / CHUNK_SZ)
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
async fetchChunk(stream, chunkKey) {
|
|
128
|
+
const start = chunkKey * CHUNK_SZ
|
|
129
|
+
const end = Math.min(start + CHUNK_SZ, stream.node.total_size)
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
const data = await ar.data(stream.node.name)
|
|
133
|
+
return data.subarray(start, end)
|
|
134
|
+
} catch (e) {
|
|
135
|
+
console.error("Failed to fetch chunk:", e)
|
|
136
|
+
return new Uint8Array(0)
|
|
164
137
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
138
|
+
},
|
|
139
|
+
|
|
140
|
+
async ensureChunkLoaded(stream, position) {
|
|
141
|
+
const chunkKey = this.getChunkKey(position)
|
|
142
|
+
|
|
143
|
+
if (!stream.node.chunks.has(chunkKey)) {
|
|
144
|
+
// Remove old chunks if we have too many
|
|
145
|
+
if (stream.node.chunks.size >= 3) {
|
|
146
|
+
// Keep only 3 chunks in memory
|
|
147
|
+
const oldestKey = stream.node.chunks.keys().next().value
|
|
148
|
+
stream.node.chunks.delete(oldestKey)
|
|
176
149
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
} else {
|
|
181
|
-
console.log("JS: Invalid path category: ", pathCategory)
|
|
182
|
-
return 0
|
|
150
|
+
|
|
151
|
+
const chunk = await this.fetchChunk(stream, chunkKey)
|
|
152
|
+
stream.node.chunks.set(chunkKey, chunk)
|
|
183
153
|
}
|
|
154
|
+
|
|
155
|
+
return stream.node.chunks.get(chunkKey)
|
|
184
156
|
},
|
|
185
157
|
|
|
186
158
|
async read(fd, raw_dst_ptr, raw_length) {
|
|
187
|
-
// Note: The length and dst_ptr are 53 bit integers in JS, so this _should_ be ok into a large memspace.
|
|
188
159
|
var to_read = Number(raw_length)
|
|
189
160
|
var dst_ptr = Number(raw_dst_ptr)
|
|
190
161
|
|
|
191
|
-
var stream =
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (stream.path.includes("/block")) {
|
|
197
|
-
mod.HEAP8.set(stream.node.contents.subarray(0, to_read), dst_ptr)
|
|
198
|
-
return to_read
|
|
199
|
-
}
|
|
200
|
-
// read tx headers
|
|
201
|
-
if (stream.path.includes("/tx")) {
|
|
162
|
+
var stream = FS.streams.find(s => s.fd === fd)
|
|
163
|
+
if (!stream) return 0
|
|
164
|
+
|
|
165
|
+
// Handle block and tx headers
|
|
166
|
+
if (stream.path.includes("/block") || stream.path.includes("/tx")) {
|
|
202
167
|
mod.HEAP8.set(stream.node.contents.subarray(0, to_read), dst_ptr)
|
|
203
168
|
return to_read
|
|
204
169
|
}
|
|
205
|
-
// Satisfy what we can with the cache first
|
|
206
|
-
var bytes_read = this.readFromCache(stream, dst_ptr, to_read)
|
|
207
|
-
stream.position += bytes_read
|
|
208
|
-
stream.lastReadPosition = stream.position
|
|
209
|
-
dst_ptr += bytes_read
|
|
210
|
-
to_read -= bytes_read
|
|
211
170
|
|
|
212
|
-
|
|
171
|
+
let bytesRead = 0
|
|
172
|
+
while (to_read > 0) {
|
|
173
|
+
// Get current chunk
|
|
174
|
+
const chunk = await this.ensureChunkLoaded(stream, stream.position)
|
|
175
|
+
const chunkOffset = stream.position % CHUNK_SZ
|
|
213
176
|
|
|
214
|
-
|
|
215
|
-
|
|
177
|
+
// Calculate how much we can read from this chunk
|
|
178
|
+
const available = chunk.length - chunkOffset
|
|
179
|
+
const readSize = Math.min(to_read, available)
|
|
216
180
|
|
|
217
|
-
|
|
181
|
+
if (readSize <= 0) break
|
|
218
182
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
stream.position + chunk_download_sz,
|
|
223
|
-
)
|
|
224
|
-
//console.log("WeaveDrive: fd: ", fd, " Read length: ", to_read, " Reading ahead:", to - to_read - stream.position)
|
|
225
|
-
|
|
226
|
-
// fetch(`/${stream.node.name}`)
|
|
227
|
-
const data = await ar.data(stream.node.name, null, log)
|
|
228
|
-
// Extract the Range header to determine the start and end of the requested chunk
|
|
229
|
-
const start = stream.position
|
|
230
|
-
const end = to
|
|
231
|
-
|
|
232
|
-
// Create a ReadableStream for the requested chunk
|
|
233
|
-
const chunk = data.subarray(start, end)
|
|
234
|
-
const response = new Response(
|
|
235
|
-
new ReadableStream({
|
|
236
|
-
start(controller) {
|
|
237
|
-
controller.enqueue(chunk)
|
|
238
|
-
controller.close()
|
|
239
|
-
},
|
|
240
|
-
}),
|
|
241
|
-
{
|
|
242
|
-
headers: { "content-length": chunk.length.toString() },
|
|
243
|
-
},
|
|
244
|
-
)
|
|
245
|
-
const reader = response.body.getReader()
|
|
246
|
-
var bytes_until_cache = CHUNK_SZ
|
|
247
|
-
var bytes_until_notify = NOTIFY_SZ
|
|
248
|
-
var downloaded_bytes = 0
|
|
249
|
-
var cache_chunks = []
|
|
250
|
-
|
|
251
|
-
try {
|
|
252
|
-
while (true) {
|
|
253
|
-
const { done, value: chunk_bytes } = await reader.read()
|
|
254
|
-
if (done) break
|
|
255
|
-
// Update the number of downloaded bytes to be _all_, not just the write length
|
|
256
|
-
downloaded_bytes += chunk_bytes.length
|
|
257
|
-
bytes_until_cache -= chunk_bytes.length
|
|
258
|
-
bytes_until_notify -= chunk_bytes.length
|
|
259
|
-
|
|
260
|
-
// Write bytes from the chunk and update the pointer if necessary
|
|
261
|
-
const write_length = Math.min(chunk_bytes.length, to_read)
|
|
262
|
-
if (write_length > 0) {
|
|
263
|
-
//console.log("WeaveDrive: Writing: ", write_length, " bytes to: ", dst_ptr)
|
|
264
|
-
mod.HEAP8.set(chunk_bytes.subarray(0, write_length), dst_ptr)
|
|
265
|
-
dst_ptr += write_length
|
|
266
|
-
bytes_read += write_length
|
|
267
|
-
stream.position += write_length
|
|
268
|
-
to_read -= write_length
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
if (to_read == 0) {
|
|
272
|
-
// Add excess bytes to our cache
|
|
273
|
-
const chunk_to_cache = chunk_bytes.subarray(write_length)
|
|
274
|
-
//console.log("WeaveDrive: Cacheing excess: ", chunk_to_cache.length)
|
|
275
|
-
cache_chunks.push(chunk_to_cache)
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (bytes_until_cache <= 0) {
|
|
279
|
-
console.log(
|
|
280
|
-
"WeaveDrive: Chunk size reached. Compressing cache...",
|
|
281
|
-
)
|
|
282
|
-
stream.node.cache = this.addChunksToCache(
|
|
283
|
-
stream.node.cache,
|
|
284
|
-
cache_chunks,
|
|
285
|
-
)
|
|
286
|
-
cache_chunks = []
|
|
287
|
-
bytes_until_cache = CHUNK_SZ
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
if (bytes_until_notify <= 0) {
|
|
291
|
-
console.log(
|
|
292
|
-
"WeaveDrive: Downloaded: ",
|
|
293
|
-
(downloaded_bytes / stream.node.total_size) * 100,
|
|
294
|
-
"%",
|
|
295
|
-
)
|
|
296
|
-
bytes_until_notify = NOTIFY_SZ
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
} catch (error) {
|
|
300
|
-
console.error("WeaveDrive: Error reading the stream: ", error)
|
|
301
|
-
} finally {
|
|
302
|
-
reader.releaseLock()
|
|
303
|
-
}
|
|
304
|
-
// If we have no cache, or we have not satisfied the full request, we need to download the rest
|
|
305
|
-
// Rebuild the cache from the new cache chunks
|
|
306
|
-
stream.node.cache = this.addChunksToCache(
|
|
307
|
-
stream.node.cache,
|
|
308
|
-
cache_chunks,
|
|
309
|
-
)
|
|
183
|
+
// Copy data to destination
|
|
184
|
+
const data = chunk.subarray(chunkOffset, chunkOffset + readSize)
|
|
185
|
+
mod.HEAP8.set(data, dst_ptr)
|
|
310
186
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
var stream = 0
|
|
317
|
-
for (var i = 0; i < FS.streams.length; i++) {
|
|
318
|
-
if (FS.streams[i].fd === fd) stream = FS.streams[i]
|
|
187
|
+
// Update pointers
|
|
188
|
+
stream.position += readSize
|
|
189
|
+
dst_ptr += readSize
|
|
190
|
+
to_read -= readSize
|
|
191
|
+
bytesRead += readSize
|
|
319
192
|
}
|
|
320
|
-
FS.close(stream)
|
|
321
|
-
},
|
|
322
193
|
|
|
323
|
-
|
|
324
|
-
readFromCache(stream, dst_ptr, length) {
|
|
325
|
-
// Check if the cache has been invalidated by a seek
|
|
326
|
-
if (stream.lastReadPosition !== stream.position) {
|
|
327
|
-
//console.log("WeaveDrive: Invalidating cache for fd: ", stream.fd, " Current pos: ", stream.position, " Last read pos: ", stream.lastReadPosition)
|
|
328
|
-
stream.node.cache = new Uint8Array(0)
|
|
329
|
-
return 0
|
|
330
|
-
}
|
|
331
|
-
// Calculate the bytes of the request that can be satisfied with the cache
|
|
332
|
-
var cache_part_length = Math.min(length, stream.node.cache.length)
|
|
333
|
-
var cache_part = stream.node.cache.subarray(0, cache_part_length)
|
|
334
|
-
mod.HEAP8.set(cache_part, dst_ptr)
|
|
335
|
-
// Set the new cache to the remainder of the unused cache and update pointers
|
|
336
|
-
stream.node.cache = stream.node.cache.subarray(cache_part_length)
|
|
337
|
-
|
|
338
|
-
return cache_part_length
|
|
194
|
+
return bytesRead
|
|
339
195
|
},
|
|
340
196
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
var
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
)
|
|
348
|
-
var new_cache = new Uint8Array(new_cache_length)
|
|
349
|
-
// Copy the old cache to the new cache
|
|
350
|
-
new_cache.set(old_cache, 0)
|
|
351
|
-
// Load the cache chunks into the new cache
|
|
352
|
-
var current_offset = old_cache.length
|
|
353
|
-
for (let chunk of chunks) {
|
|
354
|
-
if (current_offset < new_cache_length) {
|
|
355
|
-
new_cache.set(
|
|
356
|
-
chunk.subarray(0, new_cache_length - current_offset),
|
|
357
|
-
current_offset,
|
|
358
|
-
)
|
|
359
|
-
current_offset += chunk.length
|
|
360
|
-
}
|
|
197
|
+
// Keep existing helper methods
|
|
198
|
+
close(fd) {
|
|
199
|
+
var stream = FS.streams.find(s => s.fd === fd)
|
|
200
|
+
if (stream) {
|
|
201
|
+
stream.node.chunks?.clear() // Clean up chunks
|
|
202
|
+
FS.close(stream)
|
|
361
203
|
}
|
|
362
|
-
return new_cache
|
|
363
204
|
},
|
|
364
205
|
|
|
365
|
-
//
|
|
206
|
+
// ... rest of the existing methods (checkAdmissible, getTagValues, etc.) ...
|
|
366
207
|
async checkAdmissible(ID) {
|
|
367
|
-
// CAUTION: If the module is initiated with `mode = test` we don't check availability.
|
|
368
208
|
if (mod.mode && mod.mode == "test") return true
|
|
369
209
|
|
|
370
|
-
// Check if we are attempting to load the On-Boot id, if so allow it
|
|
371
|
-
// this was added for AOP 6 Boot loader See: https://github.com/permaweb/aos/issues/342
|
|
372
210
|
const bootTag = this.getTagValue("On-Boot", mod.spawn.tags)
|
|
373
211
|
if (bootTag && bootTag === ID) return true
|
|
374
212
|
|
|
375
|
-
// Check that this module or process set the WeaveDrive tag on spawn
|
|
376
213
|
const blockHeight = mod.blockHeight
|
|
377
214
|
const moduleExtensions = this.getTagValues(
|
|
378
215
|
"Extension",
|
|
@@ -393,18 +230,16 @@ export default class WeaveDrive {
|
|
|
393
230
|
)
|
|
394
231
|
return false
|
|
395
232
|
}
|
|
233
|
+
|
|
396
234
|
const modes = ["Assignments", "Individual", "Library"]
|
|
397
|
-
// Get the Availability-Type from the spawned process's Module or Process item
|
|
398
|
-
// First check the module for its defaults
|
|
399
235
|
const moduleAvailabilityType = this.getTagValue(
|
|
400
236
|
"Availability-Type",
|
|
401
237
|
mod.module.tags,
|
|
402
238
|
)
|
|
403
239
|
const moduleMode = moduleAvailabilityType
|
|
404
240
|
? moduleAvailabilityType
|
|
405
|
-
: "Assignments"
|
|
241
|
+
: "Assignments"
|
|
406
242
|
|
|
407
|
-
// Now check the process's spawn item. These settings override Module item settings.
|
|
408
243
|
const processAvailabilityType = this.getTagValue(
|
|
409
244
|
"Availability-Type",
|
|
410
245
|
mod.spawn.tags,
|
|
@@ -423,8 +258,7 @@ export default class WeaveDrive {
|
|
|
423
258
|
...this.getTagValues("Attestor", mod.spawn.tags),
|
|
424
259
|
].filter(t => !!t),
|
|
425
260
|
)
|
|
426
|
-
|
|
427
|
-
// Every WeaveDrive process has at least the "Assignments" availability check form.
|
|
261
|
+
|
|
428
262
|
const exists = async tags => {
|
|
429
263
|
const common = {
|
|
430
264
|
owners: attestors,
|
|
@@ -433,6 +267,7 @@ export default class WeaveDrive {
|
|
|
433
267
|
}
|
|
434
268
|
return (await ar.gql.txs({ ...common, tags })).length > 0
|
|
435
269
|
}
|
|
270
|
+
|
|
436
271
|
const assignmentsHaveID = await exists({
|
|
437
272
|
Type: "Attestation",
|
|
438
273
|
Message: ID,
|
|
@@ -472,6 +307,67 @@ export default class WeaveDrive {
|
|
|
472
307
|
const values = this.getTagValues(key, tags)
|
|
473
308
|
return values.pop()
|
|
474
309
|
},
|
|
310
|
+
|
|
311
|
+
async open(filename) {
|
|
312
|
+
const pathCategory = filename.split("/")[1]
|
|
313
|
+
const id = filename.split("/")[2]
|
|
314
|
+
console.log("JS: Opening ID: ", id)
|
|
315
|
+
|
|
316
|
+
if (pathCategory === "tx") {
|
|
317
|
+
FS.createPath("/", "tx", true, false)
|
|
318
|
+
if (FS.analyzePath(filename).exists) {
|
|
319
|
+
var stream = FS.open(filename, "r")
|
|
320
|
+
if (stream.fd) return stream.fd
|
|
321
|
+
return 0
|
|
322
|
+
} else {
|
|
323
|
+
const stream = await this.createTxHeader(id)
|
|
324
|
+
return stream.fd
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (pathCategory === "tx2") {
|
|
329
|
+
FS.createPath("/", "tx2", true, false)
|
|
330
|
+
if (FS.analyzePath(filename).exists) {
|
|
331
|
+
var stream = FS.open(filename, "r")
|
|
332
|
+
if (stream.fd) return stream.fd
|
|
333
|
+
return 0
|
|
334
|
+
} else {
|
|
335
|
+
const stream = await this.createDataItemTxHeader(id)
|
|
336
|
+
if (stream.fd) return stream.fd
|
|
337
|
+
return 0
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (pathCategory === "block") {
|
|
342
|
+
FS.createPath("/", "block", true, false)
|
|
343
|
+
if (FS.analyzePath(filename).exists) {
|
|
344
|
+
var stream = FS.open(filename, "r")
|
|
345
|
+
if (stream.fd) return stream.fd
|
|
346
|
+
return 0
|
|
347
|
+
} else {
|
|
348
|
+
const stream = await this.createBlockHeader(id)
|
|
349
|
+
return stream.fd
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (pathCategory === "data") {
|
|
354
|
+
if (FS.analyzePath(filename).exists) {
|
|
355
|
+
var stream = FS.open(filename, "r")
|
|
356
|
+
if (stream.fd) return stream.fd
|
|
357
|
+
console.log("JS: File not found: ", filename)
|
|
358
|
+
return 0
|
|
359
|
+
} else {
|
|
360
|
+
const stream = await this.create(id)
|
|
361
|
+
return stream.fd
|
|
362
|
+
}
|
|
363
|
+
} else if (pathCategory === "headers") {
|
|
364
|
+
console.log("Header access not implemented yet.")
|
|
365
|
+
return 0
|
|
366
|
+
} else {
|
|
367
|
+
console.log("JS: Invalid path category: ", pathCategory)
|
|
368
|
+
return 0
|
|
369
|
+
}
|
|
370
|
+
},
|
|
475
371
|
}
|
|
476
372
|
}
|
|
477
373
|
}
|