Skip to content

Commit

Permalink
[Feed] Implement commit Journal operations for Journal storage
Browse files Browse the repository at this point in the history
Implement commit Journal operations for Journal storage on C++ side.

Bug:879855

Change-Id: I8bf9d38571a4c83f7110be2d0043a8471171ba8c
Reviewed-on: https://chromium-review.googlesource.com/1200943
Commit-Queue: Gang Wu <[email protected]>
Reviewed-by: Filip Gorski <[email protected]>
Reviewed-by: Sky Malice <[email protected]>
Cr-Commit-Position: refs/heads/master@{#590106}
  • Loading branch information
Gang Wu authored and Commit Bot committed Sep 10, 2018
1 parent 2658ccb commit 6eca5f2
Show file tree
Hide file tree
Showing 10 changed files with 428 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void loadJournal(String journalName, Callback<String[]> callback) {
public void commitJournalMutation(JournalMutation mutation, Callback<Boolean> callback) {
assert mNativeFeedJournalBridge != 0;

nativeCreateJournalMutation(mNativeFeedJournalBridge, mutation.getJournalName());
nativeStartJournalMutation(mNativeFeedJournalBridge, mutation.getJournalName());
for (JournalOperation operation : mutation.getOperations()) {
switch (operation.getType()) {
case Type.APPEND:
Expand Down Expand Up @@ -110,7 +110,7 @@ private native void nativeLoadJournal(
long nativeFeedJournalBridge, String journalName, Callback<String[]> callback);
private native void nativeCommitJournalMutation(
long nativeFeedJournalBridge, Callback<Boolean> callback);
private native void nativeCreateJournalMutation(
private native void nativeStartJournalMutation(
long nativeFeedJournalBridge, String journalName);
private native void nativeDeleteJournalMutation(long nativeFeedJournalBridge);
private native void nativeAddAppendOperation(long nativeFeedJournalBridge, String value);
Expand Down
54 changes: 45 additions & 9 deletions chrome/browser/android/feed/feed_journal_bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "chrome/browser/profiles/profile_android.h"
#include "components/feed/content/feed_host_service.h"
#include "components/feed/core/feed_journal_database.h"
#include "components/feed/core/feed_journal_mutation.h"
#include "jni/FeedJournalBridge_jni.h"

namespace feed {
Expand Down Expand Up @@ -67,14 +68,21 @@ void FeedJournalBridge::LoadJournal(
ScopedJavaGlobalRef<jobject> callback(j_callback);

feed_journal_database_->LoadJournal(
journal_name, base::BindOnce(&FeedJournalBridge::OnLoadJournalDone,
weak_ptr_factory_.GetWeakPtr(), callback));
journal_name,
base::BindOnce(&FeedJournalBridge::OnLoadJournalDone, callback));
}

void FeedJournalBridge::CommitJournalMutation(
JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const base::android::JavaRef<jobject>& j_callback) {}
const base::android::JavaRef<jobject>& j_callback) {
DCHECK(journal_mutation_);
ScopedJavaGlobalRef<jobject> callback(j_callback);

feed_journal_database_->CommitJournalMutation(
std::move(journal_mutation_),
base::BindOnce(&FeedJournalBridge::OnStorageCommitDone, callback));
}

void FeedJournalBridge::DoesJournalExist(
JNIEnv* j_env,
Expand All @@ -92,29 +100,50 @@ void FeedJournalBridge::DeleteAllJournals(
const base::android::JavaRef<jobject>& j_this,
const base::android::JavaRef<jobject>& j_callback) {}

void FeedJournalBridge::CreateJournalMutation(
void FeedJournalBridge::StartJournalMutation(
JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const base::android::JavaRef<jstring>& j_journal_name) {}
const base::android::JavaRef<jstring>& j_journal_name) {
DCHECK(!journal_mutation_);
std::string journal_name = ConvertJavaStringToUTF8(j_env, j_journal_name);
journal_mutation_ =
std::make_unique<JournalMutation>(std::move(journal_name));
}

void FeedJournalBridge::DeleteJournalMutation(
JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this) {}
const base::android::JavaRef<jobject>& j_this) {
DCHECK(journal_mutation_);
journal_mutation_.reset();
}

void FeedJournalBridge::AddAppendOperation(
JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const base::android::JavaRef<jstring>& j_value) {}
const base::android::JavaRef<jstring>& j_value) {
DCHECK(journal_mutation_);
std::string value = ConvertJavaStringToUTF8(j_env, j_value);
journal_mutation_->AddAppendOperation(std::move(value));
}

void FeedJournalBridge::AddCopyOperation(
JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const base::android::JavaRef<jstring>& j_to_journal_name) {}
const base::android::JavaRef<jstring>& j_to_journal_name) {
DCHECK(journal_mutation_);
std::string to_journal_name =
ConvertJavaStringToUTF8(j_env, j_to_journal_name);
journal_mutation_->AddCopyOperation(std::move(to_journal_name));
}

void FeedJournalBridge::AddDeleteOperation(
JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this) {}
const base::android::JavaRef<jobject>& j_this) {
DCHECK(journal_mutation_);
journal_mutation_->AddDeleteOperation();
}

// static
void FeedJournalBridge::OnLoadJournalDone(
base::android::ScopedJavaGlobalRef<jobject> callback,
std::vector<std::string> entries) {
Expand All @@ -125,4 +154,11 @@ void FeedJournalBridge::OnLoadJournalDone(
RunObjectCallbackAndroid(callback, j_entries);
}

// static
void FeedJournalBridge::OnStorageCommitDone(
ScopedJavaGlobalRef<jobject> callback,
bool success) {
RunBooleanCallbackAndroid(callback, success);
}

} // namespace feed
20 changes: 17 additions & 3 deletions chrome/browser/android/feed/feed_journal_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_ANDROID_FEED_FEED_JOURNAL_BRIDGE_H_
#define CHROME_BROWSER_ANDROID_FEED_FEED_JOURNAL_BRIDGE_H_

#include <memory>
#include <string>
#include <vector>

Expand All @@ -14,6 +15,7 @@
namespace feed {

class FeedJournalDatabase;
class JournalMutation;

// Native counterpart of FeedJournalBridge.java. Holds non-owning pointers
// to native implementation to which operations are delegated. Results are
Expand All @@ -28,6 +30,7 @@ class FeedJournalBridge {

void Destroy(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this);

// Database related methods, they add/delete/update database.
void LoadJournal(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const base::android::JavaRef<jstring>& j_journal_name,
Expand All @@ -46,7 +49,9 @@ class FeedJournalBridge {
const base::android::JavaRef<jobject>& j_this,
const base::android::JavaRef<jobject>& j_callback);

void CreateJournalMutation(
// The following methods create/delete mutation, and add operations into
// mutation.
void StartJournalMutation(
JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const base::android::JavaRef<jstring>& j_journal_name);
Expand All @@ -63,8 +68,17 @@ class FeedJournalBridge {
const base::android::JavaRef<jobject>& j_this);

private:
void OnLoadJournalDone(base::android::ScopedJavaGlobalRef<jobject> callback,
std::vector<std::string> entries);
static void OnLoadJournalDone(
base::android::ScopedJavaGlobalRef<jobject> callback,
std::vector<std::string> entries);
static void OnStorageCommitDone(
base::android::ScopedJavaGlobalRef<jobject> callback,
bool success);

// This unique_ptr will hold a list of JournalOperations which are not
// committed yet. After send |journal_mutation_| to database, this unique_ptr
// will be reset.
std::unique_ptr<JournalMutation> journal_mutation_;

FeedJournalDatabase* feed_journal_database_;

Expand Down
2 changes: 2 additions & 0 deletions components/feed/core/feed_content_database.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "base/sys_info.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/feed/core/feed_content_mutation.h"
#include "components/feed/core/feed_content_operation.h"
#include "components/feed/core/proto/content_storage.pb.h"
#include "components/leveldb_proto/proto_database_impl.h"

Expand Down
4 changes: 2 additions & 2 deletions components/feed/core/feed_content_database.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@

#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
#include "components/feed/core/feed_content_mutation.h"
#include "components/feed/core/feed_content_operation.h"
#include "components/leveldb_proto/proto_database.h"

namespace feed {

class ContentMutation;
class ContentOperation;
class ContentStorageProto;

// FeedContentDatabase is leveldb backend store for Feed's content storage data.
Expand Down
141 changes: 134 additions & 7 deletions components/feed/core/feed_journal_database.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

#include "base/sys_info.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/feed/core/feed_journal_mutation.h"
#include "components/feed/core/feed_journal_operation.h"
#include "components/feed/core/proto/journal_storage.pb.h"
#include "components/leveldb_proto/proto_database_impl.h"

Expand Down Expand Up @@ -76,6 +79,108 @@ void FeedJournalDatabase::LoadJournal(const std::string& key,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void FeedJournalDatabase::CommitJournalMutation(
std::unique_ptr<JournalMutation> journal_mutation,
ConfirmationCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(journal_mutation);

if (journal_mutation->Empty()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), true));
return;
}

// Skip loading journal if the first operation is JOURNAL_DELETE.
if (journal_mutation->FirstOperationType() ==
JournalOperation::JOURNAL_DELETE) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&FeedJournalDatabase::PerformOperations,
weak_ptr_factory_.GetWeakPtr(), nullptr,
std::move(journal_mutation), std::move(callback)));
return;
}

std::string journal_name = journal_mutation->journal_name();
storage_database_->GetEntry(
journal_name,
base::BindOnce(&FeedJournalDatabase::OnGetEntryForCommitJournalMutation,
weak_ptr_factory_.GetWeakPtr(),
std::move(journal_mutation), std::move(callback)));
}

void FeedJournalDatabase::PerformOperations(
std::unique_ptr<JournalStorageProto> journal,
std::unique_ptr<JournalMutation> journal_mutation,
ConfirmationCallback callback) {
DCHECK(!journal_mutation->Empty());

if (journal) {
DCHECK_EQ(journal->key(), journal_mutation->journal_name());
} else {
journal = std::make_unique<JournalStorageProto>();
journal->set_key(journal_mutation->journal_name());
}

JournalMap copy_to_journal;
while (!journal_mutation->Empty()) {
JournalOperation operation = journal_mutation->TakeFristOperation();
switch (operation.type()) {
case JournalOperation::JOURNAL_APPEND:
journal->add_journal_data(operation.value());
break;
case JournalOperation::JOURNAL_COPY:
copy_to_journal[operation.to_journal_name()] =
CopyJouarnal(operation.to_journal_name(), *journal);
break;
case JournalOperation::JOURNAL_DELETE:
journal->clear_journal_data();
break;
}
}

CommitOperations(std::move(journal), std::move(copy_to_journal),
std::move(callback));
}

void FeedJournalDatabase::CommitOperations(
std::unique_ptr<JournalStorageProto> journal,
JournalMap copy_to_journal,
ConfirmationCallback callback) {
auto journals_to_save = std::make_unique<StorageEntryVector>();
auto journals_to_delete = std::make_unique<std::vector<std::string>>();

if (journal->journal_data_size() == 0) {
// This can only happens when the journal is deleted.
journals_to_delete->push_back(journal->key());
} else {
std::string journal_name = journal->key();
journals_to_save->emplace_back(journal_name, std::move(*journal));
}

for (JournalMap::iterator it = copy_to_journal.begin();
it != copy_to_journal.end(); ++it) {
journals_to_save->emplace_back(it->first, std::move(it->second));
}

storage_database_->UpdateEntries(
std::move(journals_to_save), std::move(journals_to_delete),
base::BindOnce(&FeedJournalDatabase::OnOperationCommitted,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void FeedJournalDatabase::OnDatabaseInitialized(bool success) {
DCHECK_EQ(database_status_, UNINITIALIZED);

if (success) {
database_status_ = INITIALIZED;
} else {
database_status_ = INIT_FAILURE;
DVLOG(1) << "FeedJournalDatabase init failed.";
}
}

void FeedJournalDatabase::OnGetEntryForLoadJournal(
JournalLoadCallback callback,
bool success,
Expand All @@ -95,15 +200,37 @@ void FeedJournalDatabase::OnGetEntryForLoadJournal(
std::move(callback).Run(std::move(results));
}

void FeedJournalDatabase::OnDatabaseInitialized(bool success) {
DCHECK_EQ(database_status_, UNINITIALIZED);
void FeedJournalDatabase::OnGetEntryForCommitJournalMutation(
std::unique_ptr<JournalMutation> journal_mutation,
ConfirmationCallback callback,
bool success,
std::unique_ptr<JournalStorageProto> journal) {
if (!success) {
DVLOG(1) << "FeedJournalDatabase load journal failed.";
std::move(callback).Run(success);
return;
}

if (success) {
database_status_ = INITIALIZED;
} else {
database_status_ = INIT_FAILURE;
DVLOG(1) << "FeedJournalDatabase init failed.";
PerformOperations(std::move(journal), std::move(journal_mutation),
std::move(callback));
}

void FeedJournalDatabase::OnOperationCommitted(ConfirmationCallback callback,
bool success) {
DVLOG_IF(1, !success) << "FeedJournalDatabase commit failed.";
std::move(callback).Run(success);
}

JournalStorageProto FeedJournalDatabase::CopyJouarnal(
const std::string& new_journal_name,
const JournalStorageProto& source_journal) {
JournalStorageProto new_journal;
new_journal.set_key(new_journal_name);
for (int i = 0; i < source_journal.journal_data_size(); ++i) {
new_journal.add_journal_data(source_journal.journal_data(i));
}

return new_journal;
}

} // namespace feed
Loading

0 comments on commit 6eca5f2

Please sign in to comment.