mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
Rename to FileSystemBlobStore
This commit is contained in:
69
spec/file-system-blob-store-spec.coffee
Normal file
69
spec/file-system-blob-store-spec.coffee
Normal file
@@ -0,0 +1,69 @@
|
||||
temp = require 'temp'
|
||||
FileSystemBlobStore = require '../src/file-system-blob-store'
|
||||
|
||||
describe "FileSystemBlobStore", ->
|
||||
[storageDirectory, blobStore] = []
|
||||
|
||||
beforeEach ->
|
||||
storageDirectory = temp.path()
|
||||
blobStore = FileSystemBlobStore.load(storageDirectory)
|
||||
|
||||
it "is empty when the file doesn't exist", ->
|
||||
expect(blobStore.get("foo")).toBeUndefined()
|
||||
expect(blobStore.get("bar")).toBeUndefined()
|
||||
|
||||
it "allows to read and write buffers from/to memory without persisting them", ->
|
||||
blobStore.set("foo", new Buffer("foo"))
|
||||
blobStore.set("bar", new Buffer("bar"))
|
||||
|
||||
expect(blobStore.get("foo")).toEqual(new Buffer("foo"))
|
||||
expect(blobStore.get("bar")).toEqual(new Buffer("bar"))
|
||||
|
||||
it "persists buffers when saved and retrieves them on load, giving priority to in-memory ones", ->
|
||||
blobStore.set("foo", new Buffer("foo"))
|
||||
blobStore.set("bar", new Buffer("bar"))
|
||||
blobStore.save()
|
||||
|
||||
blobStore = FileSystemBlobStore.load(storageDirectory)
|
||||
|
||||
expect(blobStore.get("foo")).toEqual(new Buffer("foo"))
|
||||
expect(blobStore.get("bar")).toEqual(new Buffer("bar"))
|
||||
|
||||
blobStore.set("foo", new Buffer("changed"))
|
||||
|
||||
expect(blobStore.get("foo")).toEqual(new Buffer("changed"))
|
||||
|
||||
it "persists both in-memory and previously stored buffers when saved", ->
|
||||
blobStore.set("foo", new Buffer("foo"))
|
||||
blobStore.set("bar", new Buffer("bar"))
|
||||
blobStore.save()
|
||||
|
||||
blobStore = FileSystemBlobStore.load(storageDirectory)
|
||||
blobStore.set("bar", new Buffer("changed"))
|
||||
blobStore.set("qux", new Buffer("qux"))
|
||||
blobStore.save()
|
||||
|
||||
blobStore = FileSystemBlobStore.load(storageDirectory)
|
||||
|
||||
expect(blobStore.get("foo")).toEqual(new Buffer("foo"))
|
||||
expect(blobStore.get("bar")).toEqual(new Buffer("changed"))
|
||||
expect(blobStore.get("qux")).toEqual(new Buffer("qux"))
|
||||
|
||||
it "allows to delete keys from both memory and stored buffers", ->
|
||||
blobStore.set("a", new Buffer("a"))
|
||||
blobStore.set("b", new Buffer("b"))
|
||||
blobStore.save()
|
||||
|
||||
blobStore = FileSystemBlobStore.load(storageDirectory)
|
||||
|
||||
blobStore.set("b", new Buffer("b"))
|
||||
blobStore.set("c", new Buffer("c"))
|
||||
blobStore.delete("b")
|
||||
blobStore.delete("c")
|
||||
blobStore.save()
|
||||
|
||||
blobStore = FileSystemBlobStore.load(storageDirectory)
|
||||
|
||||
expect(blobStore.get("a")).toEqual(new Buffer("a"))
|
||||
expect(blobStore.get("b")).toBeUndefined()
|
||||
expect(blobStore.get("c")).toBeUndefined()
|
||||
@@ -1,69 +0,0 @@
|
||||
temp = require 'temp'
|
||||
FileSystemCacheBlobStorage = require '../src/file-system-cache-blob-storage'
|
||||
|
||||
describe "FileSystemCacheBlobStorage", ->
|
||||
[storageDirectory, cacheBlobStorage] = []
|
||||
|
||||
beforeEach ->
|
||||
storageDirectory = temp.path()
|
||||
cacheBlobStorage = FileSystemCacheBlobStorage.load(storageDirectory)
|
||||
|
||||
it "is empty when the file doesn't exist", ->
|
||||
expect(cacheBlobStorage.get("foo")).toBeUndefined()
|
||||
expect(cacheBlobStorage.get("bar")).toBeUndefined()
|
||||
|
||||
it "allows to read and write buffers from/to memory without persisting them", ->
|
||||
cacheBlobStorage.set("foo", new Buffer("foo"))
|
||||
cacheBlobStorage.set("bar", new Buffer("bar"))
|
||||
|
||||
expect(cacheBlobStorage.get("foo")).toEqual(new Buffer("foo"))
|
||||
expect(cacheBlobStorage.get("bar")).toEqual(new Buffer("bar"))
|
||||
|
||||
it "persists buffers when saved and retrieves them on load, giving priority to in-memory ones", ->
|
||||
cacheBlobStorage.set("foo", new Buffer("foo"))
|
||||
cacheBlobStorage.set("bar", new Buffer("bar"))
|
||||
cacheBlobStorage.save()
|
||||
|
||||
cacheBlobStorage = FileSystemCacheBlobStorage.load(storageDirectory)
|
||||
|
||||
expect(cacheBlobStorage.get("foo")).toEqual(new Buffer("foo"))
|
||||
expect(cacheBlobStorage.get("bar")).toEqual(new Buffer("bar"))
|
||||
|
||||
cacheBlobStorage.set("foo", new Buffer("changed"))
|
||||
|
||||
expect(cacheBlobStorage.get("foo")).toEqual(new Buffer("changed"))
|
||||
|
||||
it "persists both in-memory and previously stored buffers when saved", ->
|
||||
cacheBlobStorage.set("foo", new Buffer("foo"))
|
||||
cacheBlobStorage.set("bar", new Buffer("bar"))
|
||||
cacheBlobStorage.save()
|
||||
|
||||
cacheBlobStorage = FileSystemCacheBlobStorage.load(storageDirectory)
|
||||
cacheBlobStorage.set("bar", new Buffer("changed"))
|
||||
cacheBlobStorage.set("qux", new Buffer("qux"))
|
||||
cacheBlobStorage.save()
|
||||
|
||||
cacheBlobStorage = FileSystemCacheBlobStorage.load(storageDirectory)
|
||||
|
||||
expect(cacheBlobStorage.get("foo")).toEqual(new Buffer("foo"))
|
||||
expect(cacheBlobStorage.get("bar")).toEqual(new Buffer("changed"))
|
||||
expect(cacheBlobStorage.get("qux")).toEqual(new Buffer("qux"))
|
||||
|
||||
it "allows to delete keys from both memory and stored buffers", ->
|
||||
cacheBlobStorage.set("a", new Buffer("a"))
|
||||
cacheBlobStorage.set("b", new Buffer("b"))
|
||||
cacheBlobStorage.save()
|
||||
|
||||
cacheBlobStorage = FileSystemCacheBlobStorage.load(storageDirectory)
|
||||
|
||||
cacheBlobStorage.set("b", new Buffer("b"))
|
||||
cacheBlobStorage.set("c", new Buffer("c"))
|
||||
cacheBlobStorage.delete("b")
|
||||
cacheBlobStorage.delete("c")
|
||||
cacheBlobStorage.save()
|
||||
|
||||
cacheBlobStorage = FileSystemCacheBlobStorage.load(storageDirectory)
|
||||
|
||||
expect(cacheBlobStorage.get("a")).toEqual(new Buffer("a"))
|
||||
expect(cacheBlobStorage.get("b")).toBeUndefined()
|
||||
expect(cacheBlobStorage.get("c")).toBeUndefined()
|
||||
@@ -1,16 +1,16 @@
|
||||
describe "NativeCompileCache", ->
|
||||
nativeCompileCache = require '../src/native-compile-cache'
|
||||
[fakeCacheStorage, cachedFiles] = []
|
||||
[fakeCacheStore, cachedFiles] = []
|
||||
|
||||
beforeEach ->
|
||||
cachedFiles = []
|
||||
fakeCacheStorage = jasmine.createSpyObj("cache storage", ["set", "get", "has", "delete"])
|
||||
nativeCompileCache.setCacheStorage(fakeCacheStorage)
|
||||
fakeCacheStore = jasmine.createSpyObj("cache store", ["set", "get", "has", "delete"])
|
||||
nativeCompileCache.setCacheStore(fakeCacheStore)
|
||||
nativeCompileCache.install()
|
||||
|
||||
it "writes and reads from the cache storage when requiring files", ->
|
||||
fakeCacheStorage.has.andReturn(false)
|
||||
fakeCacheStorage.set.andCallFake (filename, cacheBuffer) ->
|
||||
fakeCacheStore.has.andReturn(false)
|
||||
fakeCacheStore.set.andCallFake (filename, cacheBuffer) ->
|
||||
cachedFiles.push({filename, cacheBuffer})
|
||||
|
||||
fn1 = require('./fixtures/native-cache/file-1')
|
||||
@@ -28,20 +28,20 @@ describe "NativeCompileCache", ->
|
||||
expect(cachedFiles[1].cacheBuffer.length).toBeGreaterThan(0)
|
||||
expect(fn2()).toBe(2)
|
||||
|
||||
fakeCacheStorage.has.andReturn(true)
|
||||
fakeCacheStorage.get.andReturn(cachedFiles[0].cacheBuffer)
|
||||
fakeCacheStorage.set.reset()
|
||||
fakeCacheStore.has.andReturn(true)
|
||||
fakeCacheStore.get.andReturn(cachedFiles[0].cacheBuffer)
|
||||
fakeCacheStore.set.reset()
|
||||
|
||||
fn1 = require('./fixtures/native-cache/file-1')
|
||||
|
||||
expect(fakeCacheStorage.set).not.toHaveBeenCalled()
|
||||
expect(fakeCacheStore.set).not.toHaveBeenCalled()
|
||||
expect(fn1()).toBe(1)
|
||||
|
||||
it "deletes previously cached code when the cache is not valid", ->
|
||||
fakeCacheStorage.has.andReturn(true)
|
||||
fakeCacheStorage.get.andCallFake -> new Buffer("an invalid cache")
|
||||
fakeCacheStore.has.andReturn(true)
|
||||
fakeCacheStore.get.andCallFake -> new Buffer("an invalid cache")
|
||||
|
||||
fn3 = require('./fixtures/native-cache/file-3')
|
||||
|
||||
expect(fakeCacheStorage.delete).toHaveBeenCalledWith(require.resolve('./fixtures/native-cache/file-3'))
|
||||
expect(fakeCacheStore.delete).toHaveBeenCalledWith(require.resolve('./fixtures/native-cache/file-3'))
|
||||
expect(fn3()).toBe(3)
|
||||
|
||||
94
src/file-system-blob-store.js
Normal file
94
src/file-system-blob-store.js
Normal file
@@ -0,0 +1,94 @@
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs-plus')
|
||||
const path = require('path')
|
||||
|
||||
module.exports =
|
||||
class FileSystemBlobStore {
|
||||
static load (directory) {
|
||||
let instance = new FileSystemBlobStore(directory)
|
||||
instance.load()
|
||||
return instance
|
||||
}
|
||||
|
||||
constructor (directory) {
|
||||
this.inMemoryBlobs = new Map()
|
||||
this.blobFilename = path.join(directory, 'BLOB')
|
||||
this.mapFilename = path.join(directory, 'MAP')
|
||||
this.storedBlob = new Buffer(0)
|
||||
this.storedMap = {}
|
||||
}
|
||||
|
||||
load () {
|
||||
if (!fs.existsSync(this.mapFilename)) {
|
||||
return
|
||||
}
|
||||
if (!fs.existsSync(this.blobFilename)) {
|
||||
return
|
||||
}
|
||||
this.storedBlob = fs.readFileSync(this.blobFilename)
|
||||
this.storedMap = JSON.parse(fs.readFileSync(this.mapFilename))
|
||||
}
|
||||
|
||||
save () {
|
||||
let dump = this.getDump()
|
||||
let cacheBlob = Buffer.concat(dump[0])
|
||||
let cacheMap = JSON.stringify(dump[1])
|
||||
fs.writeFileSync(this.blobFilename, cacheBlob)
|
||||
fs.writeFileSync(this.mapFilename, cacheMap)
|
||||
}
|
||||
|
||||
has (key) {
|
||||
return this.inMemoryBlobs.hasOwnProperty(key) || this.storedMap.hasOwnProperty(key)
|
||||
}
|
||||
|
||||
get (key) {
|
||||
return this.getFromMemory(key) || this.getFromStorage(key)
|
||||
}
|
||||
|
||||
set (key, buffer) {
|
||||
return this.inMemoryBlobs.set(key, buffer)
|
||||
}
|
||||
|
||||
delete (key) {
|
||||
this.inMemoryBlobs.delete(key)
|
||||
delete this.storedMap[key]
|
||||
}
|
||||
|
||||
getFromMemory (key) {
|
||||
return this.inMemoryBlobs.get(key)
|
||||
}
|
||||
|
||||
getFromStorage (key) {
|
||||
if (this.storedMap[key] == null) {
|
||||
return
|
||||
}
|
||||
|
||||
return this.storedBlob.slice.apply(this.storedBlob, this.storedMap[key])
|
||||
}
|
||||
|
||||
getDump () {
|
||||
let buffers = []
|
||||
let cacheMap = {}
|
||||
let currentBufferStart = 0
|
||||
|
||||
function dump (key, getBufferByKey) {
|
||||
let buffer = getBufferByKey(key)
|
||||
buffers.push(buffer)
|
||||
cacheMap[key] = [currentBufferStart, currentBufferStart + buffer.length]
|
||||
currentBufferStart += buffer.length
|
||||
}
|
||||
|
||||
for (let key of this.inMemoryBlobs.keys()) {
|
||||
dump(key, this.getFromMemory.bind(this))
|
||||
}
|
||||
|
||||
for (let key of Object.keys(this.storedMap)) {
|
||||
if (!cacheMap[key]) {
|
||||
dump(key, this.getFromStorage.bind(this))
|
||||
}
|
||||
}
|
||||
|
||||
return [buffers, cacheMap]
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const fs = require('fs-plus')
|
||||
const path = require('path')
|
||||
|
||||
module.exports =
|
||||
class FileSystemCacheBlobStorage {
|
||||
static load (directory) {
|
||||
let instance = new FileSystemCacheBlobStorage(directory)
|
||||
instance.load()
|
||||
return instance
|
||||
}
|
||||
|
||||
constructor (directory) {
|
||||
this.inMemoryCache = new Map()
|
||||
this.cacheBlobFilename = path.join(directory, 'v8-compile-cache.blob')
|
||||
this.cacheMapFilename = path.join(directory, 'v8-compile-cache.map')
|
||||
this.storedCacheBlob = new Buffer(0)
|
||||
this.storedCacheMap = {}
|
||||
}
|
||||
|
||||
load () {
|
||||
if (!fs.existsSync(this.cacheMapFilename)) {
|
||||
return
|
||||
}
|
||||
if (!fs.existsSync(this.cacheBlobFilename)) {
|
||||
return
|
||||
}
|
||||
this.storedCacheBlob = fs.readFileSync(this.cacheBlobFilename)
|
||||
this.storedCacheMap = JSON.parse(fs.readFileSync(this.cacheMapFilename))
|
||||
}
|
||||
|
||||
save () {
|
||||
let dump = this.getDump()
|
||||
let cacheBlob = Buffer.concat(dump[0])
|
||||
let cacheMap = JSON.stringify(dump[1])
|
||||
fs.writeFileSync(this.cacheBlobFilename, cacheBlob)
|
||||
fs.writeFileSync(this.cacheMapFilename, cacheMap)
|
||||
}
|
||||
|
||||
has (key) {
|
||||
return this.inMemoryCache.hasOwnProperty(key) || this.storedCacheMap.hasOwnProperty(key)
|
||||
}
|
||||
|
||||
get (key) {
|
||||
return this.getFromMemory(key) || this.getFromStorage(key)
|
||||
}
|
||||
|
||||
set (key, buffer) {
|
||||
return this.inMemoryCache.set(key, buffer)
|
||||
}
|
||||
|
||||
delete (key) {
|
||||
this.inMemoryCache.delete(key)
|
||||
delete this.storedCacheMap[key]
|
||||
}
|
||||
|
||||
getFromMemory (key) {
|
||||
return this.inMemoryCache.get(key)
|
||||
}
|
||||
|
||||
getFromStorage (key) {
|
||||
if (this.storedCacheMap[key] == null) {
|
||||
return
|
||||
}
|
||||
|
||||
return this.storedCacheBlob.slice.apply(this.storedCacheBlob, this.storedCacheMap[key])
|
||||
}
|
||||
|
||||
getDump () {
|
||||
let buffers = []
|
||||
let cacheMap = {}
|
||||
let currentBufferStart = 0
|
||||
|
||||
function dump (key, getBufferByKey) {
|
||||
let buffer = getBufferByKey(key)
|
||||
buffers.push(buffer)
|
||||
cacheMap[key] = [currentBufferStart, currentBufferStart + buffer.length]
|
||||
currentBufferStart += buffer.length
|
||||
}
|
||||
|
||||
for (let key of this.inMemoryCache.keys()) {
|
||||
dump(key, this.getFromMemory.bind(this))
|
||||
}
|
||||
|
||||
for (let key of Object.keys(this.storedCacheMap)) {
|
||||
if (!cacheMap[key]) {
|
||||
dump(key, this.getFromStorage.bind(this))
|
||||
}
|
||||
}
|
||||
|
||||
return [buffers, cacheMap]
|
||||
}
|
||||
}
|
||||
@@ -6,12 +6,12 @@ const cachedVm = require('cached-run-in-this-context')
|
||||
|
||||
class NativeCompileCache {
|
||||
constructor () {
|
||||
this.cacheStorage = null
|
||||
this.cacheStore = null
|
||||
this.previousModuleCompile = null
|
||||
}
|
||||
|
||||
setCacheStorage (storage) {
|
||||
this.cacheStorage = storage
|
||||
setCacheStore (store) {
|
||||
this.cacheStore = store
|
||||
}
|
||||
|
||||
install () {
|
||||
@@ -28,7 +28,7 @@ class NativeCompileCache {
|
||||
}
|
||||
|
||||
overrideModuleCompile () {
|
||||
let cacheStorage = this.cacheStorage
|
||||
let cacheStore = this.cacheStore
|
||||
let resolvedArgv = null
|
||||
Module.prototype._compile = function (content, filename) {
|
||||
let self = this
|
||||
@@ -52,17 +52,17 @@ class NativeCompileCache {
|
||||
let wrapper = Module.wrap(content)
|
||||
|
||||
let compiledWrapper = null
|
||||
if (cacheStorage.has(filename)) {
|
||||
let buffer = cacheStorage.get(filename)
|
||||
if (cacheStore.has(filename)) {
|
||||
let buffer = cacheStore.get(filename)
|
||||
let compilationResult = cachedVm.runInThisContextCached(wrapper, filename, buffer)
|
||||
compiledWrapper = compilationResult.result
|
||||
if (compilationResult.wasRejected) {
|
||||
cacheStorage.delete(filename)
|
||||
cacheStore.delete(filename)
|
||||
}
|
||||
} else {
|
||||
let compilationResult = cachedVm.runInThisContext(wrapper, filename)
|
||||
if (compilationResult.cacheBuffer) {
|
||||
cacheStorage.set(filename, compilationResult.cacheBuffer)
|
||||
cacheStore.set(filename, compilationResult.cacheBuffer)
|
||||
}
|
||||
compiledWrapper = compilationResult.result
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
var app = require('remote').require('app')
|
||||
var fs = require('fs-plus')
|
||||
var path = require('path')
|
||||
var FileSystemCacheBlobStorage = require('../src/file-system-cache-blob-storage')
|
||||
var FileSystemBlobStore = require('../src/file-system-blob-store')
|
||||
var NativeCompileCache = require('../src/native-compile-cache')
|
||||
|
||||
var loadSettings = null
|
||||
@@ -26,10 +26,10 @@
|
||||
// Ensure ATOM_HOME is always set before anything else is required
|
||||
setupAtomHome()
|
||||
|
||||
cacheStorage = FileSystemCacheBlobStorage.load(
|
||||
path.join(process.env.ATOM_HOME, 'native-compile-cache/')
|
||||
blobStore = FileSystemBlobStore.load(
|
||||
path.join(process.env.ATOM_HOME, 'blob-store/')
|
||||
)
|
||||
NativeCompileCache.setCacheStorage(cacheStorage)
|
||||
NativeCompileCache.setCacheStore(blobStore)
|
||||
NativeCompileCache.install()
|
||||
|
||||
// Normalize to make sure drive letter case is consistent on Windows
|
||||
|
||||
Reference in New Issue
Block a user