// Copyright 2012 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 "sync/syncable/syncable_write_transaction.h"

#include "sync/syncable/directory.h"
#include "sync/syncable/directory_change_delegate.h"
#include "sync/syncable/mutable_entry.h"
#include "sync/syncable/transaction_observer.h"
#include "sync/syncable/write_transaction_info.h"

namespace syncer {
namespace syncable {

const int64 kInvalidTransactionVersion = -1;

WriteTransaction::WriteTransaction(const tracked_objects::Location& location,
                                   WriterTag writer, Directory* directory)
    : BaseWriteTransaction(location, "WriteTransaction", writer, directory),
      transaction_version_(NULL) {
  Lock();
}

WriteTransaction::WriteTransaction(const tracked_objects::Location& location,
                                   Directory* directory,
                                   int64* transaction_version)
    : BaseWriteTransaction(location, "WriteTransaction", SYNCAPI, directory),
      transaction_version_(transaction_version) {
  Lock();
  if (transaction_version_)
    *transaction_version_ = kInvalidTransactionVersion;
}

void WriteTransaction::TrackChangesTo(const EntryKernel* entry) {
  if (!entry) {
    return;
  }
  // Insert only if it's not already there.
  const int64 handle = entry->ref(META_HANDLE);
  EntryKernelMutationMap::iterator it = mutations_.lower_bound(handle);
  if (it == mutations_.end() || it->first != handle) {
    mutations_[handle].original = *entry;
  }
}

ImmutableEntryKernelMutationMap WriteTransaction::RecordMutations() {
  directory_->kernel_->transaction_mutex.AssertAcquired();
  for (syncable::EntryKernelMutationMap::iterator it = mutations_.begin();
       it != mutations_.end();) {
    EntryKernel* kernel = directory()->GetEntryByHandle(it->first);
    if (!kernel) {
      NOTREACHED();
      continue;
    }
    if (kernel->is_dirty()) {
      it->second.mutated = *kernel;
      ++it;
    } else {
      DCHECK(!it->second.original.is_dirty());
      // Not actually mutated, so erase from |mutations_|.
      mutations_.erase(it++);
    }
  }
  return ImmutableEntryKernelMutationMap(&mutations_);
}

void WriteTransaction::UnlockAndNotify(
    const ImmutableEntryKernelMutationMap& mutations) {
  // Work while transaction mutex is held.
  ModelTypeSet models_with_changes;
  bool has_mutations = !mutations.Get().empty();
  if (has_mutations) {
    models_with_changes = NotifyTransactionChangingAndEnding(mutations);
  }
  Unlock();

  // Work after mutex is relased.
  if (has_mutations) {
    NotifyTransactionComplete(models_with_changes);
  }
}

ModelTypeSet WriteTransaction::NotifyTransactionChangingAndEnding(
    const ImmutableEntryKernelMutationMap& mutations) {
  directory_->kernel_->transaction_mutex.AssertAcquired();
  DCHECK(!mutations.Get().empty());

  WriteTransactionInfo write_transaction_info(
      directory_->kernel_->next_write_transaction_id,
      from_here_, writer_, mutations);
  ++directory_->kernel_->next_write_transaction_id;

  ImmutableWriteTransactionInfo immutable_write_transaction_info(
      &write_transaction_info);
  DirectoryChangeDelegate* const delegate = directory_->kernel_->delegate;
  std::vector<int64> entry_changed;
  if (writer_ == syncable::SYNCAPI) {
    delegate->HandleCalculateChangesChangeEventFromSyncApi(
        immutable_write_transaction_info, this, &entry_changed);
  } else {
    delegate->HandleCalculateChangesChangeEventFromSyncer(
        immutable_write_transaction_info, this, &entry_changed);
  }
  UpdateTransactionVersion(entry_changed);

  ModelTypeSet models_with_changes =
      delegate->HandleTransactionEndingChangeEvent(
          immutable_write_transaction_info, this);

  directory_->kernel_->transaction_observer.Call(FROM_HERE,
      &TransactionObserver::OnTransactionWrite,
      immutable_write_transaction_info, models_with_changes);

  return models_with_changes;
}

void WriteTransaction::NotifyTransactionComplete(
    ModelTypeSet models_with_changes) {
  directory_->kernel_->delegate->HandleTransactionCompleteChangeEvent(
      models_with_changes);
}

void WriteTransaction::UpdateTransactionVersion(
    const std::vector<int64>& entry_changed) {
  syncer::ModelTypeSet type_seen;
  for (uint32 i = 0; i < entry_changed.size(); ++i) {
    MutableEntry entry(this, GET_BY_HANDLE, entry_changed[i]);
    if (entry.good()) {
      ModelType type = GetModelTypeFromSpecifics(entry.GetSpecifics());
      if (type < FIRST_REAL_MODEL_TYPE)
        continue;
      if (!type_seen.Has(type)) {
        directory_->IncrementTransactionVersion(type);
        type_seen.Put(type);
      }
      entry.UpdateTransactionVersion(directory_->GetTransactionVersion(type));
    }
  }

  if (!type_seen.Empty() && transaction_version_) {
    DCHECK_EQ(1u, type_seen.Size());
    *transaction_version_ = directory_->GetTransactionVersion(
        type_seen.First().Get());
  }
}

WriteTransaction::~WriteTransaction() {
  const ImmutableEntryKernelMutationMap& mutations = RecordMutations();

  MetahandleSet modified_handles;
  for (EntryKernelMutationMap::const_iterator i = mutations.Get().begin();
       i != mutations.Get().end(); ++i) {
    modified_handles.insert(i->first);
  }
  directory()->CheckInvariantsOnTransactionClose(this, modified_handles);

  // |CheckTreeInvariants| could have thrown an unrecoverable error.
  if (unrecoverable_error_set_) {
    HandleUnrecoverableErrorIfSet();
    Unlock();
    return;
  }

  UnlockAndNotify(mutations);
}

#define ENUM_CASE(x) case x: return #x; break

std::string WriterTagToString(WriterTag writer_tag) {
  switch (writer_tag) {
    ENUM_CASE(INVALID);
    ENUM_CASE(SYNCER);
    ENUM_CASE(AUTHWATCHER);
    ENUM_CASE(UNITTEST);
    ENUM_CASE(VACUUM_AFTER_SAVE);
    ENUM_CASE(HANDLE_SAVE_FAILURE);
    ENUM_CASE(PURGE_ENTRIES);
    ENUM_CASE(SYNCAPI);
  };
  NOTREACHED();
  return std::string();
}

#undef ENUM_CASE

}  // namespace syncable
}  // namespace syncer
