Ao fazer algumas auditorias de um banco de dados, descobri que alguns conteúdos de anexos não correspondiam aos hashes dados no _attachments
map do documento.
Eu testei isso baixando o documento e calculando seu hash. Comparando isso com couchdb mostrou que eles não combinavam. Então notei que os anexos incompatíveis eram aqueles que o couchdb estava configurado para compactar. Parece que meu id de sofá foi configurado para usar compactação instantânea:
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
No entanto, quando tento compactar o conteúdo do anexo usando instantâneo e calculo o hash dos dados compactados, ainda não corresponde ao hash do couchdb. No meu exemplo abaixo, document-25977
está descompactado (digite application / pdf), e o hash descompactado corresponde ao fornecido pelo couchdb. O segundo, document-78608
, é um tipo compressível (text / plain), e os hashes não correspondem:
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
Este é o script que usei para fazer a comparação:
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
Eu verifiquei que os documentos não estão corrompidos quando buscados. Então, o que estou perdendo? Eu não sou versado o suficiente em Erlang para ler a fonte couchdb e descobrir o que está acontecendo. Por que os documentos têm um resumo que não corresponde ao seu conteúdo compactado ou de outra forma?