rep-cache.c (322442) | rep-cache.c (362181) |
---|---|
1/* rep-sharing.c --- the rep-sharing cache for fsfs 2 * 3 * ==================================================================== 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the --- 10 unchanged lines hidden (view full) --- 19 * under the License. 20 * ==================================================================== 21 */ 22 23#include "svn_pools.h" 24 25#include "svn_private_config.h" 26 | 1/* rep-sharing.c --- the rep-sharing cache for fsfs 2 * 3 * ==================================================================== 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the --- 10 unchanged lines hidden (view full) --- 19 * under the License. 20 * ==================================================================== 21 */ 22 23#include "svn_pools.h" 24 25#include "svn_private_config.h" 26 |
27#include "cached_data.h" |
|
27#include "fs_fs.h" 28#include "fs.h" 29#include "rep-cache.h" 30#include "../libsvn_fs/fs-loader.h" 31 32#include "svn_path.h" 33 34#include "private/svn_sqlite.h" 35 36#include "rep-cache-db.h" 37 | 28#include "fs_fs.h" 29#include "fs.h" 30#include "rep-cache.h" 31#include "../libsvn_fs/fs-loader.h" 32 33#include "svn_path.h" 34 35#include "private/svn_sqlite.h" 36 37#include "rep-cache-db.h" 38 |
38/* A few magic values */ 39#define REP_CACHE_SCHEMA_FORMAT 1 40 | |
41REP_CACHE_DB_SQL_DECLARE_STATEMENTS(statements); 42 43 44 45/** Helper functions. **/ 46static APR_INLINE const char * 47path_rep_cache_db(const char *fs_path, 48 apr_pool_t *result_pool) 49{ 50 return svn_dirent_join(fs_path, REP_CACHE_DB_NAME, result_pool); 51} 52 | 39REP_CACHE_DB_SQL_DECLARE_STATEMENTS(statements); 40 41 42 43/** Helper functions. **/ 44static APR_INLINE const char * 45path_rep_cache_db(const char *fs_path, 46 apr_pool_t *result_pool) 47{ 48 return svn_dirent_join(fs_path, REP_CACHE_DB_NAME, result_pool); 49} 50 |
53#define SVN_ERR_CLOSE(x, db) do \ 54{ \ 55 svn_error_t *svn__err = (x); \ 56 if (svn__err) \ 57 return svn_error_compose_create(svn__err, svn_sqlite__close(db)); \ 58} while (0) 59 | |
60 61/** Library-private API's. **/ 62 63/* Body of svn_fs_fs__open_rep_cache(). 64 Implements svn_atomic__init_once().init_func. 65 */ 66static svn_error_t * 67open_rep_cache(void *baton, --- 33 unchanged lines hidden (view full) --- 101 } 102 } 103#endif 104 SVN_ERR(svn_sqlite__open(&sdb, db_path, 105 svn_sqlite__mode_rwcreate, statements, 106 0, NULL, 0, 107 fs->pool, pool)); 108 | 51 52/** Library-private API's. **/ 53 54/* Body of svn_fs_fs__open_rep_cache(). 55 Implements svn_atomic__init_once().init_func. 56 */ 57static svn_error_t * 58open_rep_cache(void *baton, --- 33 unchanged lines hidden (view full) --- 92 } 93 } 94#endif 95 SVN_ERR(svn_sqlite__open(&sdb, db_path, 96 svn_sqlite__mode_rwcreate, statements, 97 0, NULL, 0, 98 fs->pool, pool)); 99 |
109 SVN_ERR_CLOSE(svn_sqlite__read_schema_version(&version, sdb, pool), sdb); 110 if (version < REP_CACHE_SCHEMA_FORMAT) | 100 SVN_SQLITE__ERR_CLOSE(svn_sqlite__read_schema_version(&version, sdb, pool), 101 sdb); 102 /* If we have an uninitialized database, go ahead and create the schema. */ 103 if (version <= 0) |
111 { | 104 { |
112 /* Must be 0 -- an uninitialized (no schema) database. Create 113 the schema. Results in schema version of 1. */ 114 SVN_ERR_CLOSE(svn_sqlite__exec_statements(sdb, STMT_CREATE_SCHEMA), sdb); | 105 int stmt; 106 107 if (ffd->format >= SVN_FS_FS__MIN_REP_CACHE_SCHEMA_V2_FORMAT) 108 stmt = STMT_CREATE_SCHEMA_V2; 109 else 110 stmt = STMT_CREATE_SCHEMA_V1; 111 112 SVN_SQLITE__ERR_CLOSE(svn_sqlite__exec_statements(sdb, stmt), sdb); |
115 } 116 117 /* This is used as a flag that the database is available so don't 118 set it earlier. */ 119 ffd->rep_cache_db = sdb; 120 121 return SVN_NO_ERROR; 122} --- 135 unchanged lines hidden (view full) --- 258 return SVN_NO_ERROR; 259} 260 261 262/* This function's caller ignores most errors it returns. 263 If you extend this function, check the callsite to see if you have 264 to make it not-ignore additional error codes. */ 265svn_error_t * | 113 } 114 115 /* This is used as a flag that the database is available so don't 116 set it earlier. */ 117 ffd->rep_cache_db = sdb; 118 119 return SVN_NO_ERROR; 120} --- 135 unchanged lines hidden (view full) --- 256 return SVN_NO_ERROR; 257} 258 259 260/* This function's caller ignores most errors it returns. 261 If you extend this function, check the callsite to see if you have 262 to make it not-ignore additional error codes. */ 263svn_error_t * |
266svn_fs_fs__get_rep_reference(representation_t **rep, | 264svn_fs_fs__get_rep_reference(representation_t **rep_p, |
267 svn_fs_t *fs, 268 svn_checksum_t *checksum, 269 apr_pool_t *pool) 270{ 271 fs_fs_data_t *ffd = fs->fsap_data; 272 svn_sqlite__stmt_t *stmt; 273 svn_boolean_t have_row; | 265 svn_fs_t *fs, 266 svn_checksum_t *checksum, 267 apr_pool_t *pool) 268{ 269 fs_fs_data_t *ffd = fs->fsap_data; 270 svn_sqlite__stmt_t *stmt; 271 svn_boolean_t have_row; |
272 representation_t *rep; |
|
274 275 SVN_ERR_ASSERT(ffd->rep_sharing_allowed); 276 if (! ffd->rep_cache_db) 277 SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool)); 278 279 /* We only allow SHA1 checksums in this table. */ 280 if (checksum->kind != svn_checksum_sha1) 281 return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, 282 _("Only SHA1 checksums can be used as keys in the " 283 "rep_cache table.\n")); 284 285 SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db, STMT_GET_REP)); 286 SVN_ERR(svn_sqlite__bindf(stmt, "s", 287 svn_checksum_to_cstring(checksum, pool))); 288 289 SVN_ERR(svn_sqlite__step(&have_row, stmt)); 290 if (have_row) 291 { | 273 274 SVN_ERR_ASSERT(ffd->rep_sharing_allowed); 275 if (! ffd->rep_cache_db) 276 SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool)); 277 278 /* We only allow SHA1 checksums in this table. */ 279 if (checksum->kind != svn_checksum_sha1) 280 return svn_error_create(SVN_ERR_BAD_CHECKSUM_KIND, NULL, 281 _("Only SHA1 checksums can be used as keys in the " 282 "rep_cache table.\n")); 283 284 SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db, STMT_GET_REP)); 285 SVN_ERR(svn_sqlite__bindf(stmt, "s", 286 svn_checksum_to_cstring(checksum, pool))); 287 288 SVN_ERR(svn_sqlite__step(&have_row, stmt)); 289 if (have_row) 290 { |
292 *rep = apr_pcalloc(pool, sizeof(**rep)); 293 svn_fs_fs__id_txn_reset(&(*rep)->txn_id); 294 memcpy((*rep)->sha1_digest, checksum->digest, 295 sizeof((*rep)->sha1_digest)); 296 (*rep)->has_sha1 = TRUE; 297 (*rep)->revision = svn_sqlite__column_revnum(stmt, 0); 298 (*rep)->item_index = svn_sqlite__column_int64(stmt, 1); 299 (*rep)->size = svn_sqlite__column_int64(stmt, 2); 300 (*rep)->expanded_size = svn_sqlite__column_int64(stmt, 3); | 291 rep = apr_pcalloc(pool, sizeof(*rep)); 292 svn_fs_fs__id_txn_reset(&(rep->txn_id)); 293 memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest)); 294 rep->has_sha1 = TRUE; 295 rep->revision = svn_sqlite__column_revnum(stmt, 0); 296 rep->item_index = svn_sqlite__column_int64(stmt, 1); 297 rep->size = svn_sqlite__column_int64(stmt, 2); 298 rep->expanded_size = svn_sqlite__column_int64(stmt, 3); |
301 } 302 else | 299 } 300 else |
303 *rep = NULL; | 301 rep = NULL; |
304 305 SVN_ERR(svn_sqlite__reset(stmt)); 306 | 302 303 SVN_ERR(svn_sqlite__reset(stmt)); 304 |
307 if (*rep) | 305 if (rep) |
308 { | 306 { |
307 svn_error_t *err; 308 309 SVN_ERR(svn_fs_fs__fixup_expanded_size(fs, rep, pool)); 310 |
|
309 /* Check that REP refers to a revision that exists in FS. */ | 311 /* Check that REP refers to a revision that exists in FS. */ |
310 svn_error_t *err = svn_fs_fs__ensure_revision_exists((*rep)->revision, 311 fs, pool); | 312 err = svn_fs_fs__ensure_revision_exists(rep->revision, fs, pool); |
312 if (err) 313 return svn_error_createf(SVN_ERR_FS_CORRUPT, err, 314 "Checksum '%s' in rep-cache is beyond HEAD", 315 svn_checksum_to_cstring_display(checksum, 316 pool)); 317 } 318 | 313 if (err) 314 return svn_error_createf(SVN_ERR_FS_CORRUPT, err, 315 "Checksum '%s' in rep-cache is beyond HEAD", 316 svn_checksum_to_cstring_display(checksum, 317 pool)); 318 } 319 |
320 *rep_p = rep; |
|
319 return SVN_NO_ERROR; 320} 321 322svn_error_t * 323svn_fs_fs__set_rep_reference(svn_fs_t *fs, 324 representation_t *rep, 325 apr_pool_t *pool) 326{ 327 fs_fs_data_t *ffd = fs->fsap_data; 328 svn_sqlite__stmt_t *stmt; | 321 return SVN_NO_ERROR; 322} 323 324svn_error_t * 325svn_fs_fs__set_rep_reference(svn_fs_t *fs, 326 representation_t *rep, 327 apr_pool_t *pool) 328{ 329 fs_fs_data_t *ffd = fs->fsap_data; 330 svn_sqlite__stmt_t *stmt; |
329 svn_error_t *err; | |
330 svn_checksum_t checksum; 331 checksum.kind = svn_checksum_sha1; 332 checksum.digest = rep->sha1_digest; 333 334 SVN_ERR_ASSERT(ffd->rep_sharing_allowed); 335 if (! ffd->rep_cache_db) 336 SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool)); 337 --- 6 unchanged lines hidden (view full) --- 344 SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db, STMT_SET_REP)); 345 SVN_ERR(svn_sqlite__bindf(stmt, "siiii", 346 svn_checksum_to_cstring(&checksum, pool), 347 (apr_int64_t) rep->revision, 348 (apr_int64_t) rep->item_index, 349 (apr_int64_t) rep->size, 350 (apr_int64_t) rep->expanded_size)); 351 | 331 svn_checksum_t checksum; 332 checksum.kind = svn_checksum_sha1; 333 checksum.digest = rep->sha1_digest; 334 335 SVN_ERR_ASSERT(ffd->rep_sharing_allowed); 336 if (! ffd->rep_cache_db) 337 SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool)); 338 --- 6 unchanged lines hidden (view full) --- 345 SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db, STMT_SET_REP)); 346 SVN_ERR(svn_sqlite__bindf(stmt, "siiii", 347 svn_checksum_to_cstring(&checksum, pool), 348 (apr_int64_t) rep->revision, 349 (apr_int64_t) rep->item_index, 350 (apr_int64_t) rep->size, 351 (apr_int64_t) rep->expanded_size)); 352 |
352 err = svn_sqlite__insert(NULL, stmt); 353 if (err) 354 { 355 representation_t *old_rep; | 353 SVN_ERR(svn_sqlite__insert(NULL, stmt)); |
356 | 354 |
357 if (err->apr_err != SVN_ERR_SQLITE_CONSTRAINT) 358 return svn_error_trace(err); 359 360 svn_error_clear(err); 361 362 /* Constraint failed so the mapping for SHA1_CHECKSUM->REP 363 should exist. If so that's cool -- just do nothing. If not, 364 that's a red flag! */ 365 SVN_ERR(svn_fs_fs__get_rep_reference(&old_rep, fs, &checksum, pool)); 366 367 if (!old_rep) 368 { 369 /* Something really odd at this point, we failed to insert the 370 checksum AND failed to read an existing checksum. Do we need 371 to flag this? */ 372 } 373 } 374 | |
375 return SVN_NO_ERROR; 376} 377 378 379svn_error_t * 380svn_fs_fs__del_rep_reference(svn_fs_t *fs, 381 svn_revnum_t youngest, 382 apr_pool_t *pool) --- 61 unchanged lines hidden --- | 355 return SVN_NO_ERROR; 356} 357 358 359svn_error_t * 360svn_fs_fs__del_rep_reference(svn_fs_t *fs, 361 svn_revnum_t youngest, 362 apr_pool_t *pool) --- 61 unchanged lines hidden --- |