blob: f7b331ced63ec7a13d5f36bdf8b12aeedb3bda62 [file] [log] [blame]
// Copyright (C) 2019 Google LLC
//
// 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 ICING_FILE_POSTING_LIST_FLASH_INDEX_STORAGE_HEADER_H_
#define ICING_FILE_POSTING_LIST_FLASH_INDEX_STORAGE_HEADER_H_
#include <cstdint>
#include <memory>
#include "icing/text_classifier/lib3/utils/base/statusor.h"
#include "icing/absl_ports/canonical_errors.h"
#include "icing/file/filesystem.h"
namespace icing {
namespace lib {
// The class used to manage the flash block that contains the header for
// FlashIndexStorage. This contains information about the index blocks that
// store the posting lists.
class HeaderBlock {
public:
// The class used to access the actual header.
struct Header {
// A magic used to mark the beginning of a valid header.
static constexpr int kMagic = 0xd1b7b293;
int magic;
int block_size;
int last_indexed_docid;
// The size of the index_block_infos array.
int num_index_block_infos;
struct IndexBlockInfo {
// The size of the posting lists that fit on all the index blocks in this
// chain. Each block on this posting list will have posting lists of size
// posting_list_bytes.
int posting_list_bytes;
// The block index of the first block in the free list chain.
int free_list_block_index;
};
// Variable-size array, num_index_block_infos long. Can have a max length
// of log(block_size). This array is used to maintain a free list for the
// available blocks.
IndexBlockInfo index_block_infos[0];
};
// Read HeaderBlock from the specified fd.
//
// RETURNS:
// - HeaderBlock, on success
// - INTERNAL if unable to read block_size bytes from fd.
static libtextclassifier3::StatusOr<HeaderBlock> Read(
const Filesystem* filesystem, int fd, int block_size) {
std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(block_size);
if (!filesystem->PRead(fd, buffer.get(), block_size, 0)) {
return absl_ports::InternalError("Unable to reader header block!");
}
return HeaderBlock(filesystem, std::move(buffer), block_size);
}
// Make a new HeaderBlock with the specified size.
explicit HeaderBlock(const Filesystem* filesystem, int block_size)
: HeaderBlock(filesystem, std::make_unique<uint8_t[]>(block_size),
block_size) {
std::memset(header_buffer_.get(), 0, block_size);
}
Header* header() const {
return reinterpret_cast<Header*>(header_buffer_.get());
}
// Add another entry to the index_block_infos array and return a pointer to
// that entry. Returns a nullptr if the index_block_infos array is already
// at a max size.
Header::IndexBlockInfo* AddIndexBlockInfo() {
if (size() + sizeof(Header::IndexBlockInfo) > block_size_) {
return nullptr;
}
++header()->num_index_block_infos;
return header()->index_block_infos + (header()->num_index_block_infos - 1);
}
// Returns the size of the header block currently in use.
int size() const {
return sizeof(Header) +
header()->num_index_block_infos * sizeof(Header::IndexBlockInfo);
}
// Writes the header to fd. Returns true on success.
bool Write(int fd) {
return filesystem_->PWrite(fd, 0, header_buffer_.get(), block_size_);
}
private:
explicit HeaderBlock(const Filesystem* filesystem,
std::unique_ptr<uint8_t[]> buffer, int block_size)
: filesystem_(filesystem),
header_buffer_(std::move(buffer)),
block_size_(block_size) {}
const Filesystem* filesystem_; // does NOT own!
std::unique_ptr<uint8_t[]> header_buffer_;
int block_size_;
};
static_assert(16 == sizeof(HeaderBlock::Header),
"Header has changed size. Consider how this change might affect "
"pre-existing indices.");
} // namespace lib
} // namespace icing
#endif // ICING_FILE_POSTING_LIST_FLASH_INDEX_STORAGE_HEADER_H_