Blame source/uds/geometry.h

Packit b55c50
/*
Packit b55c50
 * Copyright (c) 2020 Red Hat, Inc.
Packit b55c50
 *
Packit b55c50
 * This program is free software; you can redistribute it and/or
Packit b55c50
 * modify it under the terms of the GNU General Public License
Packit b55c50
 * as published by the Free Software Foundation; either version 2
Packit b55c50
 * of the License, or (at your option) any later version.
Packit b55c50
 * 
Packit b55c50
 * This program is distributed in the hope that it will be useful,
Packit b55c50
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit b55c50
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit b55c50
 * GNU General Public License for more details.
Packit b55c50
 * 
Packit b55c50
 * You should have received a copy of the GNU General Public License
Packit b55c50
 * along with this program; if not, write to the Free Software
Packit b55c50
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit b55c50
 * 02110-1301, USA. 
Packit b55c50
 *
Packit b55c50
 * $Id: //eng/uds-releases/jasper/src/uds/geometry.h#3 $
Packit b55c50
 */
Packit b55c50
Packit b55c50
#ifndef GEOMETRY_H
Packit b55c50
#define GEOMETRY_H 1
Packit b55c50
Packit b55c50
#include "compiler.h"
Packit b55c50
#include "typeDefs.h"
Packit b55c50
#include "uds.h"
Packit b55c50
#include "uds-block.h"
Packit b55c50
Packit b55c50
/**
Packit b55c50
 * Geometry defines constants and a record that parameterize the layout of an
Packit b55c50
 * Albireo index volume.
Packit b55c50
 *
Packit b55c50
 * 

An index volume is divided into a fixed number of fixed-size

Packit b55c50
 * chapters, each consisting of a fixed number of fixed-size
Packit b55c50
 * pages. The volume layout is defined by two assumptions and four
Packit b55c50
 * parameters. The assumptions (constants) are that index records are
Packit b55c50
 * 64 bytes (32-byte block name plus 32-byte metadata) and that open
Packit b55c50
 * chapter index hash slots are one byte long. The four parameters are
Packit b55c50
 * the number of bytes in a page, the number of chapters in a volume,
Packit b55c50
 * the number of record pages in a chapter, and the number of chapters
Packit b55c50
 * that are sparse. From these parameters, we derive the rest of the
Packit b55c50
 * layout and derived properties, ranging from the number of pages in
Packit b55c50
 * a chapter to the number of records in the volume.
Packit b55c50
 *
Packit b55c50
 * 

The default geometry is 64 KByte pages, 1024 chapters, 256

Packit b55c50
 * record pages in a chapter, and zero sparse chapters. This will
Packit b55c50
 * allow us to store 2^28 entries (indexing 1TB of 4K blocks) in an
Packit b55c50
 * approximately 16.5 MByte volume using fourteen index pages in each
Packit b55c50
 * chapter.
Packit b55c50
 **/
Packit b55c50
typedef struct geometry {
Packit b55c50
  /** Length of a page in a chapter, in bytes */
Packit b55c50
  size_t bytesPerPage;
Packit b55c50
  /** Number of record pages in a chapter */
Packit b55c50
  unsigned int recordPagesPerChapter;
Packit b55c50
  /** Number of (total) chapters in a volume */
Packit b55c50
  unsigned int chaptersPerVolume;
Packit b55c50
  /** Number of sparsely-indexed chapters in a volume */
Packit b55c50
  unsigned int sparseChaptersPerVolume;
Packit b55c50
  /** Number of bits used to determine delta list numbers */
Packit b55c50
  unsigned int chapterDeltaListBits;
Packit b55c50
Packit b55c50
  // These are derived properties, expressed as fields for convenience.
Packit b55c50
  /** Total number of pages in a volume, excluding header */
Packit b55c50
  unsigned int pagesPerVolume;
Packit b55c50
  /** Total number of header pages per volume */
Packit b55c50
  unsigned int headerPagesPerVolume;
Packit b55c50
  /** Total number of bytes in a volume, including header */
Packit b55c50
  size_t bytesPerVolume;
Packit b55c50
  /** Total number of bytes in a chapter */
Packit b55c50
  size_t bytesPerChapter;
Packit b55c50
  /** Number of pages in a chapter */
Packit b55c50
  unsigned int pagesPerChapter;
Packit b55c50
  /** Number of index pages in a chapter index */
Packit b55c50
  unsigned int indexPagesPerChapter;
Packit b55c50
  /** The minimum ratio of hash slots to records in an open chapter */
Packit b55c50
  unsigned int openChapterLoadRatio;
Packit b55c50
  /** Number of records that fit on a page */
Packit b55c50
  unsigned int recordsPerPage;
Packit b55c50
  /** Number of records that fit in a chapter */
Packit b55c50
  unsigned int recordsPerChapter;
Packit b55c50
  /** Number of records that fit in a volume */
Packit b55c50
  uint64_t recordsPerVolume;
Packit b55c50
  /** Number of deltaLists per chapter index */
Packit b55c50
  unsigned int deltaListsPerChapter;
Packit b55c50
  /** Mean delta in chapter indexes */
Packit b55c50
  unsigned int chapterMeanDelta;
Packit b55c50
  /** Number of bits needed for record page numbers */
Packit b55c50
  unsigned int chapterPayloadBits;
Packit b55c50
  /** Number of bits used to compute addresses for chapter delta lists */
Packit b55c50
  unsigned int chapterAddressBits;
Packit b55c50
  /** Number of densely-indexed chapters in a volume */
Packit b55c50
  unsigned int denseChaptersPerVolume;
Packit b55c50
} Geometry;
Packit b55c50
Packit b55c50
enum {
Packit b55c50
  /* The number of bytes in a record (name + metadata) */
Packit b55c50
  BYTES_PER_RECORD = (UDS_CHUNK_NAME_SIZE + UDS_MAX_BLOCK_DATA_SIZE),
Packit b55c50
Packit b55c50
  /* The default length of a page in a chapter, in bytes */
Packit b55c50
  DEFAULT_BYTES_PER_PAGE = 1024 * BYTES_PER_RECORD,
Packit b55c50
Packit b55c50
  /* The default maximum number of records per page */
Packit b55c50
  DEFAULT_RECORDS_PER_PAGE = DEFAULT_BYTES_PER_PAGE / BYTES_PER_RECORD,
Packit b55c50
Packit b55c50
  /** The default number of record pages in a chapter */
Packit b55c50
  DEFAULT_RECORD_PAGES_PER_CHAPTER = 256,
Packit b55c50
Packit b55c50
  /** The default number of record pages in a chapter for a small index */
Packit b55c50
  SMALL_RECORD_PAGES_PER_CHAPTER = 64,
Packit b55c50
Packit b55c50
  /** The default number of chapters in a volume */
Packit b55c50
  DEFAULT_CHAPTERS_PER_VOLUME = 1024,
Packit b55c50
Packit b55c50
  /** The default number of sparsely-indexed chapters in a volume */
Packit b55c50
  DEFAULT_SPARSE_CHAPTERS_PER_VOLUME = 0,
Packit b55c50
Packit b55c50
  /** The log2 of the default mean delta */
Packit b55c50
  DEFAULT_CHAPTER_MEAN_DELTA_BITS = 16,
Packit b55c50
Packit b55c50
  /** The log2 of the number of delta lists in a large chapter */
Packit b55c50
  DEFAULT_CHAPTER_DELTA_LIST_BITS = 12,
Packit b55c50
Packit b55c50
  /** The log2 of the number of delta lists in a small chapter */
Packit b55c50
  SMALL_CHAPTER_DELTA_LIST_BITS = 10,
Packit b55c50
Packit b55c50
  /** The default min ratio of slots to records in an open chapter */
Packit b55c50
  DEFAULT_OPEN_CHAPTER_LOAD_RATIO = 2,
Packit b55c50
Packit b55c50
  /** Checkpoint every n chapters written.  Default is to not checkpoint */
Packit b55c50
  DEFAULT_CHECKPOINT_FREQUENCY = 0
Packit b55c50
};
Packit b55c50
Packit b55c50
/**
Packit b55c50
 * Allocate and initialize all fields of a volume geometry using the
Packit b55c50
 * specified layout parameters.
Packit b55c50
 *
Packit b55c50
 * @param bytesPerPage            The length of a page in a chapter, in bytes
Packit b55c50
 * @param recordPagesPerChapter   The number of pages in a chapter
Packit b55c50
 * @param chaptersPerVolume       The number of chapters in a volume
Packit b55c50
 * @param sparseChaptersPerVolume The number of sparse chapters in a volume
Packit b55c50
 * @param geometryPtr             A pointer to hold the new geometry
Packit b55c50
 *
Packit b55c50
 * @return UDS_SUCCESS or an error code
Packit b55c50
 **/
Packit b55c50
int makeGeometry(size_t       bytesPerPage,
Packit b55c50
                 unsigned int recordPagesPerChapter,
Packit b55c50
                 unsigned int chaptersPerVolume,
Packit b55c50
                 unsigned int sparseChaptersPerVolume,
Packit b55c50
                 Geometry   **geometryPtr)
Packit b55c50
  __attribute__((warn_unused_result));
Packit b55c50
Packit b55c50
/**
Packit b55c50
 * Allocate a new geometry and initialize it with the same parameters as an
Packit b55c50
 * existing geometry.
Packit b55c50
 *
Packit b55c50
 * @param source      The geometry record to copy
Packit b55c50
 * @param geometryPtr A pointer to hold the new geometry
Packit b55c50
 *
Packit b55c50
 * @return UDS_SUCCESS or an error code
Packit b55c50
 **/
Packit b55c50
int copyGeometry(Geometry  *source,
Packit b55c50
                 Geometry **geometryPtr)
Packit b55c50
  __attribute__((warn_unused_result));
Packit b55c50
Packit b55c50
/**
Packit b55c50
 * Clean up a geometry and its memory.
Packit b55c50
 *
Packit b55c50
 * @param geometry The geometry record to free
Packit b55c50
 **/
Packit b55c50
void freeGeometry(Geometry *geometry);
Packit b55c50
Packit b55c50
/**
Packit b55c50
 * Map a virtual chapter number to a physical chapter number
Packit b55c50
 *
Packit b55c50
 * @param geometry        The geometry
Packit b55c50
 * @param virtualChapter  The virtual chapter number
Packit b55c50
 *
Packit b55c50
 * @return the corresponding physical chapter number
Packit b55c50
 **/
Packit b55c50
__attribute__((warn_unused_result))
Packit b55c50
static INLINE unsigned int mapToPhysicalChapter(const Geometry *geometry,
Packit b55c50
                                                uint64_t virtualChapter)
Packit b55c50
{
Packit b55c50
  return (virtualChapter % geometry->chaptersPerVolume);
Packit b55c50
}
Packit b55c50
Packit b55c50
/**
Packit b55c50
 * Convert a physical chapter number to its current virtual chapter number.
Packit b55c50
 *
Packit b55c50
 * @param geometry             The geometry
Packit b55c50
 * @param newestVirtualChapter The number of the newest virtual chapter
Packit b55c50
 * @param physicalChapter      The physical chapter number to convert
Packit b55c50
 *
Packit b55c50
 * @return The current virtual chapter number of the physical chapter
Packit b55c50
 *         in question
Packit b55c50
 **/
Packit b55c50
uint64_t mapToVirtualChapterNumber(Geometry     *geometry,
Packit b55c50
                                   uint64_t      newestVirtualChapter,
Packit b55c50
                                   unsigned int  physicalChapter);
Packit b55c50
Packit b55c50
/**
Packit b55c50
 * Check whether this geometry is for a sparse index.
Packit b55c50
 *
Packit b55c50
 * @param geometry   The geometry to check
Packit b55c50
 *
Packit b55c50
 * @return true if this geometry has sparse chapters
Packit b55c50
 **/
Packit b55c50
__attribute__((warn_unused_result))
Packit b55c50
static INLINE bool isSparse(const Geometry *geometry)
Packit b55c50
{
Packit b55c50
  return (geometry->sparseChaptersPerVolume > 0);
Packit b55c50
}
Packit b55c50
Packit b55c50
/**
Packit b55c50
 * Check whether any sparse chapters have been filled.
Packit b55c50
 *
Packit b55c50
 * @param geometry             The geometry of the index
Packit b55c50
 * @param oldestVirtualChapter The number of the oldest chapter in the
Packit b55c50
 *                             index
Packit b55c50
 * @param newestVirtualChapter The number of the newest chapter in the
Packit b55c50
 *                             index
Packit b55c50
 *
Packit b55c50
 * @return true if the index has filled at least one sparse chapter
Packit b55c50
 **/
Packit b55c50
bool hasSparseChapters(const Geometry *geometry,
Packit b55c50
                       uint64_t        oldestVirtualChapter,
Packit b55c50
                       uint64_t        newestVirtualChapter)
Packit b55c50
  __attribute__((warn_unused_result));
Packit b55c50
Packit b55c50
/**
Packit b55c50
 * Check whether a chapter is sparse or dense.
Packit b55c50
 *
Packit b55c50
 * @param geometry             The geometry of the index containing the chapter
Packit b55c50
 * @param oldestVirtualChapter The number of the oldest chapter in the index
Packit b55c50
 * @param newestVirtualChapter The number of the newest chapter in the index
Packit b55c50
 * @param virtualChapterNumber The number of the chapter to check
Packit b55c50
 *
Packit b55c50
 * @return true if the chapter is sparse
Packit b55c50
 **/
Packit b55c50
bool isChapterSparse(const Geometry *geometry,
Packit b55c50
                     uint64_t        oldestVirtualChapter,
Packit b55c50
                     uint64_t        newestVirtualChapter,
Packit b55c50
                     uint64_t        virtualChapterNumber)
Packit b55c50
  __attribute__((warn_unused_result));
Packit b55c50
Packit b55c50
/**
Packit b55c50
 * Check whether two virtual chapter numbers correspond to the same
Packit b55c50
 * physical chapter.
Packit b55c50
 *
Packit b55c50
 * @param geometry The geometry of the index
Packit b55c50
 * @param chapter1 The first chapter to compare
Packit b55c50
 * @param chapter2 The second chapter to compare
Packit b55c50
 *
Packit b55c50
 * @return true if both chapters correspond to the same
Packit b55c50
 *         physical chapter
Packit b55c50
 **/
Packit b55c50
bool areSamePhysicalChapter(const Geometry *geometry,
Packit b55c50
                            uint64_t        chapter1,
Packit b55c50
                            uint64_t        chapter2)
Packit b55c50
  __attribute__((warn_unused_result));
Packit b55c50
Packit b55c50
#endif /* GEOMETRY_H */