diff options
author | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-25 21:16:39 +0000 |
---|---|---|
committer | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-25 21:16:39 +0000 |
commit | abbc672ea19a37009560f198ae43f43b72d81874 (patch) | |
tree | b4e0f238468545a28412ec0a28ad4d201751a1bb /chrome | |
parent | 4d5ae3782302f6a9a844ae64c7527c4110cf7688 (diff) | |
download | chromium_src-abbc672ea19a37009560f198ae43f43b72d81874.zip chromium_src-abbc672ea19a37009560f198ae43f43b72d81874.tar.gz chromium_src-abbc672ea19a37009560f198ae43f43b72d81874.tar.bz2 |
Detect error codes in sqlite calls (one)
- This CL is the skeleton of the approach, does not change current behavior
- Right now only detects errors for the SQLStatement::step calls
TEST=none
BUG=11908
Review URL: http://codereview.chromium.org/174090
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24321 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/common/sqlite_utils.cc | 83 | ||||
-rw-r--r-- | chrome/common/sqlite_utils.h | 25 |
2 files changed, 107 insertions, 1 deletions
diff --git a/chrome/common/sqlite_utils.cc b/chrome/common/sqlite_utils.cc index 9695cfb..c37ba9b 100644 --- a/chrome/common/sqlite_utils.cc +++ b/chrome/common/sqlite_utils.cc @@ -4,10 +4,86 @@ #include "chrome/common/sqlite_utils.h" +#include <list> + +#include "base/at_exit.h" #include "base/file_path.h" +#include "base/lock.h" #include "base/logging.h" +#include "base/singleton.h" +#include "base/stl_util-inl.h" #include "base/string16.h" +// The vanilla error handler implements the common fucntionality for all the +// error handlers. Specialized error handlers are expected to only override +// the Handler() function. +class VanillaSQLErrorHandler : public SQLErrorHandler { + public: + VanillaSQLErrorHandler() : error_(SQLITE_OK) { + } + virtual int GetLastError() const { + return error_; + } + protected: + int error_; +}; + +class DebugSQLErrorHandler: public VanillaSQLErrorHandler { + public: + virtual int HandleError(int error, sqlite3* db) { + error_ = error; + NOTREACHED() << "sqlite error " << error + << " db " << static_cast<void*>(db); + return error; + } +}; + +class ReleaseSQLErrorHandler : public VanillaSQLErrorHandler { + public: + virtual int HandleError(int error, sqlite3* db) { + error_ = error; + // TODO(cpu): need to write to some place so we can trigger + // the diagnostic-repair mode. + return error; + } +}; + +// The default error handler factory is also in charge of managing the +// lifetime of the error objects. This object is multi-thread safe. +class DefaultSQLErrorHandlerFactory : public SQLErrorHandlerFactory { + public: + ~DefaultSQLErrorHandlerFactory() { + STLDeleteContainerPointers(errors_.begin(), errors_.end()); + } + + virtual SQLErrorHandler* Make() { + SQLErrorHandler* handler; +#ifndef NDEBUG + handler = new DebugSQLErrorHandler; +#else + handler = new ReleaseSQLErrorHandler; +#endif // NDEBUG + AddHandler(handler); + return handler; + } + + private: + void AddHandler(SQLErrorHandler* handler) { + AutoLock lock(lock_); + errors_.push_back(handler); + } + + typedef std::list<SQLErrorHandler*> ErrorList; + ErrorList errors_; + Lock lock_; +}; + +SQLErrorHandlerFactory* GetErrorHandlerFactory() { + // TODO(cpu): Testing needs to override the error handler. + // Destruction of DefaultSQLErrorHandlerFactory handled by at_exit manager. + return Singleton<DefaultSQLErrorHandlerFactory>::get(); +} + int OpenSqliteDb(const FilePath& filepath, sqlite3** database) { #if defined(OS_WIN) // We want the default encoding to always be UTF-8, so we use the @@ -208,7 +284,12 @@ int SQLStatement::prepare(sqlite3* db, const char* sql, int sql_len) { int SQLStatement::step() { DCHECK(stmt_); - return sqlite3_step(stmt_); + int status = sqlite3_step(stmt_); + if ((status == SQLITE_ROW) || (status == SQLITE_DONE)) + return status; + // We got a problem. + SQLErrorHandler* error_handler = GetErrorHandlerFactory()->Make(); + return error_handler->HandleError(status, db_handle()); } int SQLStatement::reset() { diff --git a/chrome/common/sqlite_utils.h b/chrome/common/sqlite_utils.h index 5ea8655..615708f 100644 --- a/chrome/common/sqlite_utils.h +++ b/chrome/common/sqlite_utils.h @@ -28,6 +28,31 @@ class scoped_sqlite3_stmt_ptr; class SQLStatement; //------------------------------------------------------------------------------ +// Interface to be implemented by objects that can handle exceptional sqlite +// conditions. This way client code can focus on handling normal condtions. +//------------------------------------------------------------------------------ +class SQLErrorHandler { + public: + virtual ~SQLErrorHandler() {} + // Handle a sqlite error. |error| is the return code an of sqlite operation + // which is considered an error. This handler is free to try repair, notify + // someone or even break into the debugger depending on the situation. + virtual int HandleError(int error, sqlite3* db) = 0; + // Returns the last value of |error| passed to HandleError. + virtual int GetLastError() const = 0; +}; + +//------------------------------------------------------------------------------ +// The factory interface is used to create the different error handling +// strategies for debug, release and for diagnostic mode. +//------------------------------------------------------------------------------ +class SQLErrorHandlerFactory { + public: + virtual ~SQLErrorHandlerFactory() {} + virtual SQLErrorHandler* Make() = 0; +}; + +//------------------------------------------------------------------------------ // A wrapper for sqlite transactions that rollsback when the wrapper // goes out of scope if the caller has not already called Commit or Rollback. // Note: the constructor does NOT Begin a transaction. |