Fix duplicate payload logic

rhizome_finish_write() was treating a duplicate file hash as an error,
instead of dealing with it sensibly
This commit is contained in:
Andrew Bettison 2013-09-30 16:32:08 +09:30
parent 01216f06c2
commit 162108dd18
3 changed files with 26 additions and 15 deletions

View File

@ -262,6 +262,7 @@ rhizome_manifest *_rhizome_new_manifest(struct __sourceloc __whence);
#define rhizome_new_manifest() _rhizome_new_manifest(__WHENCE__)
int rhizome_manifest_pack_variables(rhizome_manifest *m);
int rhizome_store_bundle(rhizome_manifest *m);
int rhizome_remove_file_datainvalid(sqlite_retry_state *retry, const char *fileid);
int rhizome_manifest_add_group(rhizome_manifest *m,char *groupid);
int rhizome_clean_payload(const char *fileidhex);
int rhizome_store_file(rhizome_manifest *m,const unsigned char *key);

View File

@ -718,7 +718,6 @@ int64_t rhizome_database_used_bytes()
int rhizome_database_filehash_from_id(const char *id, uint64_t version, char hash[SHA512_DIGEST_STRING_LENGTH])
{
IN();
strbuf hash_sb = strbuf_local(hash, SHA512_DIGEST_STRING_LENGTH);
RETURN(sqlite_exec_strbuf(hash_sb, "SELECT filehash FROM MANIFESTS WHERE manifests.version=%lld AND manifests.id='%s';",
version,id));
@ -739,6 +738,16 @@ static int rhizome_delete_orphan_fileblobs_retry(sqlite_retry_state *retry)
return sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, retry, "DELETE FROM FILEBLOBS WHERE NOT EXISTS( SELECT 1 FROM FILES WHERE FILES.id = FILEBLOBS.id );");
}
int rhizome_remove_file_datainvalid(sqlite_retry_state *retry, const char *fileid)
{
int ret = 0;
if (sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, retry, "DELETE FROM FILES WHERE id='%s' and datavalid=0;", fileid) == -1)
ret = -1;
if (sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, retry, "DELETE FROM FILEBLOBS WHERE id='%s' AND NOT EXISTS( SELECT 1 FROM FILES WHERE FILES.id=FILEBLOBS.id );", fileid) == -1)
ret = -1;
return ret;
}
int rhizome_cleanup(struct rhizome_cleanup_report *report)
{
IN();

View File

@ -462,23 +462,26 @@ int rhizome_finish_write(struct rhizome_write *write)
char hash_out[SHA512_DIGEST_STRING_LENGTH + 1];
SHA512_End(&write->sha512_context, hash_out);
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
str_toupper_inplace(hash_out);
if (write->id_known){
if (strcasecmp(write->id, hash_out)){
WHYF("Expected hash=%s, got %s", write->id, hash_out);
if (write->id_known) {
if (strcasecmp(write->id, hash_out) != 0) {
WHYF("expected filehash=%s, got %s", write->id, hash_out);
goto failure;
}
} else {
strlcpy(write->id, hash_out, SHA512_DIGEST_STRING_LENGTH);
}
if (rhizome_exists(hash_out)){
// ooops, we've already got that file, delete the new copy.
rhizome_fail_write(write);
}else{
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
rhizome_remove_file_datainvalid(&retry, write->id);
if (rhizome_exists(write->id)) {
// we've already got that payload, delete the new copy
sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry,"DELETE FROM FILEBLOBS WHERE id='%"PRId64"';", write->temp_id);
sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry,"DELETE FROM FILES WHERE id='%"PRId64"';", write->temp_id);
if (config.debug.rhizome)
DEBUGF("File id='%s' already present, removed id='%"PRId64"'", write->id, write->temp_id);
} else {
if (sqlite_exec_void_retry(&retry, "BEGIN TRANSACTION;") == -1)
goto dbfailure;
@ -517,12 +520,10 @@ int rhizome_finish_write(struct rhizome_write *write)
}
if (sqlite_exec_void_retry(&retry, "COMMIT;") == -1)
goto dbfailure;
if (config.debug.rhizome)
DEBUGF("Stored file %s", write->id);
}
write->blob_rowid=-1;
if (config.debug.rhizome)
DEBUGF("Stored file %s", hash_out);
return 0;
dbfailure: