summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorcpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-25 21:16:39 +0000
committercpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-25 21:16:39 +0000
commitabbc672ea19a37009560f198ae43f43b72d81874 (patch)
treeb4e0f238468545a28412ec0a28ad4d201751a1bb /chrome
parent4d5ae3782302f6a9a844ae64c7527c4110cf7688 (diff)
downloadchromium_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.cc83
-rw-r--r--chrome/common/sqlite_utils.h25
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.