/* This function's caller ignores most errors it returns. If you extend this function, check the callsite to see if you have to make it not-ignore additional error codes. */ svn_error_t * svn_fs_fs__get_rep_reference(representation_t **rep, svn_fs_t *fs, svn_checksum_t *checksum, apr_pool_t *pool) { fs_fs_data_t *ffd = fs->fsap_data; svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; 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 (checksum->kind != svn_checksum_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_GET_REP)); SVN_ERR(svn_sqlite__bindf(stmt, "s", svn_checksum_to_cstring(checksum, pool))); SVN_ERR(svn_sqlite__step(&have_row, stmt)); if (have_row) { *rep = apr_pcalloc(pool, sizeof(**rep)); svn_fs_fs__id_txn_reset(&(*rep)->txn_id); memcpy((*rep)->sha1_digest, checksum->digest, sizeof((*rep)->sha1_digest)); (*rep)->has_sha1 = TRUE; (*rep)->revision = svn_sqlite__column_revnum(stmt, 0); (*rep)->item_index = svn_sqlite__column_int64(stmt, 1); (*rep)->size = svn_sqlite__column_int64(stmt, 2); (*rep)->expanded_size = svn_sqlite__column_int64(stmt, 3); } else *rep = NULL; SVN_ERR(svn_sqlite__reset(stmt)); if (*rep) { /* Check that REP refers to a revision that exists in FS. */ svn_error_t *err = svn_fs_fs__ensure_revision_exists((*rep)->revision, fs, pool); if (err) return svn_error_createf(SVN_ERR_FS_CORRUPT, err, "Checksum '%s' in rep-cache is beyond HEAD", svn_checksum_to_cstring_display(checksum, pool)); } return SVN_NO_ERROR; }
svn_error_t * svn_fs_fs__parse_representation(representation_t **rep_p, svn_stringbuf_t *text, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { representation_t *rep; char *str; apr_int64_t val; char *string = text->data; svn_checksum_t *checksum; const char *end; rep = apr_pcalloc(result_pool, sizeof(*rep)); *rep_p = rep; SVN_ERR(parse_revnum(&rep->revision, (const char **)&string)); /* initialize transaction info (never stored) */ svn_fs_fs__id_txn_reset(&rep->txn_id); /* while in transactions, it is legal to simply write "-1" */ str = svn_cstring_tokenize(" ", &string); if (str == NULL) { if (rep->revision == SVN_INVALID_REVNUM) return SVN_NO_ERROR; return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); } SVN_ERR(svn_cstring_atoi64(&val, str)); rep->item_index = (apr_uint64_t)val; str = svn_cstring_tokenize(" ", &string); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_cstring_atoi64(&val, str)); rep->size = (svn_filesize_t)val; str = svn_cstring_tokenize(" ", &string); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_cstring_atoi64(&val, str)); rep->expanded_size = (svn_filesize_t)val; /* Read in the MD5 hash. */ str = svn_cstring_tokenize(" ", &string); if ((str == NULL) || (strlen(str) != (APR_MD5_DIGESTSIZE * 2))) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_md5, str, scratch_pool)); memcpy(rep->md5_digest, checksum->digest, sizeof(rep->md5_digest)); /* The remaining fields are only used for formats >= 4, so check that. */ str = svn_cstring_tokenize(" ", &string); if (str == NULL) return SVN_NO_ERROR; /* Read the SHA1 hash. */ if (strlen(str) != (APR_SHA1_DIGESTSIZE * 2)) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1, str, scratch_pool)); rep->has_sha1 = checksum != NULL; memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest)); /* Read the uniquifier. */ str = svn_cstring_tokenize("/", &string); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); SVN_ERR(svn_fs_fs__id_txn_parse(&rep->uniquifier.noderev_txn_id, str)); str = svn_cstring_tokenize(" ", &string); if (str == NULL || *str != '_') return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); ++str; rep->uniquifier.number = svn__base36toui64(&end, str); if (*end) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); return SVN_NO_ERROR; }
svn_error_t * svn_fs_fs__walk_rep_reference(svn_fs_t *fs, svn_revnum_t start, svn_revnum_t end, svn_error_t *(*walker)(representation_t *, void *, svn_fs_t *, apr_pool_t *), void *walker_baton, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) { fs_fs_data_t *ffd = fs->fsap_data; svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; int iterations = 0; apr_pool_t *iterpool = svn_pool_create(pool); /* Don't check ffd->rep_sharing_allowed. */ SVN_ERR_ASSERT(ffd->format >= SVN_FS_FS__MIN_REP_SHARING_FORMAT); if (! ffd->rep_cache_db) SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool)); /* Check global invariants. */ if (start == 0) { svn_revnum_t max; SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db, STMT_GET_MAX_REV)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); max = svn_sqlite__column_revnum(stmt, 0); SVN_ERR(svn_sqlite__reset(stmt)); if (SVN_IS_VALID_REVNUM(max)) /* The rep-cache could be empty. */ SVN_ERR(svn_fs_fs__ensure_revision_exists(max, fs, iterpool)); } SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db, STMT_GET_REPS_FOR_RANGE)); SVN_ERR(svn_sqlite__bindf(stmt, "rr", start, end)); /* Walk the cache entries. */ SVN_ERR(svn_sqlite__step(&have_row, stmt)); while (have_row) { representation_t *rep; const char *sha1_digest; svn_error_t *err; svn_checksum_t *checksum; /* Clear ITERPOOL occasionally. */ if (iterations++ % 16 == 0) svn_pool_clear(iterpool); /* Check for cancellation. */ if (cancel_func) { err = cancel_func(cancel_baton); if (err) return svn_error_compose_create(err, svn_sqlite__reset(stmt)); } /* Construct a representation_t. */ rep = apr_pcalloc(iterpool, sizeof(*rep)); svn_fs_fs__id_txn_reset(&rep->txn_id); sha1_digest = svn_sqlite__column_text(stmt, 0, iterpool); err = svn_checksum_parse_hex(&checksum, svn_checksum_sha1, sha1_digest, iterpool); if (err) return svn_error_compose_create(err, svn_sqlite__reset(stmt)); rep->has_sha1 = TRUE; memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest)); rep->revision = svn_sqlite__column_revnum(stmt, 1); rep->item_index = svn_sqlite__column_int64(stmt, 2); rep->size = svn_sqlite__column_int64(stmt, 3); rep->expanded_size = svn_sqlite__column_int64(stmt, 4); /* Walk. */ err = walker(rep, walker_baton, fs, iterpool); if (err) return svn_error_compose_create(err, svn_sqlite__reset(stmt)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); } SVN_ERR(svn_sqlite__reset(stmt)); svn_pool_destroy(iterpool); return SVN_NO_ERROR; }