Blame source/uds/geometry.c

Packit Service 310c69
/*
Packit Service 310c69
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 310c69
 *
Packit Service 310c69
 * This program is free software; you can redistribute it and/or
Packit Service 310c69
 * modify it under the terms of the GNU General Public License
Packit Service 310c69
 * as published by the Free Software Foundation; either version 2
Packit Service 310c69
 * of the License, or (at your option) any later version.
Packit Service 310c69
 * 
Packit Service 310c69
 * This program is distributed in the hope that it will be useful,
Packit Service 310c69
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 310c69
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 310c69
 * GNU General Public License for more details.
Packit Service 310c69
 * 
Packit Service 310c69
 * You should have received a copy of the GNU General Public License
Packit Service 310c69
 * along with this program; if not, write to the Free Software
Packit Service 310c69
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 310c69
 * 02110-1301, USA. 
Packit Service 310c69
 *
Packit Service 310c69
 * $Id: //eng/uds-releases/jasper/src/uds/geometry.c#3 $
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
#include "geometry.h"
Packit Service 310c69
Packit Service 310c69
#include "deltaIndex.h"
Packit Service 310c69
#include "errors.h"
Packit Service 310c69
#include "hashUtils.h"
Packit Service 310c69
#include "logger.h"
Packit Service 310c69
#include "memoryAlloc.h"
Packit Service 310c69
#include "permassert.h"
Packit Service 310c69
#include "uds.h"
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
static int initializeGeometry(Geometry    *geometry,
Packit Service 310c69
                              size_t       bytesPerPage,
Packit Service 310c69
                              unsigned int recordPagesPerChapter,
Packit Service 310c69
                              unsigned int chaptersPerVolume,
Packit Service 310c69
                              unsigned int sparseChaptersPerVolume)
Packit Service 310c69
{
Packit Service 310c69
  int result = ASSERT_WITH_ERROR_CODE(bytesPerPage >= BYTES_PER_RECORD,
Packit Service 310c69
                                      UDS_BAD_STATE,
Packit Service 310c69
                                      "page is smaller than a record: %zu",
Packit Service 310c69
                                      bytesPerPage);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = ASSERT_WITH_ERROR_CODE(chaptersPerVolume > sparseChaptersPerVolume,
Packit Service 310c69
                                  UDS_INVALID_ARGUMENT,
Packit Service 310c69
                                  "sparse chapters per volume (%u) must be less"
Packit Service 310c69
                                  " than chapters per volume (%u)",
Packit Service 310c69
                                  sparseChaptersPerVolume,
Packit Service 310c69
                                  chaptersPerVolume);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  geometry->bytesPerPage            = bytesPerPage;
Packit Service 310c69
  geometry->recordPagesPerChapter   = recordPagesPerChapter;
Packit Service 310c69
  geometry->chaptersPerVolume       = chaptersPerVolume;
Packit Service 310c69
  geometry->sparseChaptersPerVolume = sparseChaptersPerVolume;
Packit Service 310c69
  geometry->denseChaptersPerVolume  =
Packit Service 310c69
    chaptersPerVolume - sparseChaptersPerVolume;
Packit Service 310c69
Packit Service 310c69
  // Calculate the number of records in a page, chapter, and volume.
Packit Service 310c69
  geometry->recordsPerPage = bytesPerPage / BYTES_PER_RECORD;
Packit Service 310c69
  geometry->recordsPerChapter
Packit Service 310c69
    = geometry->recordsPerPage * recordPagesPerChapter;
Packit Service 310c69
  geometry->recordsPerVolume
Packit Service 310c69
    = (unsigned long) geometry->recordsPerChapter * chaptersPerVolume;
Packit Service 310c69
  geometry->openChapterLoadRatio = DEFAULT_OPEN_CHAPTER_LOAD_RATIO;
Packit Service 310c69
Packit Service 310c69
  // Initialize values for delta chapter indexes.
Packit Service 310c69
  geometry->chapterMeanDelta     = 1 << DEFAULT_CHAPTER_MEAN_DELTA_BITS;
Packit Service 310c69
  geometry->chapterPayloadBits   = computeBits(recordPagesPerChapter - 1);
Packit Service 310c69
  // We want 1 delta list for every 64 records in the chapter.  The "| 077"
Packit Service 310c69
  // ensures that the chapterDeltaListBits computation does not underflow.
Packit Service 310c69
  geometry->chapterDeltaListBits
Packit Service 310c69
    = computeBits((geometry->recordsPerChapter - 1) | 077) - 6;
Packit Service 310c69
  geometry->deltaListsPerChapter = 1 << geometry->chapterDeltaListBits;
Packit Service 310c69
  // We need enough address bits to achieve the desired mean delta.
Packit Service 310c69
  geometry->chapterAddressBits
Packit Service 310c69
    = (DEFAULT_CHAPTER_MEAN_DELTA_BITS - geometry->chapterDeltaListBits
Packit Service 310c69
       + computeBits(geometry->recordsPerChapter - 1));
Packit Service 310c69
  // Let the delta index code determine how many pages are needed for the index
Packit Service 310c69
  geometry->indexPagesPerChapter
Packit Service 310c69
    = getDeltaIndexPageCount(geometry->recordsPerChapter,
Packit Service 310c69
                             geometry->deltaListsPerChapter,
Packit Service 310c69
                             geometry->chapterMeanDelta,
Packit Service 310c69
                             geometry->chapterPayloadBits,
Packit Service 310c69
                             bytesPerPage);
Packit Service 310c69
Packit Service 310c69
  // Now that we have the size of a chapter index, we can calculate the
Packit Service 310c69
  // space used by chapters and volumes.
Packit Service 310c69
  geometry->pagesPerChapter
Packit Service 310c69
    = geometry->indexPagesPerChapter + recordPagesPerChapter;
Packit Service 310c69
  geometry->pagesPerVolume  = geometry->pagesPerChapter * chaptersPerVolume;
Packit Service 310c69
  geometry->headerPagesPerVolume = 1;
Packit Service 310c69
  geometry->bytesPerVolume = bytesPerPage *
Packit Service 310c69
    (geometry->pagesPerVolume + geometry->headerPagesPerVolume);
Packit Service 310c69
  geometry->bytesPerChapter = bytesPerPage * geometry->pagesPerChapter;
Packit Service 310c69
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int makeGeometry(size_t       bytesPerPage,
Packit Service 310c69
                 unsigned int recordPagesPerChapter,
Packit Service 310c69
                 unsigned int chaptersPerVolume,
Packit Service 310c69
                 unsigned int sparseChaptersPerVolume,
Packit Service 310c69
                 Geometry   **geometryPtr)
Packit Service 310c69
{
Packit Service 310c69
  Geometry *geometry;
Packit Service 310c69
  int result = ALLOCATE(1, Geometry, "geometry", &geometry);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  result = initializeGeometry(geometry, bytesPerPage, recordPagesPerChapter,
Packit Service 310c69
                              chaptersPerVolume, sparseChaptersPerVolume);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    freeGeometry(geometry);
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  *geometryPtr = geometry;
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int copyGeometry(Geometry *source, Geometry **geometryPtr)
Packit Service 310c69
{
Packit Service 310c69
  return makeGeometry(source->bytesPerPage,
Packit Service 310c69
                      source->recordPagesPerChapter,
Packit Service 310c69
                      source->chaptersPerVolume,
Packit Service 310c69
                      source->sparseChaptersPerVolume,
Packit Service 310c69
                      geometryPtr);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void freeGeometry(Geometry *geometry)
Packit Service 310c69
{
Packit Service 310c69
  FREE(geometry);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
uint64_t mapToVirtualChapterNumber(Geometry     *geometry,
Packit Service 310c69
                                   uint64_t      newestVirtualChapter,
Packit Service 310c69
                                   unsigned int  physicalChapter)
Packit Service 310c69
{
Packit Service 310c69
  unsigned int newestPhysicalChapter
Packit Service 310c69
    = mapToPhysicalChapter(geometry, newestVirtualChapter);
Packit Service 310c69
  uint64_t virtualChapter
Packit Service 310c69
    = newestVirtualChapter - newestPhysicalChapter + physicalChapter;
Packit Service 310c69
  if (physicalChapter > newestPhysicalChapter) {
Packit Service 310c69
    virtualChapter -= geometry->chaptersPerVolume;
Packit Service 310c69
  }
Packit Service 310c69
  return virtualChapter;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool hasSparseChapters(const Geometry *geometry,
Packit Service 310c69
                       uint64_t        oldestVirtualChapter,
Packit Service 310c69
                       uint64_t        newestVirtualChapter)
Packit Service 310c69
{
Packit Service 310c69
  return (isSparse(geometry)
Packit Service 310c69
          && ((newestVirtualChapter - oldestVirtualChapter + 1)
Packit Service 310c69
              > geometry->denseChaptersPerVolume));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool isChapterSparse(const Geometry *geometry,
Packit Service 310c69
                     uint64_t        oldestVirtualChapter,
Packit Service 310c69
                     uint64_t        newestVirtualChapter,
Packit Service 310c69
                     uint64_t        virtualChapterNumber)
Packit Service 310c69
{
Packit Service 310c69
  return (hasSparseChapters(geometry, oldestVirtualChapter,
Packit Service 310c69
                            newestVirtualChapter)
Packit Service 310c69
          && ((virtualChapterNumber + geometry->denseChaptersPerVolume)
Packit Service 310c69
              <= newestVirtualChapter));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
bool areSamePhysicalChapter(const Geometry *geometry,
Packit Service 310c69
                            uint64_t        chapter1,
Packit Service 310c69
                            uint64_t        chapter2)
Packit Service 310c69
{
Packit Service 310c69
  return ((chapter1 % geometry->chaptersPerVolume)
Packit Service 310c69
          == (chapter2 % geometry->chaptersPerVolume));
Packit Service 310c69
}