|
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 |
}
|