Skip to content

Instantly share code, notes, and snippets.

@kocoten1992 kocoten1992/chrome-chunk-store.js Secret
Last active Apr 20, 2017

Embed
What would you like to do?
ChromeChunkStore
function ChromeChunkStore (chunkLength, opts) {
var self = this
if (!(self instanceof ChromeChunkStore)) return new ChromeChunkStore(chunkLength, opts)
if (!opts) opts = {}
if (opts.torrent && opts.torrent.infoHash) {
self.path = opts.torrent.infoHash
}
self.opts = opts
self.chunkLength = Number(chunkLength)
if (!self.chunkLength) throw new Error('First argument must be a chunk length')
self.closed = false
self.length = Number(opts.length) || Infinity
if (self.length !== Infinity) {
self.lastChunkLength = (self.length % self.chunkLength) || self.chunkLength
self.lastChunkIndex = Math.ceil(self.length / self.chunkLength) - 1
}
if (opts.size == null) {
opts.size = 10 * 1024 * 1024 * 1024 // 10GB
}
if (opts.type == null) {
opts.type = 0 // temporary
}
navigator.webkitTemporaryStorage.requestQuota(opts.size, () => {
webkitRequestFileSystem(opts.type, opts.size, fs => {
self.fs = fs
_setUp()
})
})
function _setUp () {
self.fileReader = new FileReader
self.fs.root.getFile(self.opts.torrent.infoHash, {create: false}, fileEntry => {
self.fileEntry = fileEntry
self.fileEntry.file(file => self.file = file, err => console.log(err))
self.fileEntry.createWriter(fileWriter => self.fileWriter = fileWriter)
}, err => console.log(err))
self.writeQueues = [] // limitation of FileWriter, single operation at a time
self.readQueues = [] // limitation of FileReader
}
}
ChromeChunkStore.prototype.put = function (index, buf, cb) {
//console.log('call put')
if (this.closed) return nextTick(cb, new Error('Storage is closed'))
if (!this.fileWriter || !this.writeQueues || !this.file) {
setTimeout(() => {
nextTick(this.put(index, buf, cb))
}, 0)
return
//return nextTick(this.put(index, buf, cb)) // this work too fast, have to settle with setTimeout 0
}
var isLastChunk = (index === this.lastChunkIndex)
if (isLastChunk && buf.length !== this.lastChunkLength) {
return nextTick(cb, new Error('Last chunk length must be ' + this.lastChunkLength))
}
if (!isLastChunk && buf.length !== this.chunkLength) {
return nextTick(cb, new Error('Chunk length must be ' + this.chunkLength))
}
this.writeQueues.push({index: index, buf: buf, cb: cb})
this._put()
}
ChromeChunkStore.prototype._put = function () {
//console.log('call _put')
if (this.writeQueues.length == 0 || this.fileWriter.readyState == 1) {
return
}
var chunkInfo = this.writeQueues.shift()
this.fileWriter.onwriteend = () => {
chunkInfo.cb()
this._put()
}
this.fileWriter.seek(chunkInfo.index * this.chunkLength)
this.fileWriter.write(new Blob([chunkInfo.buf]))
}
ChromeChunkStore.prototype.get = function (index, opts, cb) {
//console.log('call get')
if (typeof opts === 'function') return this.get(index, null, opts)
if (this.closed) return nextTick(cb, new Error('Storage is closed'))
if (!this.fileReader || !this.readQueues || !this.file) {
setTimeout(() => {
this.get(index, opts, cb)
}, 0)
return
//return nextTick(this.get(index, opts, cb))
}
if (opts == null) {
opts = {}
}
if (!opts.offset) {
opts.offset = 0
}
if (!opts.length) {
opts.length = 0
}
this.readQueues.push({index: index, opts: opts, cb: cb})
this._get()
}
ChromeChunkStore.prototype._get = function () {
//console.log('call _get')
if (this.readQueues.length == 0 || this.fileReader.readyState == 1) {
return
}
var chunkInfo = this.readQueues.shift()
this.fileReader.onload = progressEvent => {
if (!this.fileReader.result.byteLength) return nextTick(chunkInfo.cb, new Error('Chunk not found'))
nextTick(chunkInfo.cb, null, this.fileReader.result)
this._get()
}
var length = chunkInfo.opts.length ? chunkInfo.opts.length + this.chunkLength * chunkInfo.index : this.chunkLength * (chunkInfo.index + 1)
this.fileReader.readAsArrayBuffer(this.file.slice(
chunkInfo.index * this.chunkLength + chunkInfo.opts.offset,
length
))
}
ChromeChunkStore.prototype.close = ChromeChunkStore.prototype.destroy = function (cb) {
if (this.closed) return nextTick(cb, new Err('Storage is closed'))
this.fileWriter.onwriteend = () => {
cb()
}
this.fileWriter.truncate(()=>{})
this.closed = true
}
function nextTick(cb, err, val) {
process.nextTick(function () {
if (cb) cb(err, val)
})
}
module.exports = ChromeChunkStore
@kocoten1992

This comment has been minimized.

Copy link
Owner Author

kocoten1992 commented Apr 20, 2017

update navigator.webkitTemporaryStorage.requestQuota, silly me -_

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.