// Copyright 2013 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/engine_impl/get_commit_ids.h"

#include <set>

#include "base/macros.h"
#include "base/stl_util.h"
#include "components/sync/engine_impl/syncer_util.h"
#include "components/sync/nigori/cryptographer.h"
#include "components/sync/syncable/entry.h"
#include "components/sync/syncable/nigori_handler.h"
#include "components/sync/syncable/nigori_util.h"
#include "components/sync/syncable/syncable_base_transaction.h"
#include "components/sync/syncable/syncable_util.h"

namespace syncer {

using syncable::Directory;
using syncable::Entry;

namespace {

bool IsEntryInConflict(const Entry& entry) {
  if (entry.GetIsUnsynced() && entry.GetServerVersion() > 0 &&
      (entry.GetServerVersion() > entry.GetBaseVersion())) {
    // The local and server versions don't match. The item must be in
    // conflict, so there's no point in attempting to commit.
    DCHECK(entry.GetIsUnappliedUpdate());
    DVLOG(1) << "Excluding entry from commit due to version mismatch " << entry;
    return true;
  }
  return false;
}

// An entry may not commit if any are true:
// 1. It requires encryption (either the type is encrypted but a passphrase
//    is missing from the cryptographer, or the entry itself wasn't properly
//    encrypted).
// 2. It's type is currently throttled.
// 3. It's a delete but has not been committed.
bool MayEntryCommit(ModelTypeSet requested_types,
                    ModelTypeSet encrypted_types,
                    bool passphrase_missing,
                    const Entry& entry) {
  DCHECK(entry.GetIsUnsynced());

  const ModelType type = entry.GetModelType();
  // We special case the nigori node because even though it is considered an
  // "encrypted type", not all nigori node changes require valid encryption
  // (ex: sync_tabs).
  if ((type != NIGORI) && encrypted_types.Has(type) &&
      (passphrase_missing ||
       syncable::EntryNeedsEncryption(encrypted_types, entry))) {
    // This entry requires encryption but is not properly encrypted (possibly
    // due to the cryptographer not being initialized or the user hasn't
    // provided the most recent passphrase).
    DVLOG(1) << "Excluding entry from commit due to lack of encryption "
             << entry;
    return false;
  }

  // Ignore it if it's not in our set of requested types.
  if (!requested_types.Has(type))
    return false;

  if (entry.GetIsDel() && !entry.GetId().ServerKnows()) {
    // New clients (following the resolution of crbug.com/125381) should not
    // create such items. Old clients may have left some in the database
    // (crbug.com/132905), but we should now be cleaning them on startup.
    NOTREACHED() << "Found deleted and unsynced local item: " << entry;
    return false;
  }

  // Extra validity checks.
  syncable::Id id = entry.GetId();
  if (id == entry.GetParentId()) {
    DCHECK(id.IsRoot()) << "Non-root item is self parenting." << entry;
    // If the root becomes unsynced it can cause us problems.
    NOTREACHED() << "Root item became unsynced " << entry;
    return false;
  }

  if (entry.IsRoot()) {
    NOTREACHED() << "Permanent item became unsynced " << entry;
    return false;
  }

  DVLOG(2) << "Entry is ready for commit: " << entry;
  return true;
}

bool SupportsHierarchy(const Entry& item) {
  // Types with explicit server supported hierarchy only.
  return IsTypeWithServerGeneratedRoot(item.GetModelType());
}

// Iterates over children of items from |conflicted_items| list that are in
// |ready_unsynced_set|, excludes them from |ready_unsynced_set| and adds them
// to |excluded_items| list.
void ExcludeChildren(syncable::BaseTransaction* trans,
                     const std::vector<int64_t>& conflicted_items,
                     std::vector<int64_t>* excluded_items,
                     std::set<int64_t>* ready_unsynced_set) {
  for (const int64_t& handle : conflicted_items) {
    Entry entry(trans, syncable::GET_BY_HANDLE, handle);

    if (!entry.GetIsDir() || entry.GetIsDel())
      continue;

    std::vector<int64_t> children;
    entry.GetChildHandles(&children);

    for (const int64_t& child_handle : children) {
      // Collect all child handles that are in |ready_unsynced_set|.
      auto ready_iter = ready_unsynced_set->find(child_handle);
      if (ready_iter != ready_unsynced_set->end()) {
        // Remove this entry from |ready_unsynced_set| and add it
        // to |excluded_items|.
        ready_unsynced_set->erase(ready_iter);
        excluded_items->push_back(child_handle);
      }
    }
  }
}

// This class helps to implement OrderCommitIds(). Its members track the
// progress of a traversal while its methods extend it. It can return early if
// the traversal reaches the desired size before the full traversal is complete.
class Traversal {
 public:
  Traversal(syncable::BaseTransaction* trans,
            int64_t max_entries,
            Directory::Metahandles* out);
  ~Traversal();

  // First step of traversal building. Adds non-deleted items in order.
  void AddCreatesAndMoves(const std::set<int64_t>& ready_unsynced_set);

  // Second step of traverals building. Appends deleted items.
  void AddDeletes(const std::set<int64_t>& ready_unsynced_set);

 private:
  // The following functions do not modify the traversal directly. They return
  // their results in the |result| vector instead.
  bool TryAddUncommittedParents(const std::set<int64_t>& ready_unsynced_set,
                                const Entry& item,
                                Directory::Metahandles* result) const;

  bool TryAddItem(const std::set<int64_t>& ready_unsynced_set,
                  const Entry& item,
                  Directory::Metahandles* result) const;

  void AddDeletedParents(const std::set<int64_t>& ready_unsynced_set,
                         const Entry& item,
                         const Directory::Metahandles& traversed,
                         Directory::Metahandles* result) const;

  // Returns true if we've collected enough items.
  bool IsFull() const;

  // Returns true if the specified handle is already in the traversal.
  bool HaveItem(int64_t handle) const;

  // Adds the specified handles to the traversal.
  void AppendManyToTraversal(const Directory::Metahandles& handles);

  // Adds the specified handle to the traversal.
  void AppendToTraversal(int64_t handle);

  Directory::Metahandles* out_;
  std::set<int64_t> added_handles_;
  const size_t max_entries_;
  syncable::BaseTransaction* trans_;

  DISALLOW_COPY_AND_ASSIGN(Traversal);
};

Traversal::Traversal(syncable::BaseTransaction* trans,
                     int64_t max_entries,
                     Directory::Metahandles* out)
    : out_(out), max_entries_(max_entries), trans_(trans) {}

Traversal::~Traversal() {}

bool Traversal::TryAddUncommittedParents(
    const std::set<int64_t>& ready_unsynced_set,
    const Entry& item,
    Directory::Metahandles* result) const {
  DCHECK(SupportsHierarchy(item));
  Directory::Metahandles dependencies;
  syncable::Id parent_id = item.GetParentId();

  // Climb the tree adding entries leaf -> root.
  while (!parent_id.ServerKnows()) {
    Entry parent(trans_, syncable::GET_BY_ID, parent_id);

    // This apparently does happen, see crbug.com/711381. Someone is violating
    // some constraint and some ancestor isn't current present in the directory
    // while the child is. Because we do not know where this comes from, be
    // defensive and skip this inclusion instead.
    if (!parent.good()) {
      DVLOG(1) << "Bad user-only parent in item path with id " << parent_id;
      return false;
    }

    int64_t handle = parent.GetMetahandle();
    if (HaveItem(handle)) {
      // We've already added this parent (and therefore all of its parents).
      // We can return early.
      break;
    }

    if (!TryAddItem(ready_unsynced_set, parent, &dependencies)) {
      // The parent isn't in |ready_unsynced_set|.
      break;
    }

    parent_id = parent.GetParentId();
  }

  // Reverse what we added to get the correct order.
  result->insert(result->end(), dependencies.rbegin(), dependencies.rend());
  return true;
}

// Adds the given item to the list if it is unsynced and ready for commit.
bool Traversal::TryAddItem(const std::set<int64_t>& ready_unsynced_set,
                           const Entry& item,
                           Directory::Metahandles* result) const {
  DCHECK(item.GetIsUnsynced());
  int64_t item_handle = item.GetMetahandle();
  if (ready_unsynced_set.count(item_handle) != 0) {
    result->push_back(item_handle);
    return true;
  }
  return false;
}

// Traverses the tree from bottom to top, adding the deleted parents of the
// given |item|. Stops traversing if it encounters a non-deleted node, or
// a node that was already listed in the |traversed| list.
//
// The result list is reversed before it is returned, so the resulting
// traversal is in top to bottom order. Also note that this function appends
// to the result list without clearing it.
void Traversal::AddDeletedParents(const std::set<int64_t>& ready_unsynced_set,
                                  const Entry& item,
                                  const Directory::Metahandles& traversed,
                                  Directory::Metahandles* result) const {
  DCHECK(SupportsHierarchy(item));
  Directory::Metahandles dependencies;
  syncable::Id parent_id = item.GetParentId();

  // Climb the tree adding entries leaf -> root.
  while (!parent_id.IsRoot()) {
    Entry parent(trans_, syncable::GET_BY_ID, parent_id);

    if (!parent.good()) {
      // This is valid because the parent could have gone away a long time ago.
      //
      // Consider the case where a folder is server-unknown and locally
      // deleted, and has a child that is server-known, deleted, and unsynced.
      // The parent could be dropped from memory at any time, but its child
      // needs to be committed first.
      break;
    }
    int64_t handle = parent.GetMetahandle();
    if (!parent.GetIsUnsynced()) {
      // In some rare cases, our parent can be both deleted and unsynced.
      // (ie. the server-unknown parent case).
      break;
    }
    if (!parent.GetIsDel()) {
      // We're not interested in non-deleted parents.
      break;
    }
    if (base::Contains(traversed, handle)) {
      // We've already added this parent (and therefore all of its parents).
      // We can return early.
      break;
    }

    if (!TryAddItem(ready_unsynced_set, parent, &dependencies)) {
      // The parent isn't in ready_unsynced_set.
      break;
    }

    parent_id = parent.GetParentId();
  }

  // Reverse what we added to get the correct order.
  result->insert(result->end(), dependencies.rbegin(), dependencies.rend());
}

bool Traversal::IsFull() const {
  return out_->size() >= max_entries_;
}

bool Traversal::HaveItem(int64_t handle) const {
  return added_handles_.find(handle) != added_handles_.end();
}

void Traversal::AppendManyToTraversal(const Directory::Metahandles& handles) {
  out_->insert(out_->end(), handles.begin(), handles.end());
  added_handles_.insert(handles.begin(), handles.end());
}

void Traversal::AppendToTraversal(int64_t handle) {
  out_->push_back(handle);
  added_handles_.insert(handle);
}

void Traversal::AddCreatesAndMoves(
    const std::set<int64_t>& ready_unsynced_set) {
  // Add moves and creates, and prepend their uncommitted parents.
  for (const int64_t& handle : ready_unsynced_set) {
    if (IsFull()) {
      break;
    }
    if (HaveItem(handle))
      continue;

    Entry entry(trans_, syncable::GET_BY_HANDLE, handle);
    if (!entry.GetIsDel()) {
      if (SupportsHierarchy(entry)) {
        // We only commit an item + its dependencies if it and all its
        // dependencies are not in conflict.
        Directory::Metahandles item_dependencies;

        // If we fail to add a required parent, give up on this entry.
        if (!TryAddUncommittedParents(ready_unsynced_set, entry,
                                      &item_dependencies)) {
          continue;
        }

        // Okay if this fails, the parents were still valid.
        TryAddItem(ready_unsynced_set, entry, &item_dependencies);
        AppendManyToTraversal(item_dependencies);
      } else {
        // No hierarchy dependencies, just commit the item itself.
        AppendToTraversal(handle);
      }
    }
  }

  // It's possible that we over committed while trying to expand dependent
  // items. If so, truncate the set down to the allowed size. This is safe
  // because we've ordered such that ancestors come before children.
  if (out_->size() > max_entries_)
    out_->resize(max_entries_);
}

void Traversal::AddDeletes(const std::set<int64_t>& ready_unsynced_set) {
  Directory::Metahandles deletion_list;

  // Note: we iterate over all the unsynced set, regardless of the max size.
  // The max size is only enforced after the top-to-bottom order has been
  // reversed, in order to ensure children are always deleted before parents.
  // We cannot bail early when full because we need to guarantee that children
  // are always deleted before parents/ancestors.
  for (const int64_t& handle : ready_unsynced_set) {
    if (HaveItem(handle))
      continue;

    if (base::Contains(deletion_list, handle)) {
      continue;
    }

    Entry entry(trans_, syncable::GET_BY_HANDLE, handle);

    if (entry.GetIsDel()) {
      if (SupportsHierarchy(entry)) {
        Directory::Metahandles parents;
        AddDeletedParents(ready_unsynced_set, entry, deletion_list, &parents);
        // Append parents and children in top to bottom order.
        deletion_list.insert(deletion_list.end(), parents.begin(),
                             parents.end());
      }
      deletion_list.push_back(handle);
    }
  }

  // We've been gathering deletions in top to bottom order. Now we reverse the
  // order as we prepare the list.
  std::reverse(deletion_list.begin(), deletion_list.end());
  AppendManyToTraversal(deletion_list);

  // It's possible that we over committed while trying to expand dependent
  // items. If so, truncate the set down to the allowed size. This is safe
  // because of the reverse above, which should guarantee the leafy nodes are
  // in the front of the ancestors nodes.
  if (out_->size() > max_entries_)
    out_->resize(max_entries_);
}

// Excludes ancestors of deleted conflicted items from |ready_unsynced_set|.
void ExcludeDeletedAncestors(
    syncable::BaseTransaction* trans,
    const std::vector<int64_t>& deleted_conflicted_items,
    std::set<int64_t>* ready_unsynced_set) {
  for (const int64_t& deleted_conflicted_handle : deleted_conflicted_items) {
    Entry item(trans, syncable::GET_BY_HANDLE, deleted_conflicted_handle);
    syncable::Id parent_id = item.GetParentId();
    DCHECK(!parent_id.IsNull());

    while (!parent_id.IsRoot()) {
      Entry parent(trans, syncable::GET_BY_ID, parent_id);
      DCHECK(parent.good()) << "Bad user-only parent in item path.";
      int64_t handle = parent.GetMetahandle();

      if (!parent.GetIsDel())
        break;

      auto ready_iter = ready_unsynced_set->find(handle);
      if (ready_iter == ready_unsynced_set->end())
        break;

      // Remove this entry from |ready_unsynced_set|.
      ready_unsynced_set->erase(ready_iter);
      parent_id = parent.GetParentId();
    }
  }
}

// Filters |unsynced_handles| to remove all entries that do not belong to the
// specified |requested_types|, or are not eligible for a commit at this time.
void FilterUnreadyEntries(syncable::BaseTransaction* trans,
                          ModelTypeSet requested_types,
                          ModelTypeSet encrypted_types,
                          bool passphrase_missing,
                          const Directory::Metahandles& unsynced_handles,
                          std::set<int64_t>* ready_unsynced_set) {
  std::vector<int64_t> deleted_conflicted_items;
  std::vector<int64_t> conflicted_items;

  // Go over all unsynced handles, filter the ones that might be committed based
  // on type / encryption, then based on whether they are in conflict add them
  // to either |ready_unsynced_set| or one of the conflicted lists.
  for (const int64_t& handle : unsynced_handles) {
    Entry entry(trans, syncable::GET_BY_HANDLE, handle);
    // TODO(maniscalco): While we check if entry is ready to be committed, we
    // also need to check that all of its ancestors (parents, transitive) are
    // ready to be committed.
    if (MayEntryCommit(requested_types, encrypted_types, passphrase_missing,
                       entry)) {
      if (IsEntryInConflict(entry)) {
        // Conflicting hierarchical entries might prevent their ancestors or
        // descendants from being committed.
        if (SupportsHierarchy(entry)) {
          if (entry.GetIsDel()) {
            deleted_conflicted_items.push_back(handle);
          } else if (entry.GetIsDir()) {
            // Populate the initial version of |conflicted_items| with folder
            // items that are in conflict.
            conflicted_items.push_back(handle);
          }
        }
      } else {
        ready_unsynced_set->insert(handle);
      }
    }
  }

  // If there are any deleted conflicted entries, remove their deleted ancestors
  // from |ready_unsynced_set| as well.
  ExcludeDeletedAncestors(trans, deleted_conflicted_items, ready_unsynced_set);

  // Starting with conflicted_items containing conflicted folders go down and
  // exclude all descendants from |ready_unsynced_set|.
  while (!conflicted_items.empty()) {
    std::vector<int64_t> new_list;
    ExcludeChildren(trans, conflicted_items, &new_list, ready_unsynced_set);
    conflicted_items.swap(new_list);
  }
}

// Given a set of commit metahandles that are ready for commit
// (|ready_unsynced_set|), sorts these into commit order and places up to
// |max_entries| of them in the output parameter |out|.
//
// See the header file for an explanation of commit ordering.
void OrderCommitIds(syncable::BaseTransaction* trans,
                    size_t max_entries,
                    const std::set<int64_t>& ready_unsynced_set,
                    Directory::Metahandles* out) {
  // Commits follow these rules:
  // 1. Moves or creates are preceded by needed folder creates, from
  //    root to leaf.
  // 2. Moves/Creates before deletes.
  // 3. Deletes, collapsed.
  // We commit deleted moves under deleted items as moves when collapsing
  // delete trees.

  Traversal traversal(trans, max_entries, out);

  // Add moves and creates, and prepend their uncommitted parents.
  traversal.AddCreatesAndMoves(ready_unsynced_set);

  // Add all deletes.
  traversal.AddDeletes(ready_unsynced_set);
}

}  // namespace

void GetCommitIdsForType(syncable::BaseTransaction* trans,
                         ModelType type,
                         size_t max_entries,
                         Directory::Metahandles* out) {
  Directory* dir = trans->directory();

  // Gather the full set of unsynced items and store it in the cycle. They
  // are not in the correct order for commit.
  std::set<int64_t> ready_unsynced_set;
  Directory::Metahandles all_unsynced_handles;
  GetUnsyncedEntries(trans, &all_unsynced_handles);

  ModelTypeSet encrypted_types;
  bool passphrase_missing = false;
  const Cryptographer* cryptographer = dir->GetCryptographer(trans);
  if (cryptographer) {
    encrypted_types = dir->GetNigoriHandler()->GetEncryptedTypes(trans);
    passphrase_missing = cryptographer->has_pending_keys();
  }

  // We filter out all unready entries from the set of unsynced handles. This
  // new set of ready and unsynced items is then what we use to determine what
  // is a candidate for commit. The caller is responsible for ensuring that no
  // throttled types are included among the requested_types.
  FilterUnreadyEntries(trans, ModelTypeSet(type), encrypted_types,
                       passphrase_missing, all_unsynced_handles,
                       &ready_unsynced_set);

  OrderCommitIds(trans, max_entries, ready_unsynced_set, out);

  for (const int64_t& handle : *out) {
    DVLOG(1) << "Debug commit batch result:" << handle;
  }
}

}  // namespace syncer
