Commit e82db8aa authored by ssid's avatar ssid Committed by Commit Bot

Fix unnecessary errors returned when unique db is missing

When unique db is missing and migration state says it should, the
database could have been deleted by other means. In this case just
return an empty shared db instead of error.

Change-Id: I5b15955662405b306583ed1942d8591703ebf942
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2130685Reviewed-by: default avatarSalvador Guerrero <salg@google.com>
Commit-Queue: ssid <ssid@chromium.org>
Cr-Commit-Position: refs/heads/master@{#756947}
parent 84e15aa2
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "components/leveldb_proto/internal/leveldb_proto_feature_list.h" #include "components/leveldb_proto/internal/leveldb_proto_feature_list.h"
#include "components/leveldb_proto/internal/proto_database_selector.h"
#include "components/leveldb_proto/internal/shared_proto_database_provider.h" #include "components/leveldb_proto/internal/shared_proto_database_provider.h"
#include "components/leveldb_proto/public/proto_database_provider.h" #include "components/leveldb_proto/public/proto_database_provider.h"
#include "components/leveldb_proto/testing/proto/test_db.pb.h" #include "components/leveldb_proto/testing/proto/test_db.pb.h"
...@@ -108,9 +109,11 @@ class TestSharedProtoDatabaseClient : public SharedProtoDatabaseClient { ...@@ -108,9 +109,11 @@ class TestSharedProtoDatabaseClient : public SharedProtoDatabaseClient {
using SharedProtoDatabaseClient::set_migration_status; using SharedProtoDatabaseClient::set_migration_status;
using SharedProtoDatabaseClient::SharedProtoDatabaseClient; using SharedProtoDatabaseClient::SharedProtoDatabaseClient;
TestSharedProtoDatabaseClient(scoped_refptr<SharedProtoDatabase> shared_db) explicit TestSharedProtoDatabaseClient(
scoped_refptr<SharedProtoDatabase> shared_db)
: SharedProtoDatabaseClient::SharedProtoDatabaseClient( : SharedProtoDatabaseClient::SharedProtoDatabaseClient(
nullptr, std::make_unique<ProtoLevelDBWrapper>(shared_db->task_runner_,
shared_db->db_.get()),
ProtoDbType::TEST_DATABASE1, ProtoDbType::TEST_DATABASE1,
shared_db) {} shared_db) {}
...@@ -118,11 +121,18 @@ class TestSharedProtoDatabaseClient : public SharedProtoDatabaseClient { ...@@ -118,11 +121,18 @@ class TestSharedProtoDatabaseClient : public SharedProtoDatabaseClient {
SharedDBMetadataProto::MigrationStatus migration_status) override { SharedDBMetadataProto::MigrationStatus migration_status) override {
set_migration_status(migration_status); set_migration_status(migration_status);
} }
void UpdateEntriesWithRemoveFilter(
std::unique_ptr<KeyValueVector> entries_to_save,
const KeyFilter& delete_key_filter,
Callbacks::UpdateCallback callback) override {
std::move(callback).Run(true);
}
}; };
class TestProtoDatabaseProvider : public ProtoDatabaseProvider { class TestProtoDatabaseProvider : public ProtoDatabaseProvider {
public: public:
TestProtoDatabaseProvider(const base::FilePath& profile_dir) explicit TestProtoDatabaseProvider(const base::FilePath& profile_dir)
: ProtoDatabaseProvider(profile_dir) {} : ProtoDatabaseProvider(profile_dir) {}
TestProtoDatabaseProvider(const base::FilePath& profile_dir, TestProtoDatabaseProvider(const base::FilePath& profile_dir,
const scoped_refptr<SharedProtoDatabase>& shared_db) const scoped_refptr<SharedProtoDatabase>& shared_db)
...@@ -156,10 +166,9 @@ class ProtoDatabaseImplTest : public testing::Test { ...@@ -156,10 +166,9 @@ class ProtoDatabaseImplTest : public testing::Test {
void SetUp() override { void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
ASSERT_TRUE(shared_db_temp_dir_.CreateUniqueTempDir()); ASSERT_TRUE(shared_db_temp_dir_.CreateUniqueTempDir());
test_task_runner_ =
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
shared_db_ = base::WrapRefCounted(new SharedProtoDatabase( shared_db_ = base::WrapRefCounted(new SharedProtoDatabase(
kDefaultClientName, shared_db_temp_dir_.GetPath())); kDefaultClientName, shared_db_temp_dir_.GetPath()));
test_task_runner_ = shared_db_->database_task_runner_for_testing();
} }
void TearDown() override { shared_db_->Shutdown(); } void TearDown() override { shared_db_->Shutdown(); }
...@@ -275,7 +284,10 @@ class ProtoDatabaseImplTest : public testing::Test { ...@@ -275,7 +284,10 @@ class ProtoDatabaseImplTest : public testing::Test {
scoped_refptr<ProtoDatabaseSelector> selector(new ProtoDatabaseSelector( scoped_refptr<ProtoDatabaseSelector> selector(new ProtoDatabaseSelector(
ProtoDbType::TEST_DATABASE1, GetTestThreadTaskRunner(), nullptr)); ProtoDbType::TEST_DATABASE1, GetTestThreadTaskRunner(), nullptr));
selector->OnGetSharedDBClient( GetTestThreadTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
&ProtoDatabaseSelector::OnGetSharedDBClient, selector,
std::move(unique_db), unique_db_status, use_shared_db, std::move(unique_db), unique_db_status, use_shared_db,
base::BindOnce( base::BindOnce(
[](base::OnceClosure closure, Enums::InitStatus expect_status, [](base::OnceClosure closure, Enums::InitStatus expect_status,
...@@ -284,7 +296,7 @@ class ProtoDatabaseImplTest : public testing::Test { ...@@ -284,7 +296,7 @@ class ProtoDatabaseImplTest : public testing::Test {
std::move(closure).Run(); std::move(closure).Run();
}, },
init_loop.QuitClosure(), expect_status), init_loop.QuitClosure(), expect_status),
std::move(shared_db_client), shared_db_status); std::move(shared_db_client), shared_db_status));
init_loop.Run(); init_loop.Run();
...@@ -522,6 +534,42 @@ TYPED_TEST(ProtoDatabaseImplTest, ...@@ -522,6 +534,42 @@ TYPED_TEST(ProtoDatabaseImplTest,
Enums::InitStatus::kOK); // Then the DB impl should use the shared DB. Enums::InitStatus::kOK); // Then the DB impl should use the shared DB.
} }
TYPED_TEST(ProtoDatabaseImplTest,
SucceedsWithShared_UseShared_HasSharedDB_MigratedUniqueWasDeleted) {
auto shared_db_client = this->GetSharedClient();
// Database has been migrated to Unique.
shared_db_client->set_migration_status(
SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SUCCESSFUL);
// If we request a shared DB, the unique DB fails does not exist and
// the data has been migrated to the unique DB then we return shared db.
this->CallOnGetSharedDBClientAndWait(
nullptr, // Unique DB fails to open.
Enums::InitStatus::kInvalidOperation, // Unique DB missing.
true, // We should be using a shared DB.
std::move(shared_db_client), // Shared DB opens fine.
Enums::InitStatus::kOK,
Enums::InitStatus::kOK); // Returns shared db.
shared_db_client = this->GetSharedClient();
// Data has been migrated to Unique, but data still exists in Shared DB that
// should be removed.
shared_db_client->set_migration_status(
SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SHARED_TO_BE_DELETED);
// This second scenario occurs when the Shared DB still contains data, we
// should still clear shared and return it.
this->CallOnGetSharedDBClientAndWait(
nullptr, // Unique DB fails to open.
Enums::InitStatus::kInvalidOperation, // Unique DB missing.
true, // We should be using a shared DB.
std::move(shared_db_client), // Shared DB opens fine.
Enums::InitStatus::kOK,
Enums::InitStatus::kOK); // Returns shared db
}
TYPED_TEST(ProtoDatabaseImplTest, TYPED_TEST(ProtoDatabaseImplTest,
Fails_UseShared_HasSharedDB_DataWasMigratedToUnique) { Fails_UseShared_HasSharedDB_DataWasMigratedToUnique) {
auto shared_db_client = this->GetSharedClient(); auto shared_db_client = this->GetSharedClient();
...@@ -535,7 +583,7 @@ TYPED_TEST(ProtoDatabaseImplTest, ...@@ -535,7 +583,7 @@ TYPED_TEST(ProtoDatabaseImplTest,
// unique database may contain data. // unique database may contain data.
this->CallOnGetSharedDBClientAndWait( this->CallOnGetSharedDBClientAndWait(
nullptr, // Unique DB fails to open. nullptr, // Unique DB fails to open.
Enums::InitStatus::kInvalidOperation, // Unique DB doesn't exist. Enums::InitStatus::kError, // Unique DB failure.
true, // We should be using a shared DB. true, // We should be using a shared DB.
std::move(shared_db_client), // Shared DB opens fine. std::move(shared_db_client), // Shared DB opens fine.
Enums::InitStatus::kOK, Enums::InitStatus::kOK,
......
...@@ -258,13 +258,24 @@ void ProtoDatabaseSelector::OnGetSharedDBClient( ...@@ -258,13 +258,24 @@ void ProtoDatabaseSelector::OnGetSharedDBClient(
break; break;
case SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SUCCESSFUL: case SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SUCCESSFUL:
case SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SHARED_TO_BE_DELETED: case SharedDBMetadataProto::MIGRATE_TO_UNIQUE_SHARED_TO_BE_DELETED:
if (unique_db_status == Enums::kInvalidOperation) {
// If unique db does not exist and migration state expects it, reset
// the migration state since this is not recoverable, and return the
// shared db. Clear the shared db since it might contain stale data.
SharedProtoDatabaseClient* client_ptr = client.get();
client_ptr->UpdateEntriesWithRemoveFilter(
std::make_unique<KeyValueVector>(),
base::BindRepeating([](const std::string& key) { return true; }),
base::BindOnce(&ProtoDatabaseSelector::
InvokeInitUniqueDbMissingSharedCleared,
this, std::move(client), std::move(callback)));
return;
}
// If the unique DB failed to open, and the data is located on it then // If the unique DB failed to open, and the data is located on it then
// we throw an error. We ignore the deletion flag because we want both // we throw an error.
// databases to be open before we delete the shared DB.
std::move(callback).Run(Enums::InitStatus::kError); std::move(callback).Run(Enums::InitStatus::kError);
OnInitDone(ProtoDatabaseInitState::kUniqueDbOpenFailed); OnInitDone(ProtoDatabaseInitState::kUniqueDbOpenFailed);
return; return;
break;
} }
} }
...@@ -604,6 +615,24 @@ void ProtoDatabaseSelector::RemoveKeysForTesting( ...@@ -604,6 +615,24 @@ void ProtoDatabaseSelector::RemoveKeysForTesting(
db_->RemoveKeysForTesting(key_filter, target_prefix, std::move(callback)); db_->RemoveKeysForTesting(key_filter, target_prefix, std::move(callback));
} }
void ProtoDatabaseSelector::InvokeInitUniqueDbMissingSharedCleared(
std::unique_ptr<SharedProtoDatabaseClient> client,
Callbacks::InitStatusCallback callback,
bool shared_cleared) {
if (!shared_cleared) {
OnInitDone(
ProtoDatabaseInitState::kFailureUniqueDbMissingClearSharedFailed);
std::move(callback).Run(Enums::InitStatus::kError);
return;
}
// Reset state to migrated to shared since unique db is missing.
client->UpdateClientInitMetadata(
SharedDBMetadataProto::MIGRATE_TO_SHARED_SUCCESSFUL);
db_ = std::move(client);
OnInitDone(ProtoDatabaseInitState::kUniqueDbMissingSharedReturned);
std::move(callback).Run(Enums::InitStatus::kOK);
}
void ProtoDatabaseSelector::OnInitDone( void ProtoDatabaseSelector::OnInitDone(
ProtoDatabaseSelector::ProtoDatabaseInitState state) { ProtoDatabaseSelector::ProtoDatabaseInitState state) {
RecordInitState(state); RecordInitState(state);
......
...@@ -61,7 +61,8 @@ class COMPONENT_EXPORT(LEVELDB_PROTO) ProtoDatabaseSelector ...@@ -61,7 +61,8 @@ class COMPONENT_EXPORT(LEVELDB_PROTO) ProtoDatabaseSelector
kSharedDbClientMissing = 25, kSharedDbClientMissing = 25,
kFailureNoSharedDBProviderUniqueFailed = 26, kFailureNoSharedDBProviderUniqueFailed = 26,
kSuccessNoSharedDBProviderUniqueSucceeded = 27, kSuccessNoSharedDBProviderUniqueSucceeded = 27,
kMaxValue = kSuccessNoSharedDBProviderUniqueSucceeded, kFailureUniqueDbMissingClearSharedFailed = 28,
kMaxValue = kFailureUniqueDbMissingClearSharedFailed,
}; };
static void RecordInitState(ProtoDatabaseInitState state); static void RecordInitState(ProtoDatabaseInitState state);
...@@ -185,6 +186,10 @@ class COMPONENT_EXPORT(LEVELDB_PROTO) ProtoDatabaseSelector ...@@ -185,6 +186,10 @@ class COMPONENT_EXPORT(LEVELDB_PROTO) ProtoDatabaseSelector
Callbacks::InitStatusCallback callback, Callbacks::InitStatusCallback callback,
bool success); bool success);
void OnInitDone(ProtoDatabaseInitState state); void OnInitDone(ProtoDatabaseInitState state);
void InvokeInitUniqueDbMissingSharedCleared(
std::unique_ptr<SharedProtoDatabaseClient> client,
Callbacks::InitStatusCallback,
bool shared_cleared);
ProtoDbType db_type_; ProtoDbType db_type_;
const scoped_refptr<base::SequencedTaskRunner> task_runner_; const scoped_refptr<base::SequencedTaskRunner> task_runner_;
......
...@@ -68,6 +68,7 @@ class COMPONENT_EXPORT(LEVELDB_PROTO) SharedProtoDatabase ...@@ -68,6 +68,7 @@ class COMPONENT_EXPORT(LEVELDB_PROTO) SharedProtoDatabase
friend class SharedProtoDatabaseTest; friend class SharedProtoDatabaseTest;
friend class SharedProtoDatabaseClientTest; friend class SharedProtoDatabaseClientTest;
friend class TestSharedProtoDatabase; friend class TestSharedProtoDatabase;
friend class TestSharedProtoDatabaseClient;
FRIEND_TEST_ALL_PREFIXES(SharedProtoDatabaseTest, FRIEND_TEST_ALL_PREFIXES(SharedProtoDatabaseTest,
CancelDeleteObsoleteClients); CancelDeleteObsoleteClients);
FRIEND_TEST_ALL_PREFIXES(SharedProtoDatabaseTest, DeleteObsoleteClients); FRIEND_TEST_ALL_PREFIXES(SharedProtoDatabaseTest, DeleteObsoleteClients);
......
...@@ -54496,6 +54496,7 @@ https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf ...@@ -54496,6 +54496,7 @@ https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf
label="Failed: No shared DB provider provided, unique DB failed"/> label="Failed: No shared DB provider provided, unique DB failed"/>
<int value="27" <int value="27"
label="Success: No shared DB provider provided, using unique"/> label="Success: No shared DB provider provided, using unique"/>
<int value="28" label="Failed: Unique DB missing, shared deletion failed"/>
</enum> </enum>
<enum name="ProvisionalLoadEvent"> <enum name="ProvisionalLoadEvent">
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment