Выполняя некоторый аудит базы данных, я обнаружил, что содержимое некоторых вложений не соответствует хешам, указанным в документе _attachments
карта.
Я проверил это, загрузив документ и вычислив его хэш. Сравнение с couchdb показало, что они не совпадают. Затем я заметил, что несовпадающие вложения были настроены для сжатия couchdb. Похоже, что мой идентификатор дивана настроен на использование мгновенного сжатия:
foobox# grep -E 'file_compression|compressible_types' /etc/couchdb/{default,local}.ini
/etc/couchdb/default.ini:file_compression = snappy
/etc/couchdb/default.ini:compressible_types = text/*, application/javascript, application/json, application/xml
Однако, когда я пытаюсь сжать содержимое вложения, используя резкий, и вычислить хэш сжатых данных, он по-прежнему не соответствует хешу couchdb. В моем примере ниже document-25977
несжатый (введите application / pdf), а несжатый хэш соответствует предоставленному couchdb. 2-й, document-78608
, является сжимаемым типом (текст / простой), и хеши не совпадают:
foobox$ python hashcompare.py
document-25977
couch len: 142918
couch hash: 028540dd92e1982bcb65c29d32e9617e (md5)
local uncompressed len: 142918
local uncompressed hash: 028540dd92e1982bcb65c29d32e9617e
local compressed len: 132333
local compressed hash: 3157583223dc1a53e1a3386d6abc312d
document-78608
couch len: 2180
couch hash: e613ab6d7f884b835142979489170499 (md5)
local uncompressed len: 2180
local uncompressed hash: 0ab2516c820f5d7afb208e3be7b924dd
local compressed len: 1382
local compressed hash: d9e79232662f57e6af262fc9f867eaf2
Это сценарий, который я использовал для сравнения:
import couchdb
import snappy
import md5
import base64
server = couchdb.Server('http://localhost:9999')
db = server['program1']
for doc_id in ['document-25977', 'document-78608']:
print doc_id
doc = db[doc_id]
att_stub = doc['_attachments'][doc_id]
hash_type, tmpdigest = att_stub['digest'].split('-', 1)
att = db.get_attachment(doc, doc_id)
data = att.read()
# CouchDB is using snappy compression
compressed_data = snappy.compress(data)
print 'couch len: ', att_stub['length']
print 'couch hash: ', base64.b64decode(tmpdigest).encode('hex'), '(%s)' % hash_type
print 'local uncompressed len: ', len(data)
print 'local uncompressed hash: ', md5.md5(data).digest().encode('hex')
print 'local compressed len: ', len(compressed_data)
print 'local compressed hash: ', md5.md5(compressed_data).digest().encode('hex')
print
Я убедился, что документы не повреждены при получении. Так что мне не хватает? Я недостаточно разбираюсь в Erlang, чтобы читать исходники couchdb и понимать, что происходит. Почему в документах должен быть дайджест, который не соответствует его содержимому в сжатом виде или иным образом?
Не уверен, что вы разобрались с этим, но я пошел по тому же пути. Посмотрев немного на источник, выяснилось, что расчеты дайджеста происходят до сжатия, поэтому я не верю, что сжатие будет иметь отношение к значению дайджеста.
Мне удалось воспроизвести дайджест md5, созданный CouchDB для вложений, используя следующее в узле:
var crypto = require('crypto');
var attachmentData = "base64-encoded-data"
var buf = new Buffer(attachmentData, 'base64')
, md5 = crypto.createHash('md5').update(buf).digest('base64');
Надеюсь, это поможет вам или кому-то, кто ищет подробности в будущем.
CouchDB действительно вычисляет хеш после сжатия для сжимаемых файлов.
Но вложения сжимаются с помощью zlib, и мне не удалось сопоставить то, что они делают, поэтому единственное решение, кажется, получить их дайджест после загрузки и сохранить его где-нибудь.