##// END OF EJS Templates
util: compression APIs to support revlog decompression...
Gregory Szorc -
r30798:f50c0db5 default
parent child Browse files
Show More
@@ -3000,6 +3000,8 b' class compressormanager(object):'
3000 3000 self._bundlenames = {}
3001 3001 # Internal bundle identifier to engine name.
3002 3002 self._bundletypes = {}
3003 # Revlog header to engine name.
3004 self._revlogheaders = {}
3003 3005 # Wire proto identifier to engine name.
3004 3006 self._wiretypes = {}
3005 3007
@@ -3053,6 +3055,14 b' class compressormanager(object):'
3053 3055
3054 3056 self._wiretypes[wiretype] = name
3055 3057
3058 revlogheader = engine.revlogheader()
3059 if revlogheader and revlogheader in self._revlogheaders:
3060 raise error.Abort(_('revlog header %s already registered by %s') %
3061 (revlogheader, self._revlogheaders[revlogheader]))
3062
3063 if revlogheader:
3064 self._revlogheaders[revlogheader] = name
3065
3056 3066 self._engines[name] = engine
3057 3067
3058 3068 @property
@@ -3121,6 +3131,13 b' class compressormanager(object):'
3121 3131 engine.name())
3122 3132 return engine
3123 3133
3134 def forrevlogheader(self, header):
3135 """Obtain a compression engine registered to a revlog header.
3136
3137 Will raise KeyError if the revlog header value isn't registered.
3138 """
3139 return self._engines[self._revlogheaders[header]]
3140
3124 3141 compengines = compressormanager()
3125 3142
3126 3143 class compressionengine(object):
@@ -3186,6 +3203,16 b' class compressionengine(object):'
3186 3203 """
3187 3204 return None
3188 3205
3206 def revlogheader(self):
3207 """Header added to revlog chunks that identifies this engine.
3208
3209 If this engine can be used to compress revlogs, this method should
3210 return the bytes used to identify chunks compressed with this engine.
3211 Else, the method should return ``None`` to indicate it does not
3212 participate in revlog compression.
3213 """
3214 return None
3215
3189 3216 def compressstream(self, it, opts=None):
3190 3217 """Compress an iterator of chunks.
3191 3218
@@ -3215,6 +3242,13 b' class compressionengine(object):'
3215 3242 the data could not be compressed (too small, not compressible, etc).
3216 3243 The returned data should have a header uniquely identifying this
3217 3244 compression format so decompression can be routed to this engine.
3245 This header should be identified by the ``revlogheader()`` return
3246 value.
3247
3248 The object has a ``decompress(data)`` method that decompresses
3249 data. The method will only be called if ``data`` begins with
3250 ``revlogheader()``. The method should return the raw, uncompressed
3251 data or raise a ``RevlogError``.
3218 3252
3219 3253 The object is reusable but is not thread safe.
3220 3254 """
@@ -3230,6 +3264,9 b' class _zlibengine(compressionengine):'
3230 3264 def wireprotosupport(self):
3231 3265 return compewireprotosupport('zlib', 20, 20)
3232 3266
3267 def revlogheader(self):
3268 return 'x'
3269
3233 3270 def compressstream(self, it, opts=None):
3234 3271 opts = opts or {}
3235 3272
@@ -3286,6 +3323,13 b' class _zlibengine(compressionengine):'
3286 3323 return ''.join(parts)
3287 3324 return None
3288 3325
3326 def decompress(self, data):
3327 try:
3328 return zlib.decompress(data)
3329 except zlib.error as e:
3330 raise error.RevlogError(_('revlog decompress error: %s') %
3331 str(e))
3332
3289 3333 def revlogcompressor(self, opts=None):
3290 3334 return self.zlibrevlogcompressor()
3291 3335
@@ -3357,6 +3401,9 b' class _noopengine(compressionengine):'
3357 3401 def wireprotosupport(self):
3358 3402 return compewireprotosupport('none', 0, 10)
3359 3403
3404 # We don't implement revlogheader because it is handled specially
3405 # in the revlog class.
3406
3360 3407 def compressstream(self, it, opts=None):
3361 3408 return it
3362 3409
@@ -3397,6 +3444,9 b' class _zstdengine(compressionengine):'
3397 3444 def wireprotosupport(self):
3398 3445 return compewireprotosupport('zstd', 50, 50)
3399 3446
3447 def revlogheader(self):
3448 return '\x28'
3449
3400 3450 def compressstream(self, it, opts=None):
3401 3451 opts = opts or {}
3402 3452 # zstd level 3 is almost always significantly faster than zlib
@@ -3425,7 +3475,9 b' class _zstdengine(compressionengine):'
3425 3475 # pre-allocate a buffer to hold the result.
3426 3476 self._cctx = zstd.ZstdCompressor(level=level,
3427 3477 write_content_size=True)
3478 self._dctx = zstd.ZstdDecompressor()
3428 3479 self._compinsize = zstd.COMPRESSION_RECOMMENDED_INPUT_SIZE
3480 self._decompinsize = zstd.DECOMPRESSION_RECOMMENDED_INPUT_SIZE
3429 3481
3430 3482 def compress(self, data):
3431 3483 insize = len(data)
@@ -3456,6 +3508,28 b' class _zstdengine(compressionengine):'
3456 3508 return ''.join(chunks)
3457 3509 return None
3458 3510
3511 def decompress(self, data):
3512 insize = len(data)
3513
3514 try:
3515 # This was measured to be faster than other streaming
3516 # decompressors.
3517 dobj = self._dctx.decompressobj()
3518 chunks = []
3519 pos = 0
3520 while pos < insize:
3521 pos2 = pos + self._decompinsize
3522 chunk = dobj.decompress(data[pos:pos2])
3523 if chunk:
3524 chunks.append(chunk)
3525 pos = pos2
3526 # Frame should be exhausted, so no finish() API.
3527
3528 return ''.join(chunks)
3529 except Exception as e:
3530 raise error.RevlogError(_('revlog decompress error: %s') %
3531 str(e))
3532
3459 3533 def revlogcompressor(self, opts=None):
3460 3534 opts = opts or {}
3461 3535 return self.zstdrevlogcompressor(self._module,
General Comments 0
You need to be logged in to leave comments. Login now