// Copyright 2014 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 "components/sync/model_impl/processor_entity_tracker.h"

#include "base/base64.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/sha1.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/memory_usage_estimator.h"
#include "components/sync/base/sync_base_switches.h"
#include "components/sync/base/time.h"
#include "components/sync/engine/non_blocking_sync_common.h"
#include "components/sync/protocol/proto_memory_estimations.h"

namespace syncer {

namespace {

// Max number of sever version for which E2E latency is calculated.
// Used for E2E latency measurements with UMA.
const size_t kMaxTrackedCommittedServerVersions = 20;

void HashSpecifics(const sync_pb::EntitySpecifics& specifics,
                   std::string* hash) {
  DCHECK_GT(specifics.ByteSize(), 0);
  base::Base64Encode(base::SHA1HashString(specifics.SerializeAsString()), hash);
}

}  // namespace

std::unique_ptr<ProcessorEntityTracker> ProcessorEntityTracker::CreateNew(
    const std::string& storage_key,
    const std::string& client_tag_hash,
    const std::string& id,
    base::Time creation_time) {
  // Initialize metadata
  sync_pb::EntityMetadata metadata;
  metadata.set_client_tag_hash(client_tag_hash);
  if (!id.empty())
    metadata.set_server_id(id);
  metadata.set_sequence_number(0);
  metadata.set_acked_sequence_number(0);
  metadata.set_server_version(kUncommittedVersion);
  metadata.set_creation_time(TimeToProtoTime(creation_time));

  return std::unique_ptr<ProcessorEntityTracker>(
      new ProcessorEntityTracker(storage_key, &metadata));
}

std::unique_ptr<ProcessorEntityTracker>
ProcessorEntityTracker::CreateFromMetadata(const std::string& storage_key,
                                           sync_pb::EntityMetadata* metadata) {
  DCHECK(!storage_key.empty());
  return std::unique_ptr<ProcessorEntityTracker>(
      new ProcessorEntityTracker(storage_key, metadata));
}

ProcessorEntityTracker::ProcessorEntityTracker(
    const std::string& storage_key,
    sync_pb::EntityMetadata* metadata)
    : storage_key_(storage_key),
      commit_requested_sequence_number_(metadata->acked_sequence_number()) {
  DCHECK(metadata->has_client_tag_hash());
  DCHECK(metadata->has_creation_time());
  metadata_.Swap(metadata);
}

ProcessorEntityTracker::~ProcessorEntityTracker() {}

void ProcessorEntityTracker::SetStorageKey(const std::string& storage_key) {
  DCHECK(storage_key_.empty());
  DCHECK(!storage_key.empty());
  storage_key_ = storage_key;
}

void ProcessorEntityTracker::SetCommitData(EntityData* data) {
  DCHECK(data);
  // Update data's fields from metadata.
  data->client_tag_hash = metadata_.client_tag_hash();
  if (!metadata_.server_id().empty())
    data->id = metadata_.server_id();
  data->creation_time = ProtoTimeToTime(metadata_.creation_time());
  data->modification_time = ProtoTimeToTime(metadata_.modification_time());

  commit_data_.reset();
  CacheCommitData(data->PassToPtr());
}

void ProcessorEntityTracker::CacheCommitData(const EntityDataPtr& data_ptr) {
  DCHECK(RequiresCommitData());
  commit_data_ = data_ptr;
  DCHECK(HasCommitData());
}

bool ProcessorEntityTracker::HasCommitData() const {
  return !commit_data_->client_tag_hash.empty();
}

bool ProcessorEntityTracker::MatchesData(const EntityData& data) const {
  if (metadata_.is_deleted())
    return data.is_deleted();
  if (data.is_deleted())
    return false;
  return MatchesSpecificsHash(data.specifics);
}

bool ProcessorEntityTracker::MatchesBaseData(const EntityData& data) const {
  DCHECK(IsUnsynced());
  if (data.is_deleted() || metadata_.base_specifics_hash().empty()) {
    return false;
  }
  std::string hash;
  HashSpecifics(data.specifics, &hash);
  return hash == metadata_.base_specifics_hash();
}

bool ProcessorEntityTracker::IsUnsynced() const {
  return metadata_.sequence_number() > metadata_.acked_sequence_number();
}

bool ProcessorEntityTracker::RequiresCommitRequest() const {
  return metadata_.sequence_number() > commit_requested_sequence_number_;
}

bool ProcessorEntityTracker::RequiresCommitData() const {
  return RequiresCommitRequest() && !HasCommitData() && !metadata_.is_deleted();
}

bool ProcessorEntityTracker::CanClearMetadata() const {
  return metadata_.is_deleted() && !IsUnsynced();
}

bool ProcessorEntityTracker::UpdateIsReflection(int64_t update_version) const {
  return metadata_.server_version() >= update_version;
}

void ProcessorEntityTracker::RecordEntityUpdateLatency(int64_t update_version,
                                                       const ModelType& type) {
  auto first_greater =
      unsynced_time_per_committed_server_version_.upper_bound(update_version);
  if (first_greater == unsynced_time_per_committed_server_version_.begin()) {
    return;
  }

  DCHECK(base::FeatureList::IsEnabled(switches::kSyncE2ELatencyMeasurement));

  for (auto it = unsynced_time_per_committed_server_version_.begin();
       it != first_greater; ++it) {
    const base::TimeDelta latency = base::Time::Now() - it->second;
    base::UmaHistogramLongTimes(
        std::string("Sync.E2ELatency.") + ModelTypeToHistogramSuffix(type),
        latency);
  }

  unsynced_time_per_committed_server_version_.erase(
      unsynced_time_per_committed_server_version_.begin(), first_greater);
}

void ProcessorEntityTracker::RecordIgnoredUpdate(
    const UpdateResponseData& update) {
  DCHECK(metadata_.server_id().empty() ||
         metadata_.server_id() == update.entity->id);
  metadata_.set_server_id(update.entity->id);
  metadata_.set_server_version(update.response_version);
  // Either these already matched, acked was just bumped to squash a pending
  // commit and this should follow, or the pending commit needs to be requeued.
  commit_requested_sequence_number_ = metadata_.acked_sequence_number();
  // If local change was made while server assigned a new id to the entity,
  // update id in cached commit data.
  if (HasCommitData() && commit_data_->id != metadata_.server_id()) {
    DCHECK(commit_data_->id.empty());
    commit_data_ = commit_data_->UpdateId(metadata_.server_id());
  }
}

void ProcessorEntityTracker::RecordAcceptedUpdate(
    const UpdateResponseData& update) {
  DCHECK(!IsUnsynced());
  RecordIgnoredUpdate(update);
  metadata_.set_is_deleted(update.entity->is_deleted());
  metadata_.set_modification_time(
      TimeToProtoTime(update.entity->modification_time));
  UpdateSpecificsHash(update.entity->specifics);
}

void ProcessorEntityTracker::RecordForcedUpdate(
    const UpdateResponseData& update) {
  DCHECK(IsUnsynced());
  // There was a conflict and the server just won it. Explicitly ack all
  // pending commits so they are never enqueued again.
  metadata_.set_acked_sequence_number(metadata_.sequence_number());
  commit_data_.reset();
  RecordAcceptedUpdate(update);
}

void ProcessorEntityTracker::MakeLocalChange(std::unique_ptr<EntityData> data) {
  DCHECK(!metadata_.client_tag_hash().empty());

  // Update metadata fields from updated data.
  base::Time modification_time = !data->modification_time.is_null()
                                     ? data->modification_time
                                     : base::Time::Now();

  // IncrementSequenceNumber should be called before UpdateSpecificHash since
  // it remembers specifics hash before the modifications.
  IncrementSequenceNumber(modification_time);
  UpdateSpecificsHash(data->specifics);
  if (!data->creation_time.is_null())
    metadata_.set_creation_time(TimeToProtoTime(data->creation_time));
  metadata_.set_modification_time(TimeToProtoTime(modification_time));
  metadata_.set_is_deleted(false);

  // SetCommitData will update data's fields from metadata and wrap it into
  // immutable EntityDataPtr.
  SetCommitData(data.get());
}

bool ProcessorEntityTracker::Delete() {
  IncrementSequenceNumber(base::Time::Now());
  metadata_.set_modification_time(TimeToProtoTime(base::Time::Now()));
  metadata_.set_is_deleted(true);
  metadata_.clear_specifics_hash();
  // Clear any cached pending commit data.
  commit_data_.reset();
  // Return true if server might know about this entity.
  // TODO(crbug/740757): This check will prevent sending tombstone in situation
  // when it should have been sent under following conditions:
  //  - Original centity was committed to server, but client crashed before
  //    receiving response.
  //  - Entity was deleted while client was offline.
  // Correct behavior is to send tombstone anyway, but directory based
  // implementation doesn't and it is unclear how server will react to such
  // tombstones. Change the behavior to always sending tombstone after
  // experimenting with server.
  return (metadata_.server_version() != kUncommittedVersion) ||
         (commit_requested_sequence_number_ >
          metadata_.acked_sequence_number());
}

void ProcessorEntityTracker::InitializeCommitRequestData(
    CommitRequestData* request) {
  if (!metadata_.is_deleted()) {
    DCHECK(HasCommitData());
    DCHECK_EQ(commit_data_->client_tag_hash, metadata_.client_tag_hash());
    DCHECK_EQ(commit_data_->id, metadata_.server_id());
    request->entity = commit_data_;
  } else {
    // Make an EntityData with empty specifics to indicate deletion. This is
    // done lazily here to simplify loading a pending deletion on startup.
    EntityData data;
    data.client_tag_hash = metadata_.client_tag_hash();
    data.id = metadata_.server_id();
    data.creation_time = ProtoTimeToTime(metadata_.creation_time());
    data.modification_time = ProtoTimeToTime(metadata_.modification_time());
    request->entity = data.PassToPtr();
  }

  request->sequence_number = metadata_.sequence_number();
  request->base_version = metadata_.server_version();
  request->specifics_hash = metadata_.specifics_hash();
  request->unsynced_time = unsynced_time_;
  commit_requested_sequence_number_ = metadata_.sequence_number();
}

void ProcessorEntityTracker::ReceiveCommitResponse(
    const CommitResponseData& data,
    bool commit_only) {
  DCHECK_EQ(metadata_.client_tag_hash(), data.client_tag_hash);
  DCHECK_GT(data.sequence_number, metadata_.acked_sequence_number());
  // Version is not valid for commit only types, as it's stripped before being
  // sent to the server, so it cannot behave correctly.
  DCHECK(commit_only || data.response_version > metadata_.server_version())
      << data.response_version << " vs " << metadata_.server_version();

  if (base::FeatureList::IsEnabled(switches::kSyncE2ELatencyMeasurement) &&
      unsynced_time_per_committed_server_version_.size() <
          kMaxTrackedCommittedServerVersions) {
    unsynced_time_per_committed_server_version_[metadata_.server_version()] =
        data.unsynced_time;
  }

  // The server can assign us a new ID in a commit response.
  metadata_.set_server_id(data.id);
  metadata_.set_acked_sequence_number(data.sequence_number);
  metadata_.set_server_version(data.response_version);
  if (!IsUnsynced()) {
    // Clear pending commit data if there hasn't been another commit request
    // since the one that is currently getting acked.
    commit_data_.reset();
    metadata_.clear_base_specifics_hash();
  } else {
    metadata_.set_base_specifics_hash(data.specifics_hash);
    // If local change was made while server assigned a new id to the entity,
    // update id in cached commit data.
    if (HasCommitData() && commit_data_->id != metadata_.server_id()) {
      DCHECK(commit_data_->id.empty());
      commit_data_ = commit_data_->UpdateId(metadata_.server_id());
    }
  }
}

void ProcessorEntityTracker::ClearTransientSyncState() {
  // If we have any unacknowledged commit requests outstanding, they've been
  // dropped and we should forget about them.
  commit_requested_sequence_number_ = metadata_.acked_sequence_number();
}

void ProcessorEntityTracker::IncrementSequenceNumber(
    base::Time modification_time) {
  DCHECK(metadata_.has_sequence_number());
  if (!IsUnsynced()) {
    // Update the base specifics hash if this entity wasn't already out of sync.
    metadata_.set_base_specifics_hash(metadata_.specifics_hash());
    unsynced_time_ = modification_time;
  }
  metadata_.set_sequence_number(metadata_.sequence_number() + 1);
  DCHECK(IsUnsynced());
}

size_t ProcessorEntityTracker::EstimateMemoryUsage() const {
  using base::trace_event::EstimateMemoryUsage;
  size_t memory_usage = 0;
  memory_usage += EstimateMemoryUsage(storage_key_);
  memory_usage += EstimateMemoryUsage(metadata_);
  memory_usage += EstimateMemoryUsage(commit_data_);
  memory_usage +=
      EstimateMemoryUsage(unsynced_time_per_committed_server_version_);
  return memory_usage;
}

bool ProcessorEntityTracker::MatchesSpecificsHash(
    const sync_pb::EntitySpecifics& specifics) const {
  DCHECK(!metadata_.is_deleted());
  DCHECK_GT(specifics.ByteSize(), 0);
  std::string hash;
  HashSpecifics(specifics, &hash);
  return hash == metadata_.specifics_hash();
}

void ProcessorEntityTracker::UpdateSpecificsHash(
    const sync_pb::EntitySpecifics& specifics) {
  if (specifics.ByteSize() > 0) {
    HashSpecifics(specifics, metadata_.mutable_specifics_hash());
  } else {
    metadata_.clear_specifics_hash();
  }
}

}  // namespace syncer
