Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_subr/sqlite.c view on Meta::CPAN
{
{
int flags;
if (mode == svn_sqlite__mode_readonly)
flags = SQLITE_OPEN_READONLY;
else if (mode == svn_sqlite__mode_readwrite)
flags = SQLITE_OPEN_READWRITE;
else if (mode == svn_sqlite__mode_rwcreate)
flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
else
SVN_ERR_MALFUNCTION();
/* Turn off SQLite's mutexes. All svn objects are single-threaded,
so we can already guarantee that our use of the SQLite handle
will be serialized properly.
Note: in 3.6.x, we've already config'd SQLite into MULTITHREAD mode,
so this is probably redundant, but if we are running in a process where
somebody initialized SQLite before us it is needed anyway. */
flags |= SQLITE_OPEN_NOMUTEX;
#if !defined(WIN32) && !defined(SVN_SQLITE_INLINE)
if (mode == svn_sqlite__mode_rwcreate)
{
svn_node_kind_t kind;
/* Create the file before SQLite to avoid any permissions
problems with an SQLite build that uses the default
SQLITE_DEFAULT_FILE_PERMISSIONS of 644 modified by umask.
We simply want umask permissions. */
SVN_ERR(svn_io_check_path(path, &kind, scratch_pool));
if (kind == svn_node_none)
SVN_ERR(svn_io_file_create(path, "", scratch_pool));
}
#endif
/* Open the database. Note that a handle is returned, even when an error
occurs (except for out-of-memory); thus, we can safely use it to
extract an error message and construct an svn_error_t. */
{
/* We'd like to use SQLITE_ERR here, but we can't since it would
just return an error and leave the database open. So, we need to
do this manually. */
/* ### SQLITE_CANTOPEN */
int err_code = sqlite3_open_v2(path, db3, flags, NULL);
if (err_code != SQLITE_OK)
{
/* Save the error message before closing the SQLite handle. */
char *msg = apr_pstrdup(scratch_pool, sqlite3_errmsg(*db3));
/* We don't catch the error here, since we care more about the open
error than the close error at this point. */
sqlite3_close(*db3);
SQLITE_ERR_MSG(err_code, msg);
}
}
}
/* Retry until timeout when database is busy. */
SQLITE_ERR_MSG(sqlite3_busy_timeout(*db3, BUSY_TIMEOUT),
sqlite3_errmsg(*db3));
return SVN_NO_ERROR;
}
/* APR cleanup function used to close the database when its pool is destroyed.
DATA should be the svn_sqlite__db_t handle for the database. */
static apr_status_t
close_apr(void *data)
{
svn_sqlite__db_t *db = data;
svn_error_t *err = SVN_NO_ERROR;
apr_status_t result;
int i;
/* Check to see if we've already closed this database. */
if (db->db3 == NULL)
return APR_SUCCESS;
/* Finalize any existing prepared statements. */
for (i = 0; i < db->nbr_statements; i++)
{
if (db->prepared_stmts[i])
{
if (db->prepared_stmts[i]->needs_reset)
{
#ifdef SVN_DEBUG
const char *stmt_text = db->statement_strings[i];
stmt_text = stmt_text; /* Provide value for debugger */
SVN_ERR_MALFUNCTION_NO_RETURN();
#else
err = svn_error_compose_create(
err,
svn_sqlite__reset(db->prepared_stmts[i]));
#endif
}
err = svn_error_compose_create(
svn_sqlite__finalize(db->prepared_stmts[i]), err);
}
}
/* And finalize any used internal statements */
for (; i < db->nbr_statements + STMT_INTERNAL_LAST; i++)
{
if (db->prepared_stmts[i])
{
err = svn_error_compose_create(
svn_sqlite__finalize(db->prepared_stmts[i]), err);
}
}
result = sqlite3_close(db->db3);
/* If there's a pre-existing error, return it. */
if (err)
{
result = err->apr_err;
svn_error_clear(err);
return result;
src/subversion/subversion/libsvn_subr/sqlite.c view on Meta::CPAN
err = svn_error_compose_create(err,
svn_sqlite__reset(db->prepared_stmts[i]));
return err;
}
svn_error_t *
svn_sqlite__begin_transaction(svn_sqlite__db_t *db)
{
svn_sqlite__stmt_t *stmt;
SVN_ERR(get_internal_statement(&stmt, db,
STMT_INTERNAL_BEGIN_TRANSACTION));
SVN_ERR(svn_sqlite__step_done(stmt));
return SVN_NO_ERROR;
}
svn_error_t *
svn_sqlite__begin_immediate_transaction(svn_sqlite__db_t *db)
{
svn_sqlite__stmt_t *stmt;
SVN_ERR(get_internal_statement(&stmt, db,
STMT_INTERNAL_BEGIN_IMMEDIATE_TRANSACTION));
SVN_ERR(svn_sqlite__step_done(stmt));
return SVN_NO_ERROR;
}
svn_error_t *
svn_sqlite__begin_savepoint(svn_sqlite__db_t *db)
{
svn_sqlite__stmt_t *stmt;
SVN_ERR(get_internal_statement(&stmt, db,
STMT_INTERNAL_SAVEPOINT_SVN));
SVN_ERR(svn_sqlite__step_done(stmt));
return SVN_NO_ERROR;
}
svn_error_t *
svn_sqlite__finish_transaction(svn_sqlite__db_t *db,
svn_error_t *err)
{
svn_sqlite__stmt_t *stmt;
/* Commit or rollback the sqlite transaction. */
if (err)
{
svn_error_t *err2;
err2 = get_internal_statement(&stmt, db,
STMT_INTERNAL_ROLLBACK_TRANSACTION);
if (!err2)
err2 = svn_sqlite__step_done(stmt);
if (err2 && err2->apr_err == SVN_ERR_SQLITE_BUSY)
{
/* ### Houston, we have a problem!
We are trying to rollback but we can't because some
statements are still busy. This leaves the database
unusable for future transactions as the current transaction
is still open.
As we are returning the actual error as the most relevant
error in the chain, our caller might assume that it can
retry/compensate on this error (e.g. SVN_WC_LOCKED), while
in fact the SQLite database is unusable until the statements
started within this transaction are reset and the transaction
aborted.
We try to compensate by resetting all prepared but unreset
statements; but we leave the busy error in the chain anyway to
help diagnosing the original error and help in finding where
a reset statement is missing. */
err2 = reset_all_statements(db, err2);
err2 = svn_error_compose_create(
svn_sqlite__step_done(stmt),
err2);
}
return svn_error_compose_create(err,
err2);
}
SVN_ERR(get_internal_statement(&stmt, db, STMT_INTERNAL_COMMIT_TRANSACTION));
return svn_error_trace(svn_sqlite__step_done(stmt));
}
svn_error_t *
svn_sqlite__finish_savepoint(svn_sqlite__db_t *db,
svn_error_t *err)
{
svn_sqlite__stmt_t *stmt;
if (err)
{
svn_error_t *err2;
err2 = get_internal_statement(&stmt, db,
STMT_INTERNAL_ROLLBACK_TO_SAVEPOINT_SVN);
if (!err2)
err2 = svn_sqlite__step_done(stmt);
if (err2 && err2->apr_err == SVN_ERR_SQLITE_BUSY)
{
/* Ok, we have a major problem. Some statement is still open, which
makes it impossible to release this savepoint.
### See huge comment in svn_sqlite__finish_transaction for
further details */
err2 = reset_all_statements(db, err2);
err2 = svn_error_compose_create(svn_sqlite__step_done(stmt), err2);
}
err = svn_error_compose_create(err, err2);
err2 = get_internal_statement(&stmt, db,
STMT_INTERNAL_RELEASE_SAVEPOINT_SVN);
if (!err2)
err2 = svn_sqlite__step_done(stmt);
return svn_error_trace(svn_error_compose_create(err, err2));
}
SVN_ERR(get_internal_statement(&stmt, db,
STMT_INTERNAL_RELEASE_SAVEPOINT_SVN));
return svn_error_trace(svn_sqlite__step_done(stmt));
}
( run in 0.667 second using v1.01-cache-2.11-cpan-140bd7fdf52 )