// 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 <cstdint>
#include <map>
#include <string>

#include "kudu/consensus/opid.pb.h"
#include "kudu/gutil/macros.h"
#include "kudu/gutil/ref_counted.h"
#include "kudu/util/locks.h"
#include "kudu/util/status.h"

namespace kudu {

class Env;
class FileCache;

namespace log {

// An entry in the index.
struct LogIndexEntry {
  consensus::OpId op_id;

  // The sequence number of the log segment which contains this entry.
  int64_t segment_sequence_number;

  // The offset within that log segment for the batch which contains this
  // entry. Note that the offset points to an entire batch which may contain
  // more than one replicate.
  int64_t offset_in_segment;

  std::string ToString() const;
};

// An on-disk structure which indexes from OpId index to the specific position
// in the WAL which contains the latest ReplicateMsg for that index.
//
// This structure is on-disk but *not durable* (i.e. it is never synced to
// disk). Its only purpose is to allow random-reading earlier entries from the
// log to serve to Raft followers.
//
// This class is thread-safe, but doesn't provide a memory barrier between
// writers and readers. In other words, if a reader is expected to see an index
// entry written by a writer, there should be some other synchronization between
// them to ensure visibility.
//
// See .cc file for implementation notes.
class LogIndex : public RefCountedThreadSafe<LogIndex> {
 public:
  LogIndex(Env* env, FileCache* file_cache, std::string base_dir);

  // Record an index entry in the index.
  Status AddEntry(const LogIndexEntry& entry);

  // Retrieve an existing entry from the index.
  // Returns NotFound() if the given log entry was never written.
  Status GetEntry(int64_t index, LogIndexEntry* entry);

  // Indicate that we no longer need to retain information about indexes lower than the
  // given index. Note that the implementation is conservative and _may_ choose to retain
  // earlier entries.
  void GC(int64_t min_index_to_retain);

 private:
  friend class RefCountedThreadSafe<LogIndex>;
  ~LogIndex();

  class IndexChunk;

  // Open the on-disk chunk with the given index.
  // Note: 'chunk_idx' is the index of the index chunk, not the index of a log _entry_.
  Status OpenChunk(int64_t chunk_idx, scoped_refptr<IndexChunk>* chunk);

  // Return the index chunk which contains the given log index.
  // If 'create' is true, creates it on-demand. If 'create' is false, and
  // the index chunk does not exist, returns NotFound.
  Status GetChunkForIndex(int64_t log_index, bool create,
                          scoped_refptr<IndexChunk>* chunk);

  // Return the path of the given index chunk.
  std::string GetChunkPath(int64_t chunk_idx);

  // Environment with which to do file I/O.
  Env* env_;

  // Optional cache thru which index files are opened.
  FileCache* file_cache_;

  // The base directory where index files are located.
  const std::string base_dir_;

  simple_spinlock open_chunks_lock_;

  // Map from chunk index to IndexChunk. The chunk index is the log index modulo
  // the number of entries per chunk (see docs in log_index.cc).
  // Protected by open_chunks_lock_
  typedef std::map<int64_t, scoped_refptr<IndexChunk>> ChunkMap;
  ChunkMap open_chunks_;

  DISALLOW_COPY_AND_ASSIGN(LogIndex);
};

} // namespace log
} // namespace kudu
