/* Body of svn_fs_fs__open_rep_cache(). Implements svn_atomic__init_once().init_func. */ static svn_error_t * open_rep_cache(void *baton, apr_pool_t *pool) { svn_fs_t *fs = baton; fs_fs_data_t *ffd = fs->fsap_data; const char *db_path; int version; /* Open (or create) the sqlite database. It will be automatically closed when fs->pool is destoyed. */ db_path = path_rep_cache_db(fs->path, pool); SVN_ERR(svn_sqlite__open(&ffd->rep_cache_db, db_path, svn_sqlite__mode_rwcreate, statements, 0, NULL, fs->pool, pool)); SVN_ERR(svn_sqlite__read_schema_version(&version, ffd->rep_cache_db, pool)); if (version < REP_CACHE_SCHEMA_FORMAT) { /* Must be 0 -- an uninitialized (no schema) database. Create the schema. Results in schema version of 1. */ SVN_ERR(svn_sqlite__exec_statements(ffd->rep_cache_db, STMT_CREATE_SCHEMA)); } return SVN_NO_ERROR; }
/* Check the schema format of the database, upgrading it if necessary. Return SVN_ERR_SQLITE_UNSUPPORTED_SCHEMA if the schema format is too new, or SVN_ERR_SQLITE_ERROR if an sqlite error occurs during validation. Return SVN_NO_ERROR if everything is okay. */ static svn_error_t * check_format(svn_sqlite__db_t *db, int latest_schema, const char * const *upgrade_sql, apr_pool_t *scratch_pool) { int current_schema; /* Validate that the schema exists as expected. */ SVN_ERR(svn_sqlite__read_schema_version(¤t_schema, db, scratch_pool)); if (current_schema == latest_schema) return SVN_NO_ERROR; if (current_schema < latest_schema) { struct upgrade_baton ub; ub.current_schema = current_schema; ub.latest_schema = latest_schema; ub.upgrade_sql = upgrade_sql; return svn_error_trace(svn_sqlite__with_transaction( db, upgrade_format, &ub, scratch_pool)); } return svn_error_createf(SVN_ERR_SQLITE_UNSUPPORTED_SCHEMA, NULL, _("Schema format %d not recognized"), current_schema); }
/* Body of svn_fs_fs__open_rep_cache(). Implements svn_atomic__init_once().init_func. */ static svn_error_t * open_rep_cache(void *baton, apr_pool_t *pool) { svn_fs_t *fs = baton; fs_fs_data_t *ffd = fs->fsap_data; svn_sqlite__db_t *sdb; const char *db_path; int version; /* Open (or create) the sqlite database. It will be automatically closed when fs->pool is destroyed. */ db_path = path_rep_cache_db(fs->path, pool); #ifndef WIN32 { /* We want to extend the permissions that apply to the repository as a whole when creating a new rep cache and not simply default to umask. */ svn_boolean_t exists; SVN_ERR(svn_fs_fs__exists_rep_cache(&exists, fs, pool)); if (!exists) { const char *current = svn_fs_fs__path_current(fs, pool); svn_error_t *err = svn_io_file_create_empty(db_path, pool); if (err && !APR_STATUS_IS_EEXIST(err->apr_err)) /* A real error. */ return svn_error_trace(err); else if (err) /* Some other thread/process created the file. */ svn_error_clear(err); else /* We created the file. */ SVN_ERR(svn_io_copy_perms(current, db_path, pool)); } } #endif SVN_ERR(svn_sqlite__open(&sdb, db_path, svn_sqlite__mode_rwcreate, statements, 0, NULL, 0, fs->pool, pool)); SVN_ERR_CLOSE(svn_sqlite__read_schema_version(&version, sdb, pool), sdb); if (version < REP_CACHE_SCHEMA_FORMAT) { /* Must be 0 -- an uninitialized (no schema) database. Create the schema. Results in schema version of 1. */ SVN_ERR_CLOSE(svn_sqlite__exec_statements(sdb, STMT_CREATE_SCHEMA), sdb); } /* This is used as a flag that the database is available so don't set it earlier. */ ffd->rep_cache_db = sdb; return SVN_NO_ERROR; }
svn_error_t * svn_sqlite__get_schema_version(int *version, const char *path, apr_pool_t *scratch_pool) { svn_sqlite__db_t db; SVN_ERR(svn_atomic__init_once(&sqlite_init_state, init_sqlite, NULL, scratch_pool)); SVN_ERR(internal_open(&db.db3, path, svn_sqlite__mode_readonly, scratch_pool)); SVN_ERR(svn_sqlite__read_schema_version(version, &db, scratch_pool)); SQLITE_ERR(sqlite3_close(db.db3), &db); return SVN_NO_ERROR; }
/* Sqlite transaction helper for opening the db in svn_wc__db_wcroot_parse_local_abspath() to avoid multiple db operations that each obtain and release a lock */ static svn_error_t * fetch_sdb_info(apr_int64_t *wc_id, int *format, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) { *wc_id = -1; *format = -1; SVN_SQLITE__WITH_LOCK4( svn_wc__db_util_fetch_wc_id(wc_id, sdb, scratch_pool), svn_sqlite__read_schema_version(format, sdb, scratch_pool), verify_stats_table(sdb, *format, scratch_pool), SVN_NO_ERROR, sdb); return SVN_NO_ERROR; }
svn_error_t * svn_wc__db_pdh_create_wcroot(svn_wc__db_wcroot_t **wcroot, const char *wcroot_abspath, svn_sqlite__db_t *sdb, apr_int64_t wc_id, int format, svn_boolean_t verify_format, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { if (sdb && format == FORMAT_FROM_SDB) SVN_ERR(svn_sqlite__read_schema_version(&format, sdb, scratch_pool)); /* If we construct a wcroot, then we better have a format. */ SVN_ERR_ASSERT(format >= 1); /* If this working copy is PRE-1.0, then simply bail out. */ if (format < 4) { return svn_error_createf( SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL, _("Working copy format of '%s' is too old (%d); " "please check out your working copy again"), svn_dirent_local_style(wcroot_abspath, scratch_pool), format); } /* If this working copy is from a future version, then bail out. */ if (format > SVN_WC__VERSION) { return svn_error_createf( SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL, _("This client is too old to work with the working copy at\n" "'%s' (format %d).\n" "You need to get a newer Subversion client. For more details, see\n" " http://subversion.apache.org/faq.html#working-copy-format-change\n" ), svn_dirent_local_style(wcroot_abspath, scratch_pool), format); } /* Verify that no work items exists. If they do, then our integrity is suspect and, thus, we cannot upgrade this database. */ if (format >= SVN_WC__HAS_WORK_QUEUE && format < SVN_WC__VERSION && verify_format) { svn_error_t *err = svn_wc__db_verify_no_work(sdb); if (err) { /* Special message for attempts to upgrade a 1.7-dev wc with outstanding workqueue items. */ if (err->apr_err == SVN_ERR_WC_CLEANUP_REQUIRED && format < SVN_WC__VERSION && verify_format) err = svn_error_quick_wrap(err, _("Cleanup with an older 1.7 " "client before upgrading with " "this client")); return svn_error_trace(err); } } /* Auto-upgrade the SDB if possible. */ if (format < SVN_WC__VERSION && verify_format) { return svn_error_createf(SVN_ERR_WC_UPGRADE_REQUIRED, NULL, _("The working copy at '%s'\nis too old " "(format %d) to work with client version " "'%s' (expects format %d). You need to " "upgrade the working copy first.\n"), svn_dirent_local_style(wcroot_abspath, scratch_pool), format, SVN_VERSION, SVN_WC__VERSION); } *wcroot = apr_palloc(result_pool, sizeof(**wcroot)); (*wcroot)->abspath = wcroot_abspath; (*wcroot)->sdb = sdb; (*wcroot)->wc_id = wc_id; (*wcroot)->format = format; /* 8 concurrent locks is probably more than a typical wc_ng based svn client uses. */ (*wcroot)->owned_locks = apr_array_make(result_pool, 8, sizeof(svn_wc__db_wclock_t)); (*wcroot)->access_cache = apr_hash_make(result_pool); /* SDB will be NULL for pre-NG working copies. We only need to run a cleanup when the SDB is present. */ if (sdb != NULL) apr_pool_cleanup_register(result_pool, *wcroot, close_wcroot, apr_pool_cleanup_null); return SVN_NO_ERROR; }