This source file includes following definitions.
- worker_
- GetDownloadProgress
- GetDataTypeContext
- ProcessGetUpdatesResponse
- ApplyUpdates
- PassiveApplyUpdates
- ApplyUpdatesImpl
- IsApplyUpdatesRequired
- UpdateSyncEntities
- IsValidProgressMarker
- UpdateProgressMarker
- ExpireEntriesIfNeeded
#include "sync/engine/directory_update_handler.h"
#include "sync/engine/conflict_resolver.h"
#include "sync/engine/process_updates_util.h"
#include "sync/engine/update_applicator.h"
#include "sync/sessions/status_controller.h"
#include "sync/syncable/directory.h"
#include "sync/syncable/syncable_model_neutral_write_transaction.h"
#include "sync/syncable/syncable_write_transaction.h"
namespace syncer {
using syncable::SYNCER;
DirectoryUpdateHandler::DirectoryUpdateHandler(
syncable::Directory* dir,
ModelType type,
scoped_refptr<ModelSafeWorker> worker)
: dir_(dir),
type_(type),
worker_(worker) {}
DirectoryUpdateHandler::~DirectoryUpdateHandler() {}
void DirectoryUpdateHandler::GetDownloadProgress(
sync_pb::DataTypeProgressMarker* progress_marker) const {
dir_->GetDownloadProgress(type_, progress_marker);
}
void DirectoryUpdateHandler::GetDataTypeContext(
sync_pb::DataTypeContext* context) const {
syncable::ModelNeutralWriteTransaction trans(FROM_HERE, SYNCER, dir_);
dir_->GetDataTypeContext(&trans, type_, context);
}
void DirectoryUpdateHandler::ProcessGetUpdatesResponse(
const sync_pb::DataTypeProgressMarker& progress_marker,
const sync_pb::DataTypeContext& mutated_context,
const SyncEntityList& applicable_updates,
sessions::StatusController* status) {
syncable::ModelNeutralWriteTransaction trans(FROM_HERE, SYNCER, dir_);
UpdateSyncEntities(&trans, applicable_updates, status);
if (IsValidProgressMarker(progress_marker)) {
ExpireEntriesIfNeeded(&trans, progress_marker);
UpdateProgressMarker(progress_marker);
}
if (mutated_context.has_context()) {
sync_pb::DataTypeContext local_context;
dir_->GetDataTypeContext(&trans, type_, &local_context);
if (mutated_context.version() >= local_context.version() &&
local_context.context() != mutated_context.context()) {
dir_->SetDataTypeContext(&trans, type_, mutated_context);
}
}
}
void DirectoryUpdateHandler::ApplyUpdates(sessions::StatusController* status) {
if (!IsApplyUpdatesRequired()) {
return;
}
WorkCallback c = base::Bind(
&DirectoryUpdateHandler::ApplyUpdatesImpl,
base::Unretained(this),
base::Unretained(status));
worker_->DoWorkAndWaitUntilDone(c);
}
void DirectoryUpdateHandler::PassiveApplyUpdates(
sessions::StatusController* status) {
if (!IsApplyUpdatesRequired()) {
return;
}
ApplyUpdatesImpl(status);
}
SyncerError DirectoryUpdateHandler::ApplyUpdatesImpl(
sessions::StatusController* status) {
syncable::WriteTransaction trans(FROM_HERE, syncable::SYNCER, dir_);
std::vector<int64> handles;
dir_->GetUnappliedUpdateMetaHandles(
&trans,
FullModelTypeSet(type_),
&handles);
UpdateApplicator applicator(dir_->GetCryptographer(&trans));
applicator.AttemptApplications(&trans, handles);
status->increment_num_updates_applied_by(applicator.updates_applied());
status->increment_num_hierarchy_conflicts_by(
applicator.hierarchy_conflicts());
status->increment_num_encryption_conflicts_by(
applicator.encryption_conflicts());
if (applicator.simple_conflict_ids().size() != 0) {
ConflictResolver resolver;
resolver.ResolveConflicts(&trans,
dir_->GetCryptographer(&trans),
applicator.simple_conflict_ids(),
status);
handles.clear();
dir_->GetUnappliedUpdateMetaHandles(
&trans,
FullModelTypeSet(type_),
&handles);
UpdateApplicator conflict_applicator(dir_->GetCryptographer(&trans));
conflict_applicator.AttemptApplications(&trans, handles);
status->increment_num_updates_applied_by(
conflict_applicator.updates_applied());
DCHECK_EQ(conflict_applicator.encryption_conflicts(),
applicator.encryption_conflicts());
DCHECK_EQ(conflict_applicator.hierarchy_conflicts(),
applicator.hierarchy_conflicts());
DCHECK(conflict_applicator.simple_conflict_ids().empty());
}
return SYNCER_OK;
}
bool DirectoryUpdateHandler::IsApplyUpdatesRequired() {
if (IsControlType(type_)) {
return false;
}
return dir_->TypeHasUnappliedUpdates(type_);
}
void DirectoryUpdateHandler::UpdateSyncEntities(
syncable::ModelNeutralWriteTransaction* trans,
const SyncEntityList& applicable_updates,
sessions::StatusController* status) {
ProcessDownloadedUpdates(dir_, trans, type_, applicable_updates, status);
}
bool DirectoryUpdateHandler::IsValidProgressMarker(
const sync_pb::DataTypeProgressMarker& progress_marker) const {
int field_number = progress_marker.data_type_id();
ModelType model_type = GetModelTypeFromSpecificsFieldNumber(field_number);
if (!IsRealDataType(model_type) || type_ != model_type) {
NOTREACHED()
<< "Update handler of type " << ModelTypeToString(type_)
<< " asked to process progress marker with invalid type "
<< field_number;
return false;
}
return true;
}
void DirectoryUpdateHandler::UpdateProgressMarker(
const sync_pb::DataTypeProgressMarker& progress_marker) {
if (progress_marker.has_gc_directive() || !cached_gc_directive_) {
dir_->SetDownloadProgress(type_, progress_marker);
} else {
sync_pb::DataTypeProgressMarker merged_marker = progress_marker;
merged_marker.mutable_gc_directive()->CopyFrom(*cached_gc_directive_);
dir_->SetDownloadProgress(type_, merged_marker);
}
}
void DirectoryUpdateHandler::ExpireEntriesIfNeeded(
syncable::ModelNeutralWriteTransaction* trans,
const sync_pb::DataTypeProgressMarker& progress_marker) {
if (!cached_gc_directive_) {
sync_pb::DataTypeProgressMarker current_marker;
GetDownloadProgress(¤t_marker);
if (current_marker.has_gc_directive()) {
cached_gc_directive_.reset(new sync_pb::GarbageCollectionDirective(
current_marker.gc_directive()));
}
}
if (!progress_marker.has_gc_directive())
return;
const sync_pb::GarbageCollectionDirective& new_gc_directive =
progress_marker.gc_directive();
if (new_gc_directive.has_version_watermark() &&
(!cached_gc_directive_ ||
cached_gc_directive_->version_watermark() <
new_gc_directive.version_watermark())) {
ExpireEntriesByVersion(dir_, trans, type_,
new_gc_directive.version_watermark());
}
cached_gc_directive_.reset(
new sync_pb::GarbageCollectionDirective(new_gc_directive));
}
}