Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test and improve performance #4

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
language: node_js
node:
- lts/*
services: xvfb
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# random-access-chrome-file

[![Build Status](https://travis-ci.com/random-access-storage/random-access-chrome-file.svg?branch=master)](https://travis-ci.com/random-access-storage/random-access-chrome-file)
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)

A [random-access-storage](https://github.com/random-access-storage/random-access-storage) instance backed by the Chrome file system api

```
Expand Down
6 changes: 5 additions & 1 deletion bench.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ function benchRead () {
console.time('512mb read')
st.read(0, 65536, function onread (err, buf) {
if (err) throw err
if (offset >= 512 * 1024 * 1024) return console.timeEnd('512mb read')
if (offset >= 512 * 1024 * 1024) {
console.timeEnd('512mb read')
console.log('### EXIT')
return
}
st.read(offset += buf.length, 65536, onread)
})
}
Expand Down
57 changes: 57 additions & 0 deletions browser-runner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const puppeteer = require('puppeteer')
const budo = require('budo')
const tapFinished = require('tap-finished')
const { PassThrough, pipeline } = require('stream')

const args = process.argv.slice(2)

budo.cli(args, { live: false, watchGlob: '', stream: false }).on('connect', runTests)

async function runTests (ev) {
const results = new PassThrough()
let browser
let page

try {
browser = await puppeteer.launch()
page = await browser.newPage()
} catch (err) {
console.error(err)
shutdown(1)
}

page.on('error', async err => {
console.error(err)
shutdown(1)
})

page.on('pageerror', async err => {
console.error(err)
shutdown(1)
})

page.on('console', msg => {
msg = msg.text()
if (msg.includes('### EXIT')) {
shutdown()
} else {
results.push(`${msg}\n`)
}
})

pipeline(results, tapFinished(result => {
shutdown(result.ok ? 0 : 1)
}), () => {})

pipeline(results, process.stdout, () => {})

await page.goto(`http://localhost:${ev.port}`)

async function shutdown (code = 0) {
if (browser) {
await browser.close().catch(() => {})
}

process.exit(code)
}
}
97 changes: 75 additions & 22 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const ras = require('random-access-storage')
const mutexify = require('mutexify')

const TYPE = {type: 'octet/stream'}
const requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem
Expand Down Expand Up @@ -29,19 +30,20 @@ function createFile (name, opts) {

var fs = null
var entry = null
var file = null
var toDestroy = null
var readers = []
var writers = []

return ras({read, write, open, stat, close, destroy})

function read (req) {
const r = readers.pop() || new ReadRequest(readers, entry, mutex)
const r = readers.pop() || new ReadRequest(readers, entry, file, mutex)
r.run(req)
}

function write (req) {
const w = writers.pop() || new WriteRequest(writers, entry, mutex)
const w = writers.pop() || new WriteRequest(writers, entry, file, mutex)
w.run(req)
}

Expand All @@ -51,9 +53,10 @@ function createFile (name, opts) {
}

function stat (req) {
entry.file(file => {
file.get((err, file) => {
if (err) return req.callback(err)
req.callback(null, file)
}, err => req.callback(err))
})
}

function destroy (req) {
Expand All @@ -78,7 +81,11 @@ function createFile (name, opts) {
mkdirp(parentFolder(name), function () {
fs.root.getFile(name, {create: true}, function (e) {
entry = toDestroy = e
req.callback(null)
file = new EntryFile(entry)
file.get((err) => {
if (err) return onerror(err)
req.callback(null)
})
}, onerror)
})
}, onerror)
Expand Down Expand Up @@ -107,9 +114,10 @@ function parentFolder (path) {
return /^\w:$/.test(p) ? '' : p
}

function WriteRequest (pool, entry, mutex) {
function WriteRequest (pool, entry, file, mutex) {
this.pool = pool
this.entry = entry
this.file = file
this.mutex = mutex
this.writer = null
this.req = null
Expand All @@ -122,7 +130,8 @@ WriteRequest.prototype.makeWriter = function () {
this.entry.createWriter(function (writer) {
self.writer = writer

writer.onwriteend = function () {
writer.onwriteend = function (e) {
self.file.updateSize(e.currentTarget.length)
self.onwrite(null)
}

Expand Down Expand Up @@ -164,21 +173,21 @@ WriteRequest.prototype.lock = function () {
}

WriteRequest.prototype.run = function (req) {
this.entry.file(file => {
this.req = req
if (!this.writer || this.writer.length !== file.size) return this.makeWriter()
var file = this.file

const end = req.offset + req.size
if (end > file.size && !this.lock()) return
this.req = req
if (!this.writer || this.writer.length !== file.size) return this.makeWriter()

if (req.offset > this.writer.length) {
if (req.offset > file.size) return this.truncate()
return this.makeWriter()
}
const end = req.offset + req.size
if (end > file.size && !this.lock()) return

if (req.offset > this.writer.length) {
if (req.offset > file.size) return this.truncate()
return this.makeWriter()
}

this.writer.seek(req.offset)
this.writer.write(new Blob([req.data], TYPE))
}, err => req.callback(err))
this.writer.seek(req.offset)
this.writer.write(new Blob([req.data], TYPE))
}

function Mutex () {
Expand All @@ -202,9 +211,10 @@ Mutex.prototype.lock = function (req) {
return true
}

function ReadRequest (pool, entry, mutex) {
function ReadRequest (pool, entry, file, mutex) {
this.pool = pool
this.entry = entry
this.file = file
this.mutex = mutex
this.reader = new FileReader()
this.req = null
Expand Down Expand Up @@ -251,10 +261,53 @@ ReadRequest.prototype.onread = function (err, buf) {
}

ReadRequest.prototype.run = function (req) {
this.entry.file(file => {
this.file.get((err, file) => {
if (err) return req.callback(err)

const end = req.offset + req.size
this.req = req
if (end > file.size) return this.onread(new Error('Could not satisfy length'), null)
this.reader.readAsArrayBuffer(file.slice(req.offset, end))
}, err => req.callback(err))
})
}

class EntryFile {
constructor (entry) {
this._entry = entry
this._lock = mutexify()
this._file = null
this._size = 0
}

get locked () {
return this._lock.locked
}

get size () {
return this._size
}

updateSize (size) {
this._size = size
this._file = null
}

get (cb) {
if (this._file) {
cb(null, this._file)
return
}

this._lock(release => {
if (this._file) {
return release(cb, null, this._file)
}

this._entry.file(file => {
this._file = file
this._size = file.size
release(cb, null, file)
}, err => release(cb, err))
})
}
}
13 changes: 11 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,22 @@
"description": "random-access-storage instance backed by the Chrome file system api.",
"main": "index.js",
"dependencies": {
"mutexify": "^1.3.0",
"random-access-storage": "^1.3.0"
},
"devDependencies": {
"standard": "^11.0.1"
"budo": "^11.6.3",
"puppeteer": "^3.0.2",
"random-access-test": "github:random-access-storage/random-access-test",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i didn't realise we had this! should we publish that to npm?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed the same. We should, I think is really helpful to test these modules.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

published

"standard": "^11.0.1",
"tap-finished": "0.0.1",
"tape": "^5.0.0"
},
"scripts": {
"test": "standard"
"test": "node browser-runner.js test.js",
"posttest": "npm run lint",
"lint": "standard",
"bench": "node browser-runner.js bench.js"
},
"repository": {
"type": "git",
Expand Down
10 changes: 10 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const test = require('random-access-test')
const racf = require('./')

const createStorage = (root) => (file, opts) => racf(`${root}/${file}`, opts)

const storage = createStorage('tests-' + Math.random())

test(function (name, options, callback) {
callback(storage(name, options))
}, {})