-
Notifications
You must be signed in to change notification settings - Fork 0
/
medea-compressed.js
120 lines (95 loc) · 3 KB
/
medea-compressed.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
var after = require('after')
, zlib = require('zlib')
, MedeaCompressed = function (db) {
if (!(this instanceof MedeaCompressed))
return new MedeaCompressed(db)
this.db = db
}
// borrowed from https://github.com/mafintosh/gunzip-maybe
, isGzipped = function (data) {
if (data.length < 10) return false // gzip header is 10 bytes
if (data[0] !== 0x1f && data[1] !== 0x8b) return false // gzip magic bytes
if (data[2] !== 8) return false // is deflating
return true
}
, maybeGunzip = function (data, callback) {
if (isGzipped(data))
zlib.gunzip(data, callback)
else
callback(null, data)
}
, maybeGzip = function (data, callback) {
zlib.gzip(data, function (err, zipped) {
if (err) return callback(err)
callback(null, zipped.length < data.length ? zipped : data)
})
}
MedeaCompressed.prototype.get = function (key, snapshot, callback) {
if (!callback) {
callback = snapshot
snapshot = null
}
this.db.get(key, snapshot, function (err, data) {
if (err) return callback(err)
if (!data) return callback()
maybeGunzip(data, callback)
})
}
MedeaCompressed.prototype.put = function (key, value, callback) {
var self = this
maybeGzip(value, function (err, zipped) {
if (err) return callback(err)
self.db.put(key, zipped, callback)
})
}
MedeaCompressed.prototype.createBatch = function () {
var operations = []
return {
put: function (key, value) {
operations.push({ key: key, value: value, type: 'put'})
},
remove: function (key) {
operations.push({ key: key, type: 'remove' })
},
operations: operations
}
}
MedeaCompressed.prototype.write = function (batch, options, callback) {
if (!callback) {
callback = options
options = {}
}
var self = this
, compressedOperations = new Array(batch.operations.length)
, done = after(batch.operations.length, function (err) {
if (err) return callback(err)
var medeaBatch = self.db.createBatch()
compressedOperations.forEach(function (operation) {
if (operation.type === 'put') {
medeaBatch.put(operation.key, operation.value)
} else {
medeaBatch.remove(operation.key)
}
})
self.db.write(medeaBatch, options, callback)
})
batch.operations.forEach(function (operation, index) {
if (operation.type === 'remove') {
compressedOperations[index] = { type: 'remove', key: operation.key }
done()
} else {
maybeGzip(operation.value, function (err, zipped) {
if (err)
return done(err)
compressedOperations[index] = { type: 'put', key: operation.key, value: zipped }
done()
})
}
})
}
;[ 'remove', 'createSnapshot', 'compact', 'open', 'close' ].forEach(function (methodName) {
MedeaCompressed.prototype[methodName] = function () {
return this.db[methodName].apply(this.db, arguments)
}
})
module.exports = MedeaCompressed