Index: content/browser/media_gallery/media_gallery_database.cc |
diff --git a/content/browser/media_gallery/media_gallery_database.cc b/content/browser/media_gallery/media_gallery_database.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8127c0bce38b42d45dfe5fb53f89b697cfc8c486 |
--- /dev/null |
+++ b/content/browser/media_gallery/media_gallery_database.cc |
@@ -0,0 +1,191 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/media_gallery/media_gallery_database.h" |
+ |
+#include <algorithm> |
+ |
+#include "base/file_path.h" |
+#include "base/logging.h" |
+#if defined(OS_WIN) |
Lei Zhang
2012/03/07 01:41:42
Put this below, even though the linter will compla
tpayne
2012/03/07 18:04:03
Done.
|
+#include "base/sys_string_conversions.h" |
+#endif // OS_WIN |
+#include "sql/diagnostic_error_delegate.h" |
+#include "sql/statement.h" |
+#include "sql/transaction.h" |
+ |
+#define MEDIA_GALLERY_COLLECTION_ROW_FIELDS \ |
+ " collections.id, collections.path, collections.last_modified_time, " \ |
+ "collections.entry_count, collections.all_parsed " |
+ |
+namespace media_gallery { |
+ |
+namespace { |
+ |
+static const int kCurrentVersionNumber = 1; |
Lei Zhang
2012/03/07 01:41:42
You don't need static inside an anonymous namespac
tpayne
2012/03/07 18:04:03
Done.
|
+static const int kCompatibleVersionNumber = 1; |
+static const FilePath::CharType kMediaGalleryDatabaseName[] = |
Lei Zhang
2012/03/07 01:41:42
This will create a static initializers. Declare co
tpayne
2012/03/07 18:04:03
I don't understand how it will create a static ini
Lei Zhang
2012/03/07 20:59:08
Whoops, I misread that as FilePath::StringType som
|
+ FILE_PATH_LITERAL(".media_gallery.db"); |
+ |
+class HistogramName { |
+ public: |
+ static const char* name() { |
+ return "Sqlite.MediaGallery.Error"; |
+ } |
+}; |
+ |
+} // namespace |
+ |
+MediaGalleryDatabase::MediaGalleryDatabase() { } |
+ |
+MediaGalleryDatabase::~MediaGalleryDatabase() { } |
+ |
+sql::InitStatus MediaGalleryDatabase::Init(const FilePath& database_dir) { |
+ // Set the exceptional sqlite error handler. |
+ db_.set_error_delegate(new sql::DiagnosticErrorDelegate<HistogramName>()); |
+ |
+ // Set the database page size to something a little larger to give us |
+ // better performance (we're typically seek rather than bandwidth limited). |
+ // This only has an effect before any tables have been created, otherwise |
+ // this is a NOP. Must be a power of 2 and a max of 8192. |
+ db_.set_page_size(4096); |
+ |
+ // Increase the cache size. The page size, plus a little extra, times this |
+ // value, tells us how much memory the cache will use maximum. |
+ // 6000 * 4KB = 24MB |
+ db_.set_cache_size(6000); |
+ |
+ if (!db_.Open(database_dir.Append(FilePath(kMediaGalleryDatabaseName)))) |
+ return sql::INIT_FAILURE; |
+ |
+ return InitInternal(&db_); |
+} |
+ |
+sql::InitStatus MediaGalleryDatabase::InitInternal(sql::Connection* db) { |
+ // Wrap the rest of init in a tranaction. This will prevent the database from |
+ // getting corrupted if we crash in the middle of initialization or migration. |
+ sql::Transaction committer(db); |
+ if (!committer.Begin()) |
+ return sql::INIT_FAILURE; |
+ |
+ // Prime the cache. |
+ db->Preload(); |
+ |
+ // Create the tables and indices. |
+ if (!meta_table_.Init(db, GetCurrentVersion(), kCompatibleVersionNumber)) |
+ return sql::INIT_FAILURE; |
+ |
+ if (!CreateCollectionsTable(db)) { |
Lei Zhang
2012/03/07 01:41:42
nit: no need for parenthesis for a one line condit
tpayne
2012/03/07 18:04:03
Done.
|
+ return sql::INIT_FAILURE; |
+ } |
+ |
+ // Version check. |
+ sql::InitStatus version_status = EnsureCurrentVersion(); |
+ if (version_status != sql::INIT_OK) |
+ return version_status; |
+ |
+ return committer.Commit() ? sql::INIT_OK : sql::INIT_FAILURE; |
+} |
+ |
+sql::Connection& MediaGalleryDatabase::GetDB() { |
+ return db_; |
+} |
+ |
+sql::InitStatus MediaGalleryDatabase::EnsureCurrentVersion() { |
+ // We can't read databases newer than we were designed for. |
Lei Zhang
2012/03/07 01:41:42
nit: indentation.
tpayne
2012/03/07 18:04:03
Done.
|
+ if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { |
+ LOG(WARNING) << "Media Gallery database is too new."; |
Lei Zhang
2012/03/07 01:41:42
VLOG? http://www.chromium.org/developers/coding-st
tpayne
2012/03/07 18:04:03
Done.
|
+ return sql::INIT_TOO_NEW; |
+ } |
+ int cur_version = meta_table_.GetVersionNumber(); |
+ if (cur_version == 0) { |
+ LOG(WARNING) << "Initializing the Media Gallery database."; |
+ |
+ ++cur_version; |
+ meta_table_.SetVersionNumber(cur_version); |
+ meta_table_.SetCompatibleVersionNumber( |
+ std::min(cur_version, kCompatibleVersionNumber)); |
+ } |
+ return sql::INIT_OK; |
+} |
+ |
+// static |
+int MediaGalleryDatabase::GetCurrentVersion() { |
+ return kCurrentVersionNumber; |
+} |
+ |
+CollectionId MediaGalleryDatabase::CreateCollectionRow( |
+ CollectionRow* row) { |
+ const char* sql = "INSERT INTO collections" |
+ "(path, last_modified_time, entry_count, all_parsed) " |
+ "VALUES(?, ?, ?, ?)"; |
+ |
+ sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, sql)); |
+#if defined(OS_WIN) |
+ statement.BindString(0, base::SysWideToUTF8(row->path.value().c_str())); |
+#elif defined(OS_POSIX) |
+ statement.BindString(0, row->path.value().c_str()); |
+#endif // OS_WIN |
+ statement.BindInt64(1, row->last_modified_time.ToInternalValue()); |
+ statement.BindInt(2, row->entry_count); |
+ statement.BindInt(3, row->all_parsed ? 1 : 0); |
+ |
+ if (!statement.Run()) { |
+ VLOG(0) << "Failed to add collection " << row->path.value() |
+ << " to table media_gallery.collections"; |
+ return 0; |
+ } |
+ return row->id = GetDB().GetLastInsertRowId(); |
+} |
+ |
+bool MediaGalleryDatabase::GetCollectionRow(CollectionId id, |
+ CollectionRow* row) { |
+ sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, |
+ "SELECT" MEDIA_GALLERY_COLLECTION_ROW_FIELDS |
+ "FROM collections WHERE id=?")); |
+ statement.BindInt64(0, id); |
+ |
+ if (statement.Step()) { |
+ FillCollectionRow(statement, row); |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+// Convenience method to fill a row from a statement. Must be in sync with the |
+// columns in MEDIA_GALLERY_COLLECTION_ROW_FIELDS |
+void MediaGalleryDatabase::FillCollectionRow(const sql::Statement& s, |
Lei Zhang
2012/03/07 01:41:42
nit: can we not use "s" and "i" as parameter names
tpayne
2012/03/07 18:04:03
Done.
|
+ CollectionRow* i) { |
+ DCHECK(i); |
Lei Zhang
2012/03/07 01:41:42
No need. If |i| is NULL, we'll immediately crash o
tpayne
2012/03/07 18:04:03
Done.
|
+ i->id = s.ColumnInt64(0); |
+#if defined(OS_WIN) |
+ i->path = FilePath(base::SysUTF8ToWide(s.ColumnString(1))); |
+#elif defined(OS_POSIX) |
+ i->path = FilePath(s.ColumnString(1)); |
+#endif // OS_WIN |
+ i->last_modified_time = base::Time::FromInternalValue(s.ColumnInt64(2)); |
+ i->entry_count = s.ColumnInt(3); |
+ i->all_parsed = s.ColumnInt(4) != 0; |
+} |
+ |
+// static |
+bool MediaGalleryDatabase::DoesCollectionsTableExist(sql::Connection *db) { |
+ return db->DoesTableExist("collections"); |
+} |
+ |
+// static |
+bool MediaGalleryDatabase::CreateCollectionsTable(sql::Connection* db) { |
+ if (DoesCollectionsTableExist(db)) |
+ return true; |
+ |
+ const char *sql = "CREATE TABLE collections" |
+ " (id INTEGER PRIMARY KEY," |
+ "path LONGVARCHAR NOT NULL," |
+ "last_modified_time INTEGER NOT NULL," |
+ "entry_count INTEGER DEFAULT 0 NOT NULL," |
+ "all_parsed INTEGER DEFAULT 0 NOT NULL)"; |
+ return db->Execute(sql); |
+} |
+ |
+} // namespace media_gallery |