// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.
#pragma once

#include <atomic>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include "kudu/gutil/ref_counted.h"
#include "kudu/transactions/transactions.pb.h"
#include "kudu/util/cow_object.h"
#include "kudu/util/locks.h"
#include "kudu/util/monotime.h"

namespace kudu {
namespace transactions {

typedef std::pair<std::string, TxnParticipantEntryPB> ParticipantIdAndPB;

// Representations of entries in the transaction status table. Currently there
// are two entry types:
// - Transaction Entries: these indicate the existence of a transaction, and
//   encapsulate encapsulate metadata that pertain to the entire transactions
//   (e.g. owner, commit status, commit timestamp).
// - Participant Entries: these indicate the existence of a tablet that is
//   participating in a transaction.
//
// There is a 1:N relationship between transaction entries and participant
// entries. Represents the metadata persisted with a participant entry in the
// transaction status table.
struct PersistentParticipantEntry {
  TxnParticipantEntryPB pb;
};
class ParticipantEntry : public RefCountedThreadSafe<ParticipantEntry> {
 public:
  typedef PersistentParticipantEntry cow_state;

  ParticipantEntry() = default;
  const CowObject<PersistentParticipantEntry>& metadata() const { return metadata_; }
  CowObject<PersistentParticipantEntry>* mutable_metadata() { return &metadata_; }

 private:
  friend class RefCountedThreadSafe<ParticipantEntry>;
  ~ParticipantEntry() = default;

  // Mutable state for this participant with concurrent access controlled via
  // copy-on-write locking.
  CowObject<PersistentParticipantEntry> metadata_;
};

// Represents the metadata persisted with a status entry in the transaction
// status table.
struct PersistentTransactionEntry {
  TxnStatusEntryPB pb;
};
class TransactionEntry : public RefCountedThreadSafe<TransactionEntry> {
 public:
  typedef PersistentTransactionEntry cow_state;

  TransactionEntry(int64_t txn_id, std::string user);

  const CowObject<PersistentTransactionEntry>& metadata() const { return metadata_; }
  CowObject<PersistentTransactionEntry>* mutable_metadata() { return &metadata_; }

  // Adds a participant with the given tablet ID, or returns the one if it
  // already exists.
  scoped_refptr<ParticipantEntry> GetOrCreateParticipant(const std::string& tablet_id);

  // Returns the list of tablet IDs associated with this transaction.
  std::vector<std::string> GetParticipantIds() const;

  const std::string& user() const {
    return user_;
  }

  // Return the last recorded heartbeat timestamp for the transaction.
  MonoTime last_heartbeat_time() const {
    return last_heartbeat_time_.load();
  }
  // Set the timestamp of last seen keep-alive heartbeat for the transaction.
  void SetLastHeartbeatTime(const MonoTime& hbtime) {
    last_heartbeat_time_.store(hbtime);
  }

  // An accessor to the transaction's state. Concurrent access is controlled
  // via the locking provided by the underlying copy-on-write metadata_ object.
  TxnStatePB state() const;

 private:
  friend class RefCountedThreadSafe<TransactionEntry>;
  ~TransactionEntry() = default;

  const int64_t txn_id_;

  // While this is redundant with the field in the protobuf, it's convenient to
  // cache this so we don't have to lock this entry to get the user.
  const std::string user_;

  // Protects participants_. If adding a new participant, the entry should also
  // be locked in read mode and the transaction should be open.
  mutable simple_spinlock lock_;
  std::unordered_map<std::string, scoped_refptr<ParticipantEntry>> participants_;

  // Mutable state for the transaction status record with concurrent access
  // controlled via copy-on-write locking.
  CowObject<PersistentTransactionEntry> metadata_;

  // Time of the last keep-alive heartbeat received for the transaction
  // identified by txn_id_. Using std::atomic wrapper since the field can be
  // accessed concurrently by multiple threads:
  //   * the field can be updated by concurrent KeepAlive requests from
  //     different clients sending writes in the context of the same transaction
  //   * the field is read by the stale transaction tracker in TxnStatusManager
  std::atomic<MonoTime> last_heartbeat_time_;
};

typedef MetadataLock<TransactionEntry> TransactionEntryLock;
typedef MetadataLock<ParticipantEntry> ParticipantEntryLock;

} // namespace transactions
} // namespace kudu
