blob: 1a4a725d9c34212b42f2cabc4578bb71e45f3b09 [file] [log] [blame]
// 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