svn_error_t * svn_fs_fs__set_rep_reference(svn_fs_t *fs, representation_t *rep, apr_pool_t *pool) { fs_fs_data_t *ffd = fs->fsap_data; svn_sqlite__stmt_t *stmt; svn_error_t *err; svn_checksum_t checksum; checksum.kind = svn_checksum_sha1; checksum.digest = rep->sha1_digest; SVN_ERR_ASSERT(ffd->rep_sharing_allowed); if (! ffd->rep_cache_db) SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool)); /* We only allow SHA1 checksums in this table. */ if (! rep->has_sha1) return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, _("Only SHA1 checksums can be used as keys in the " "rep_cache table.\n")); SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db, STMT_SET_REP)); SVN_ERR(svn_sqlite__bindf(stmt, "siiii", svn_checksum_to_cstring(&checksum, pool), (apr_int64_t) rep->revision, (apr_int64_t) rep->item_index, (apr_int64_t) rep->size, (apr_int64_t) rep->expanded_size)); err = svn_sqlite__insert(NULL, stmt); if (err) { representation_t *old_rep; if (err->apr_err != SVN_ERR_SQLITE_CONSTRAINT) return svn_error_trace(err); svn_error_clear(err); /* Constraint failed so the mapping for SHA1_CHECKSUM->REP should exist. If so that's cool -- just do nothing. If not, that's a red flag! */ SVN_ERR(svn_fs_fs__get_rep_reference(&old_rep, fs, &checksum, pool)); if (!old_rep) { /* Something really odd at this point, we failed to insert the checksum AND failed to read an existing checksum. Do we need to flag this? */ } } return SVN_NO_ERROR; }
svn_error_t * svn_fs_fs__set_rep_reference(svn_fs_t *fs, representation_t *rep, svn_boolean_t reject_dup, apr_pool_t *pool) { fs_fs_data_t *ffd = fs->fsap_data; svn_sqlite__stmt_t *stmt; svn_error_t *err; SVN_ERR_ASSERT(ffd->rep_sharing_allowed); if (! ffd->rep_cache_db) SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool)); /* We only allow SHA1 checksums in this table. */ if (rep->sha1_checksum == NULL) return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, _("Only SHA1 checksums can be used as keys in the " "rep_cache table.\n")); SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db, STMT_SET_REP)); SVN_ERR(svn_sqlite__bindf(stmt, "siiii", svn_checksum_to_cstring(rep->sha1_checksum, pool), (apr_int64_t) rep->revision, (apr_int64_t) rep->offset, (apr_int64_t) rep->size, (apr_int64_t) rep->expanded_size)); err = svn_sqlite__insert(NULL, stmt); if (err) { representation_t *old_rep; if (err->apr_err != SVN_ERR_SQLITE_CONSTRAINT) return svn_error_trace(err); svn_error_clear(err); /* Constraint failed so the mapping for SHA1_CHECKSUM->REP should exist. If so, and the value is the same one we were about to write, that's cool -- just do nothing. If, however, the value is *different*, that's a red flag! */ SVN_ERR(svn_fs_fs__get_rep_reference(&old_rep, fs, rep->sha1_checksum, pool)); if (old_rep) { if (reject_dup && ((old_rep->revision != rep->revision) || (old_rep->offset != rep->offset) || (old_rep->size != rep->size) || (old_rep->expanded_size != rep->expanded_size))) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, apr_psprintf(pool, _("Representation key for checksum '%%s' exists " "in filesystem '%%s' with a different value " "(%%ld,%%%s,%%%s,%%%s) than what we were about " "to store (%%ld,%%%s,%%%s,%%%s)"), APR_OFF_T_FMT, SVN_FILESIZE_T_FMT, SVN_FILESIZE_T_FMT, APR_OFF_T_FMT, SVN_FILESIZE_T_FMT, SVN_FILESIZE_T_FMT), svn_checksum_to_cstring_display(rep->sha1_checksum, pool), fs->path, old_rep->revision, old_rep->offset, old_rep->size, old_rep->expanded_size, rep->revision, rep->offset, rep->size, rep->expanded_size); else return SVN_NO_ERROR; } else { /* Something really odd at this point, we failed to insert the checksum AND failed to read an existing checksum. Do we need to flag this? */ } } return SVN_NO_ERROR; }