/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_TRANSACTION_H_
#define ART_RUNTIME_TRANSACTION_H_

#include "base/macros.h"
#include "base/mutex.h"
#include "object_callbacks.h"
#include "offsets.h"
#include "primitive.h"
#include "safe_map.h"

#include <list>
#include <map>

namespace art {
namespace mirror {
class Array;
class Object;
class String;
}
class InternTable;

class Transaction {
 public:
  Transaction();
  ~Transaction();

  // Record object field changes.
  void RecordWriteField32(mirror::Object* obj, MemberOffset field_offset, uint32_t value,
                          bool is_volatile)
      LOCKS_EXCLUDED(log_lock_);
  void RecordWriteField64(mirror::Object* obj, MemberOffset field_offset, uint64_t value,
                          bool is_volatile)
      LOCKS_EXCLUDED(log_lock_);
  void RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset,
                                 mirror::Object* value, bool is_volatile)
      LOCKS_EXCLUDED(log_lock_);

  // Record array change.
  void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
      LOCKS_EXCLUDED(log_lock_)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  // Record intern string table changes.
  void RecordStrongStringInsertion(mirror::String* s, uint32_t hash_code)
      EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_)
      LOCKS_EXCLUDED(log_lock_);
  void RecordWeakStringInsertion(mirror::String* s, uint32_t hash_code)
      EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_)
      LOCKS_EXCLUDED(log_lock_);
  void RecordStrongStringRemoval(mirror::String* s, uint32_t hash_code)
      EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_)
      LOCKS_EXCLUDED(log_lock_);
  void RecordWeakStringRemoval(mirror::String* s, uint32_t hash_code)
      EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_)
      LOCKS_EXCLUDED(log_lock_);

  // Abort transaction by undoing all recorded changes.
  void Abort()
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
      LOCKS_EXCLUDED(log_lock_);

  void VisitRoots(RootCallback* callback, void* arg)
      LOCKS_EXCLUDED(log_lock_)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

 private:
  class ObjectLog {
   public:
    void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
    void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
    void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);

    void Undo(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
    void VisitRoots(RootCallback* callback, void* arg);

    size_t Size() const {
      return field_values_.size();
    }

   private:
    enum FieldValueKind {
      k32Bits,
      k64Bits,
      kReference
    };
    struct FieldValue {
      // TODO use JValue instead ?
      uint64_t value;
      FieldValueKind kind;
      bool is_volatile;
    };

    void UndoFieldWrite(mirror::Object* obj, MemberOffset field_offset,
                        const FieldValue& field_value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

    // Maps field's offset to its value.
    std::map<uint32_t, FieldValue> field_values_;
  };

  class ArrayLog {
   public:
    void LogValue(size_t index, uint64_t value);

    void Undo(mirror::Array* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

    size_t Size() const {
      return array_values_.size();
    }

   private:
    void UndoArrayWrite(mirror::Array* array, Primitive::Type array_type, size_t index,
                        uint64_t value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

    // Maps index to value.
    // TODO use JValue instead ?
    std::map<size_t, uint64_t> array_values_;
  };

  class InternStringLog {
   public:
    enum StringKind {
      kStrongString,
      kWeakString
    };
    enum StringOp {
      kInsert,
      kRemove
    };
    InternStringLog(mirror::String* s, uint32_t hash_code, StringKind kind, StringOp op)
      : str_(s), hash_code_(hash_code), string_kind_(kind), string_op_(op) {
      DCHECK(s != nullptr);
    }

    void Undo(InternTable* intern_table)
        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
        EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
    void VisitRoots(RootCallback* callback, void* arg);

   private:
    mirror::String* str_;
    uint32_t hash_code_;
    StringKind string_kind_;
    StringOp string_op_;
  };

  void LogInternedString(InternStringLog& log)
      EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_)
      LOCKS_EXCLUDED(log_lock_);

  void UndoObjectModifications()
      EXCLUSIVE_LOCKS_REQUIRED(log_lock_)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  void UndoArrayModifications()
      EXCLUSIVE_LOCKS_REQUIRED(log_lock_)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  void UndoInternStringTableModifications()
      EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_)
      EXCLUSIVE_LOCKS_REQUIRED(log_lock_)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  void VisitObjectLogs(RootCallback* callback, void* arg)
      EXCLUSIVE_LOCKS_REQUIRED(log_lock_)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  void VisitArrayLogs(RootCallback* callback, void* arg)
      EXCLUSIVE_LOCKS_REQUIRED(log_lock_)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  void VisitStringLogs(RootCallback* callback, void* arg)
      EXCLUSIVE_LOCKS_REQUIRED(log_lock_)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_);
  std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_);
  std::map<mirror::Array*, ArrayLog> array_logs_  GUARDED_BY(log_lock_);
  std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_);

  DISALLOW_COPY_AND_ASSIGN(Transaction);
};

}  // namespace art

#endif  // ART_RUNTIME_TRANSACTION_H_
