|
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/deltaMemory.c#3 $
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
#include "deltaMemory.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "bits.h"
|
|
Packit Service |
310c69 |
#include "buffer.h"
|
|
Packit Service |
310c69 |
#include "compiler.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 "timeUtils.h"
|
|
Packit Service |
310c69 |
#include "typeDefs.h"
|
|
Packit Service |
310c69 |
#include "uds.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* The DeltaMemory structure manages the memory that stores delta lists.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* The "mutable" form of DeltaMemory is used for the master index and for
|
|
Packit Service |
310c69 |
* an open chapter index. The "immutable" form of DeltaMemory is used for
|
|
Packit Service |
310c69 |
* regular chapter indices.
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// This is the number of guard bits that are needed in the tail guard list
|
|
Packit Service |
310c69 |
enum { GUARD_BITS = POST_FIELD_GUARD_BYTES * CHAR_BIT };
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Get the offset of the first byte that a delta list bit stream resides in
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param deltaList The delta list
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the number byte offset
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE uint64_t getDeltaListByteStart(const DeltaList *deltaList)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return getDeltaListStart(deltaList) / CHAR_BIT;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Get the actual number of bytes that a delta list bit stream resides in
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param deltaList The delta list
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the number of bytes
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE uint16_t getDeltaListByteSize(const DeltaList *deltaList)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
uint16_t startBitOffset = getDeltaListStart(deltaList) % CHAR_BIT;
|
|
Packit Service |
310c69 |
uint16_t bitSize = getDeltaListSize(deltaList);
|
|
Packit Service |
310c69 |
return ((unsigned int) startBitOffset + bitSize + CHAR_BIT - 1) / CHAR_BIT;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Get the number of bytes in the delta lists headers.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param numLists The number of delta lists
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the number of bytes in the delta lists headers
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE size_t getSizeOfDeltaLists(unsigned int numLists)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return (numLists + 2) * sizeof(DeltaList);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Get the size of the flags array (in bytes)
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param numLists The number of delta lists
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the number of bytes for an array that has one bit per delta
|
|
Packit Service |
310c69 |
* list, plus the necessary guard bytes.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE size_t getSizeOfFlags(unsigned int numLists)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return (numLists + CHAR_BIT - 1) / CHAR_BIT + POST_FIELD_GUARD_BYTES;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Get the number of bytes of scratch memory for the delta lists.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param numLists The number of delta lists
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the number of bytes of scratch memory for the delta lists
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE size_t getSizeOfTempOffsets(unsigned int numLists)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return (numLists + 2) * sizeof(uint64_t);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Clear the transfers flags.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param deltaMemory The delta memory
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static void clearTransferFlags(DeltaMemory *deltaMemory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
memset(deltaMemory->flags, 0, getSizeOfFlags(deltaMemory->numLists));
|
|
Packit Service |
310c69 |
deltaMemory->numTransfers = 0;
|
|
Packit Service |
310c69 |
deltaMemory->transferStatus = UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Set the transfer flags for delta lists that are not empty, and count how
|
|
Packit Service |
310c69 |
* many there are.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param deltaMemory The delta memory
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static void flagNonEmptyDeltaLists(DeltaMemory *deltaMemory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
clearTransferFlags(deltaMemory);
|
|
Packit Service |
310c69 |
unsigned int i;
|
|
Packit Service |
310c69 |
for (i = 0; i < deltaMemory->numLists; i++) {
|
|
Packit Service |
310c69 |
if (getDeltaListSize(&deltaMemory->deltaLists[i + 1]) > 0) {
|
|
Packit Service |
310c69 |
setOne(deltaMemory->flags, i, 1);
|
|
Packit Service |
310c69 |
deltaMemory->numTransfers++;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void emptyDeltaLists(DeltaMemory *deltaMemory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// Zero all the delta list headers
|
|
Packit Service |
310c69 |
DeltaList *deltaLists = deltaMemory->deltaLists;
|
|
Packit Service |
310c69 |
memset(deltaLists, 0, getSizeOfDeltaLists(deltaMemory->numLists));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* Initialize delta lists to be empty. We keep 2 extra delta list
|
|
Packit Service |
310c69 |
* descriptors, one before the first real entry and one after so that we
|
|
Packit Service |
310c69 |
* don't need to bounds check the array access when calculating
|
|
Packit Service |
310c69 |
* preceeding and following gap sizes.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* Because the delta list headers were zeroed, the head guard list is
|
|
Packit Service |
310c69 |
* already at offset zero and size zero.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* The end guard list contains guard bytes so that the bit field
|
|
Packit Service |
310c69 |
* utilities can safely read past the end of any byte we are interested
|
|
Packit Service |
310c69 |
* in.
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
uint64_t numBits = (uint64_t) deltaMemory->size * CHAR_BIT;
|
|
Packit Service |
310c69 |
deltaLists[deltaMemory->numLists + 1].startOffset = numBits - GUARD_BITS;
|
|
Packit Service |
310c69 |
deltaLists[deltaMemory->numLists + 1].size = GUARD_BITS;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// Set all the bits in the end guard list. Do not use the bit field
|
|
Packit Service |
310c69 |
// utilities.
|
|
Packit Service |
310c69 |
memset(deltaMemory->memory + deltaMemory->size - POST_FIELD_GUARD_BYTES,
|
|
Packit Service |
310c69 |
~0, POST_FIELD_GUARD_BYTES);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// Evenly space out the real delta lists. The sizes are already zero, so
|
|
Packit Service |
310c69 |
// we just need to set the starting offsets.
|
|
Packit Service |
310c69 |
uint64_t spacing = (numBits - GUARD_BITS) / deltaMemory->numLists;
|
|
Packit Service |
310c69 |
uint64_t offset = spacing / 2;
|
|
Packit Service |
310c69 |
unsigned int i;
|
|
Packit Service |
310c69 |
for (i = 1; i <= deltaMemory->numLists; i++) {
|
|
Packit Service |
310c69 |
deltaLists[i].startOffset = offset;
|
|
Packit Service |
310c69 |
offset += spacing;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// Update the statistics
|
|
Packit Service |
310c69 |
deltaMemory->discardCount += deltaMemory->recordCount;
|
|
Packit Service |
310c69 |
deltaMemory->recordCount = 0;
|
|
Packit Service |
310c69 |
deltaMemory->collisionCount = 0;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Compute the Huffman coding parameters for the given mean delta
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param meanDelta The mean delta value
|
|
Packit Service |
310c69 |
* @param minBits The number of bits in the minimal key code
|
|
Packit Service |
310c69 |
* @param minKeys The number of keys used in a minimal code
|
|
Packit Service |
310c69 |
* @param incrKeys The number of keys used for another code bit
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static void computeCodingConstants(unsigned int meanDelta,
|
|
Packit Service |
310c69 |
unsigned short *minBits,
|
|
Packit Service |
310c69 |
unsigned int *minKeys,
|
|
Packit Service |
310c69 |
unsigned int *incrKeys)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// We want to compute the rounded value of log(2) * meanDelta. Since we
|
|
Packit Service |
310c69 |
// cannot always use floating point, use a really good integer approximation.
|
|
Packit Service |
310c69 |
*incrKeys = (836158UL * meanDelta + 603160UL) / 1206321UL;
|
|
Packit Service |
310c69 |
*minBits = computeBits(*incrKeys + 1);
|
|
Packit Service |
310c69 |
*minKeys = (1 << *minBits) - *incrKeys;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Rebalance a range of delta lists within memory.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param deltaMemory A delta memory structure
|
|
Packit Service |
310c69 |
* @param first The first delta list index
|
|
Packit Service |
310c69 |
* @param last The last delta list index
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static void rebalanceDeltaMemory(const DeltaMemory *deltaMemory,
|
|
Packit Service |
310c69 |
unsigned int first, unsigned int last)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (first == last) {
|
|
Packit Service |
310c69 |
DeltaList *deltaList = &deltaMemory->deltaLists[first];
|
|
Packit Service |
310c69 |
uint64_t newStart = deltaMemory->tempOffsets[first];
|
|
Packit Service |
310c69 |
// We need to move only one list, and we know it is safe to do so
|
|
Packit Service |
310c69 |
if (getDeltaListStart(deltaList) != newStart) {
|
|
Packit Service |
310c69 |
// Compute the first source byte
|
|
Packit Service |
310c69 |
uint64_t source = getDeltaListByteStart(deltaList);
|
|
Packit Service |
310c69 |
// Update the delta list location
|
|
Packit Service |
310c69 |
deltaList->startOffset = newStart;
|
|
Packit Service |
310c69 |
// Now use the same computation to locate the first destination byte
|
|
Packit Service |
310c69 |
uint64_t destination = getDeltaListByteStart(deltaList);
|
|
Packit Service |
310c69 |
memmove(deltaMemory->memory + destination, deltaMemory->memory + source,
|
|
Packit Service |
310c69 |
getDeltaListByteSize(deltaList));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
} else {
|
|
Packit Service |
310c69 |
// There is more than one list. Divide the problem in half, and use
|
|
Packit Service |
310c69 |
// recursive calls to process each half. Note that after this
|
|
Packit Service |
310c69 |
// computation, first <= middle, and middle < last.
|
|
Packit Service |
310c69 |
unsigned int middle = (first + last) / 2;
|
|
Packit Service |
310c69 |
const DeltaList *deltaList = &deltaMemory->deltaLists[middle];
|
|
Packit Service |
310c69 |
uint64_t newStart = deltaMemory->tempOffsets[middle];
|
|
Packit Service |
310c69 |
// The direction that our middle list is moving determines which half
|
|
Packit Service |
310c69 |
// of the problem must be processed first.
|
|
Packit Service |
310c69 |
if (newStart > getDeltaListStart(deltaList)) {
|
|
Packit Service |
310c69 |
rebalanceDeltaMemory(deltaMemory, middle + 1, last);
|
|
Packit Service |
310c69 |
rebalanceDeltaMemory(deltaMemory, first, middle);
|
|
Packit Service |
310c69 |
} else {
|
|
Packit Service |
310c69 |
rebalanceDeltaMemory(deltaMemory, first, middle);
|
|
Packit Service |
310c69 |
rebalanceDeltaMemory(deltaMemory, middle + 1, last);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int initializeDeltaMemory(DeltaMemory *deltaMemory, size_t size,
|
|
Packit Service |
310c69 |
unsigned int firstList, unsigned int numLists,
|
|
Packit Service |
310c69 |
unsigned int meanDelta, unsigned int numPayloadBits)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (numLists == 0) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(UDS_INVALID_ARGUMENT,
|
|
Packit Service |
310c69 |
"cannot initialize delta memory with 0 "
|
|
Packit Service |
310c69 |
"delta lists");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
byte *memory = NULL;
|
|
Packit Service |
310c69 |
int result = ALLOCATE(size, byte, "delta list", &memory);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
uint64_t *tempOffsets = NULL;
|
|
Packit Service |
310c69 |
result = ALLOCATE(numLists + 2, uint64_t, "delta list temp",
|
|
Packit Service |
310c69 |
&tempOffsets);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(memory);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
byte *flags = NULL;
|
|
Packit Service |
310c69 |
result = ALLOCATE(getSizeOfFlags(numLists), byte, "delta list flags",
|
|
Packit Service |
310c69 |
&flags);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
FREE(memory);
|
|
Packit Service |
310c69 |
FREE(tempOffsets);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
computeCodingConstants(meanDelta, &deltaMemory->minBits,
|
|
Packit Service |
310c69 |
&deltaMemory->minKeys, &deltaMemory->incrKeys);
|
|
Packit Service |
310c69 |
deltaMemory->valueBits = numPayloadBits;
|
|
Packit Service |
310c69 |
deltaMemory->memory = memory;
|
|
Packit Service |
310c69 |
deltaMemory->deltaLists = NULL;
|
|
Packit Service |
310c69 |
deltaMemory->tempOffsets = tempOffsets;
|
|
Packit Service |
310c69 |
deltaMemory->flags = flags;
|
|
Packit Service |
310c69 |
deltaMemory->bufferedWriter = NULL;
|
|
Packit Service |
310c69 |
deltaMemory->size = size;
|
|
Packit Service |
310c69 |
deltaMemory->rebalanceTime = 0;
|
|
Packit Service |
310c69 |
deltaMemory->rebalanceCount = 0;
|
|
Packit Service |
310c69 |
deltaMemory->recordCount = 0;
|
|
Packit Service |
310c69 |
deltaMemory->collisionCount = 0;
|
|
Packit Service |
310c69 |
deltaMemory->discardCount = 0;
|
|
Packit Service |
310c69 |
deltaMemory->overflowCount = 0;
|
|
Packit Service |
310c69 |
deltaMemory->firstList = firstList;
|
|
Packit Service |
310c69 |
deltaMemory->numLists = numLists;
|
|
Packit Service |
310c69 |
deltaMemory->numTransfers = 0;
|
|
Packit Service |
310c69 |
deltaMemory->transferStatus = UDS_SUCCESS;
|
|
Packit Service |
310c69 |
deltaMemory->tag = 'm';
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// Allocate the delta lists.
|
|
Packit Service |
310c69 |
result = ALLOCATE(deltaMemory->numLists + 2, DeltaList,
|
|
Packit Service |
310c69 |
"delta lists", &deltaMemory->deltaLists);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
uninitializeDeltaMemory(deltaMemory);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
emptyDeltaLists(deltaMemory);
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void uninitializeDeltaMemory(DeltaMemory *deltaMemory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
FREE(deltaMemory->flags);
|
|
Packit Service |
310c69 |
deltaMemory->flags = NULL;
|
|
Packit Service |
310c69 |
FREE(deltaMemory->tempOffsets);
|
|
Packit Service |
310c69 |
deltaMemory->tempOffsets = NULL;
|
|
Packit Service |
310c69 |
FREE(deltaMemory->deltaLists);
|
|
Packit Service |
310c69 |
deltaMemory->deltaLists = NULL;
|
|
Packit Service |
310c69 |
FREE(deltaMemory->memory);
|
|
Packit Service |
310c69 |
deltaMemory->memory = NULL;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void initializeDeltaMemoryPage(DeltaMemory *deltaMemory, byte *memory,
|
|
Packit Service |
310c69 |
size_t size, unsigned int numLists,
|
|
Packit Service |
310c69 |
unsigned int meanDelta,
|
|
Packit Service |
310c69 |
unsigned int numPayloadBits)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
computeCodingConstants(meanDelta, &deltaMemory->minBits,
|
|
Packit Service |
310c69 |
&deltaMemory->minKeys, &deltaMemory->incrKeys);
|
|
Packit Service |
310c69 |
deltaMemory->valueBits = numPayloadBits;
|
|
Packit Service |
310c69 |
deltaMemory->memory = memory;
|
|
Packit Service |
310c69 |
deltaMemory->deltaLists = NULL;
|
|
Packit Service |
310c69 |
deltaMemory->tempOffsets = NULL;
|
|
Packit Service |
310c69 |
deltaMemory->flags = NULL;
|
|
Packit Service |
310c69 |
deltaMemory->bufferedWriter = NULL;
|
|
Packit Service |
310c69 |
deltaMemory->size = size;
|
|
Packit Service |
310c69 |
deltaMemory->rebalanceTime = 0;
|
|
Packit Service |
310c69 |
deltaMemory->rebalanceCount = 0;
|
|
Packit Service |
310c69 |
deltaMemory->recordCount = 0;
|
|
Packit Service |
310c69 |
deltaMemory->collisionCount = 0;
|
|
Packit Service |
310c69 |
deltaMemory->discardCount = 0;
|
|
Packit Service |
310c69 |
deltaMemory->overflowCount = 0;
|
|
Packit Service |
310c69 |
deltaMemory->firstList = 0;
|
|
Packit Service |
310c69 |
deltaMemory->numLists = numLists;
|
|
Packit Service |
310c69 |
deltaMemory->numTransfers = 0;
|
|
Packit Service |
310c69 |
deltaMemory->transferStatus = UDS_SUCCESS;
|
|
Packit Service |
310c69 |
deltaMemory->tag = 'p';
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
bool areDeltaMemoryTransfersDone(const DeltaMemory *deltaMemory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return deltaMemory->numTransfers == 0;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int startRestoringDeltaMemory(DeltaMemory *deltaMemory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// Extend and balance memory to receive the delta lists
|
|
Packit Service |
310c69 |
int result = extendDeltaMemory(deltaMemory, 0, 0, false);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// The tail guard list needs to be set to ones
|
|
Packit Service |
310c69 |
DeltaList *deltaList = &deltaMemory->deltaLists[deltaMemory->numLists + 1];
|
|
Packit Service |
310c69 |
setOne(deltaMemory->memory, getDeltaListStart(deltaList),
|
|
Packit Service |
310c69 |
getDeltaListSize(deltaList));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
flagNonEmptyDeltaLists(deltaMemory);
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int readDeltaListSaveInfo(BufferedReader *reader,
|
|
Packit Service |
310c69 |
DeltaListSaveInfo *dlsi)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
byte buffer[sizeof(DeltaListSaveInfo)];
|
|
Packit Service |
310c69 |
int result = readFromBufferedReader(reader, buffer, sizeof(buffer));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
dlsi->tag = buffer[0];
|
|
Packit Service |
310c69 |
dlsi->bitOffset = buffer[1];
|
|
Packit Service |
310c69 |
dlsi->byteCount = getUInt16LE(&buffer[2]);
|
|
Packit Service |
310c69 |
dlsi->index = getUInt32LE(&buffer[4]);
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int readSavedDeltaList(DeltaListSaveInfo *dlsi,
|
|
Packit Service |
310c69 |
byte data[DELTA_LIST_MAX_BYTE_COUNT],
|
|
Packit Service |
310c69 |
BufferedReader *bufferedReader)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
int result = readDeltaListSaveInfo(bufferedReader, dlsi);
|
|
Packit Service |
310c69 |
if (result == UDS_END_OF_FILE) {
|
|
Packit Service |
310c69 |
return UDS_END_OF_FILE;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(result, "failed to read delta list data");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if ((dlsi->bitOffset >= CHAR_BIT)
|
|
Packit Service |
310c69 |
|| (dlsi->byteCount > DELTA_LIST_MAX_BYTE_COUNT)) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"corrupt delta list data");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (dlsi->tag == 'z') {
|
|
Packit Service |
310c69 |
return UDS_END_OF_FILE;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = readFromBufferedReader(bufferedReader, data, dlsi->byteCount);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(result, "failed to read delta list data");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int restoreDeltaList(DeltaMemory *deltaMemory, const DeltaListSaveInfo *dlsi,
|
|
Packit Service |
310c69 |
const byte data[DELTA_LIST_MAX_BYTE_COUNT])
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
unsigned int listNumber = dlsi->index - deltaMemory->firstList;
|
|
Packit Service |
310c69 |
if (listNumber >= deltaMemory->numLists) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"invalid delta list number %u not in"
|
|
Packit Service |
310c69 |
" range [%u,%u)",
|
|
Packit Service |
310c69 |
dlsi->index, deltaMemory->firstList,
|
|
Packit Service |
310c69 |
deltaMemory->firstList
|
|
Packit Service |
310c69 |
+ deltaMemory->numLists);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (getField(deltaMemory->flags, listNumber, 1) == 0) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"unexpected delta list number %u",
|
|
Packit Service |
310c69 |
dlsi->index);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
DeltaList *deltaList = &deltaMemory->deltaLists[listNumber + 1];
|
|
Packit Service |
310c69 |
uint16_t bitSize = getDeltaListSize(deltaList);
|
|
Packit Service |
310c69 |
unsigned int byteCount
|
|
Packit Service |
310c69 |
= ((unsigned int) dlsi->bitOffset + bitSize + CHAR_BIT - 1) / CHAR_BIT;
|
|
Packit Service |
310c69 |
if (dlsi->byteCount != byteCount) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(UDS_CORRUPT_COMPONENT,
|
|
Packit Service |
310c69 |
"unexpected delta list size %u != %u",
|
|
Packit Service |
310c69 |
dlsi->byteCount, byteCount);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
moveBits(data, dlsi->bitOffset, deltaMemory->memory,
|
|
Packit Service |
310c69 |
getDeltaListStart(deltaList), bitSize);
|
|
Packit Service |
310c69 |
setZero(deltaMemory->flags, listNumber, 1);
|
|
Packit Service |
310c69 |
deltaMemory->numTransfers--;
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void abortRestoringDeltaMemory(DeltaMemory *deltaMemory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
clearTransferFlags(deltaMemory);
|
|
Packit Service |
310c69 |
emptyDeltaLists(deltaMemory);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void startSavingDeltaMemory(DeltaMemory *deltaMemory,
|
|
Packit Service |
310c69 |
BufferedWriter *bufferedWriter)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
flagNonEmptyDeltaLists(deltaMemory);
|
|
Packit Service |
310c69 |
deltaMemory->bufferedWriter = bufferedWriter;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int finishSavingDeltaMemory(DeltaMemory *deltaMemory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
unsigned int i;
|
|
Packit Service |
310c69 |
for (i = 0;
|
|
Packit Service |
310c69 |
!areDeltaMemoryTransfersDone(deltaMemory)
|
|
Packit Service |
310c69 |
&& (i < deltaMemory->numLists);
|
|
Packit Service |
310c69 |
i++) {
|
|
Packit Service |
310c69 |
lazyFlushDeltaList(deltaMemory, i);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (deltaMemory->numTransfers > 0) {
|
|
Packit Service |
310c69 |
deltaMemory->transferStatus
|
|
Packit Service |
310c69 |
= logWarningWithStringError(UDS_CORRUPT_DATA,
|
|
Packit Service |
310c69 |
"Not all delta lists written");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
deltaMemory->bufferedWriter = NULL;
|
|
Packit Service |
310c69 |
return deltaMemory->transferStatus;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void abortSavingDeltaMemory(DeltaMemory *deltaMemory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
clearTransferFlags(deltaMemory);
|
|
Packit Service |
310c69 |
deltaMemory->bufferedWriter = NULL;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result))
|
|
Packit Service |
310c69 |
static int writeDeltaListSaveInfo(BufferedWriter *bufferedWriter,
|
|
Packit Service |
310c69 |
DeltaListSaveInfo *dlsi)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
byte buffer[sizeof(DeltaListSaveInfo)];
|
|
Packit Service |
310c69 |
buffer[0] = dlsi->tag;
|
|
Packit Service |
310c69 |
buffer[1] = dlsi->bitOffset;
|
|
Packit Service |
310c69 |
storeUInt16LE(&buffer[2], dlsi->byteCount);
|
|
Packit Service |
310c69 |
storeUInt32LE(&buffer[4], dlsi->index);
|
|
Packit Service |
310c69 |
return writeToBufferedWriter(bufferedWriter, buffer, sizeof(buffer));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
void flushDeltaList(DeltaMemory *deltaMemory, unsigned int flushIndex)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY((getField(deltaMemory->flags, flushIndex, 1) != 0),
|
|
Packit Service |
310c69 |
"flush bit is set");
|
|
Packit Service |
310c69 |
setZero(deltaMemory->flags, flushIndex, 1);
|
|
Packit Service |
310c69 |
deltaMemory->numTransfers--;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
DeltaList *deltaList = &deltaMemory->deltaLists[flushIndex + 1];
|
|
Packit Service |
310c69 |
DeltaListSaveInfo dlsi;
|
|
Packit Service |
310c69 |
dlsi.tag = deltaMemory->tag;
|
|
Packit Service |
310c69 |
dlsi.bitOffset = getDeltaListStart(deltaList) % CHAR_BIT;
|
|
Packit Service |
310c69 |
dlsi.byteCount = getDeltaListByteSize(deltaList);
|
|
Packit Service |
310c69 |
dlsi.index = deltaMemory->firstList + flushIndex;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
int result = writeDeltaListSaveInfo(deltaMemory->bufferedWriter, &dlsi);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
if (deltaMemory->transferStatus == UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
logWarningWithStringError(result, "failed to write delta list memory");
|
|
Packit Service |
310c69 |
deltaMemory->transferStatus = result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
result = writeToBufferedWriter(deltaMemory->bufferedWriter,
|
|
Packit Service |
310c69 |
deltaMemory->memory
|
|
Packit Service |
310c69 |
+ getDeltaListByteStart(deltaList),
|
|
Packit Service |
310c69 |
dlsi.byteCount);
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
if (deltaMemory->transferStatus == UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
logWarningWithStringError(result, "failed to write delta list memory");
|
|
Packit Service |
310c69 |
deltaMemory->transferStatus = result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int writeGuardDeltaList(BufferedWriter *bufferedWriter)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
DeltaListSaveInfo dlsi;
|
|
Packit Service |
310c69 |
dlsi.tag = 'z';
|
|
Packit Service |
310c69 |
dlsi.bitOffset = 0;
|
|
Packit Service |
310c69 |
dlsi.byteCount = 0;
|
|
Packit Service |
310c69 |
dlsi.index = 0;
|
|
Packit Service |
310c69 |
int result = writeToBufferedWriter(bufferedWriter, (const byte *) &dlsi,
|
|
Packit Service |
310c69 |
sizeof(DeltaListSaveInfo));
|
|
Packit Service |
310c69 |
if (result != UDS_SUCCESS) {
|
|
Packit Service |
310c69 |
logWarningWithStringError(result, "failed to write guard delta list");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return result;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int extendDeltaMemory(DeltaMemory *deltaMemory, unsigned int growingIndex,
|
|
Packit Service |
310c69 |
size_t growingSize, bool doCopy)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
if (!isMutable(deltaMemory)) {
|
|
Packit Service |
310c69 |
return logErrorWithStringError(UDS_BAD_STATE,
|
|
Packit Service |
310c69 |
"Attempt to read into an immutable delta"
|
|
Packit Service |
310c69 |
" list memory");
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
AbsTime startTime = currentTime(CLOCK_MONOTONIC);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// Calculate the amount of space that is in use. Include the space that
|
|
Packit Service |
310c69 |
// has a planned use.
|
|
Packit Service |
310c69 |
DeltaList *deltaLists = deltaMemory->deltaLists;
|
|
Packit Service |
310c69 |
size_t usedSpace = growingSize;
|
|
Packit Service |
310c69 |
unsigned int i;
|
|
Packit Service |
310c69 |
for (i = 0; i <= deltaMemory->numLists + 1; i++) {
|
|
Packit Service |
310c69 |
usedSpace += getDeltaListByteSize(&deltaLists[i]);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (deltaMemory->size < usedSpace) {
|
|
Packit Service |
310c69 |
return UDS_OVERFLOW;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// Compute the new offsets of the delta lists
|
|
Packit Service |
310c69 |
size_t spacing = (deltaMemory->size - usedSpace) / deltaMemory->numLists;
|
|
Packit Service |
310c69 |
deltaMemory->tempOffsets[0] = 0;
|
|
Packit Service |
310c69 |
for (i = 0; i <= deltaMemory->numLists; i++) {
|
|
Packit Service |
310c69 |
deltaMemory->tempOffsets[i + 1] = (deltaMemory->tempOffsets[i]
|
|
Packit Service |
310c69 |
+ getDeltaListByteSize(&deltaLists[i])
|
|
Packit Service |
310c69 |
+ spacing);
|
|
Packit Service |
310c69 |
deltaMemory->tempOffsets[i] *= CHAR_BIT;
|
|
Packit Service |
310c69 |
deltaMemory->tempOffsets[i]
|
|
Packit Service |
310c69 |
+= getDeltaListStart(&deltaLists[i]) % CHAR_BIT;
|
|
Packit Service |
310c69 |
if (i == 0) {
|
|
Packit Service |
310c69 |
deltaMemory->tempOffsets[i + 1] -= spacing / 2;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (i + 1 == growingIndex) {
|
|
Packit Service |
310c69 |
deltaMemory->tempOffsets[i + 1] += growingSize;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
deltaMemory->tempOffsets[deltaMemory->numLists + 1]
|
|
Packit Service |
310c69 |
= (deltaMemory->size * CHAR_BIT
|
|
Packit Service |
310c69 |
- getDeltaListSize(&deltaLists[deltaMemory->numLists + 1]));
|
|
Packit Service |
310c69 |
// When we rebalance the delta list, we will include the end guard list
|
|
Packit Service |
310c69 |
// in the rebalancing. It contains the end guard data, which must be
|
|
Packit Service |
310c69 |
// copied.
|
|
Packit Service |
310c69 |
if (doCopy) {
|
|
Packit Service |
310c69 |
rebalanceDeltaMemory(deltaMemory, 1, deltaMemory->numLists + 1);
|
|
Packit Service |
310c69 |
AbsTime endTime = currentTime(CLOCK_MONOTONIC);
|
|
Packit Service |
310c69 |
deltaMemory->rebalanceCount++;
|
|
Packit Service |
310c69 |
deltaMemory->rebalanceTime += timeDifference(endTime, startTime);
|
|
Packit Service |
310c69 |
} else {
|
|
Packit Service |
310c69 |
for (i = 1; i <= deltaMemory->numLists + 1; i++) {
|
|
Packit Service |
310c69 |
deltaLists[i].startOffset = deltaMemory->tempOffsets[i];
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
int validateDeltaLists(const DeltaMemory *deltaMemory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// Validate the delta index fields set by restoring a delta index
|
|
Packit Service |
310c69 |
if (deltaMemory->collisionCount > deltaMemory->recordCount) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(UDS_BAD_STATE,
|
|
Packit Service |
310c69 |
"delta index contains more collisions"
|
|
Packit Service |
310c69 |
" (%ld) than records (%ld)",
|
|
Packit Service |
310c69 |
deltaMemory->collisionCount,
|
|
Packit Service |
310c69 |
deltaMemory->recordCount);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// Validate the delta lists
|
|
Packit Service |
310c69 |
DeltaList *deltaLists = deltaMemory->deltaLists;
|
|
Packit Service |
310c69 |
if (getDeltaListStart(&deltaLists[0]) != 0) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(UDS_BAD_STATE,
|
|
Packit Service |
310c69 |
"the head guard delta list does not start"
|
|
Packit Service |
310c69 |
" at 0: %llu",
|
|
Packit Service |
310c69 |
getDeltaListStart(&deltaLists[0]));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
uint64_t numBits = getDeltaListEnd(&deltaLists[deltaMemory->numLists + 1]);
|
|
Packit Service |
310c69 |
if (numBits != deltaMemory->size * CHAR_BIT) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(UDS_BAD_STATE,
|
|
Packit Service |
310c69 |
"the tail guard delta list does not end "
|
|
Packit Service |
310c69 |
"at end of allocated memory: %" PRIu64
|
|
Packit Service |
310c69 |
" != %zd",
|
|
Packit Service |
310c69 |
numBits, deltaMemory->size * CHAR_BIT);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
int numGuardBits = getDeltaListSize(&deltaLists[deltaMemory->numLists + 1]);
|
|
Packit Service |
310c69 |
if (numGuardBits < GUARD_BITS) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(UDS_BAD_STATE,
|
|
Packit Service |
310c69 |
"the tail guard delta list does not "
|
|
Packit Service |
310c69 |
"contain sufficient guard bits: %d < %d",
|
|
Packit Service |
310c69 |
numGuardBits, GUARD_BITS);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
unsigned int i;
|
|
Packit Service |
310c69 |
for (i = 0; i <= deltaMemory->numLists + 1; i++) {
|
|
Packit Service |
310c69 |
if (getDeltaListStart(&deltaLists[i]) > getDeltaListEnd(&deltaLists[i])) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(UDS_BAD_STATE,
|
|
Packit Service |
310c69 |
"invalid delta list %u: [%" PRIu64
|
|
Packit Service |
310c69 |
", %llu)",
|
|
Packit Service |
310c69 |
i,
|
|
Packit Service |
310c69 |
getDeltaListStart(&deltaLists[i]),
|
|
Packit Service |
310c69 |
getDeltaListEnd(&deltaLists[i]));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (i > deltaMemory->numLists) {
|
|
Packit Service |
310c69 |
// The rest of the checks do not apply to the tail guard list
|
|
Packit Service |
310c69 |
continue;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (getDeltaListEnd(&deltaLists[i])
|
|
Packit Service |
310c69 |
> getDeltaListStart(&deltaLists[i + 1])) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(UDS_BAD_STATE,
|
|
Packit Service |
310c69 |
"delta lists %u and %u overlap: %"
|
|
Packit Service |
310c69 |
PRIu64 " > %llu",
|
|
Packit Service |
310c69 |
i, i + 1,
|
|
Packit Service |
310c69 |
getDeltaListEnd(&deltaLists[i]),
|
|
Packit Service |
310c69 |
getDeltaListStart(&deltaLists[i + 1]));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (i == 0) {
|
|
Packit Service |
310c69 |
// The rest of the checks do not apply to the head guard list
|
|
Packit Service |
310c69 |
continue;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
if (deltaLists[i].saveOffset > getDeltaListSize(&deltaLists[i])) {
|
|
Packit Service |
310c69 |
return logWarningWithStringError(UDS_BAD_STATE,
|
|
Packit Service |
310c69 |
"delta lists %u saved offset is larger"
|
|
Packit Service |
310c69 |
" than the list: %u > %u",
|
|
Packit Service |
310c69 |
i, deltaLists[i].saveOffset,
|
|
Packit Service |
310c69 |
getDeltaListSize(&deltaLists[i]));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return UDS_SUCCESS;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
size_t getDeltaMemoryAllocated(const DeltaMemory *deltaMemory)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return (deltaMemory->size
|
|
Packit Service |
310c69 |
+ getSizeOfDeltaLists(deltaMemory->numLists)
|
|
Packit Service |
310c69 |
+ getSizeOfFlags(deltaMemory->numLists)
|
|
Packit Service |
310c69 |
+ getSizeOfTempOffsets(deltaMemory->numLists));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**********************************************************************/
|
|
Packit Service |
310c69 |
size_t getDeltaMemorySize(unsigned long numEntries, unsigned int meanDelta,
|
|
Packit Service |
310c69 |
unsigned int numPayloadBits)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
unsigned short minBits;
|
|
Packit Service |
310c69 |
unsigned int incrKeys, minKeys;
|
|
Packit Service |
310c69 |
computeCodingConstants(meanDelta, &minBits, &minKeys, &incrKeys);
|
|
Packit Service |
310c69 |
// On average, each delta is encoded into about minBits+1.5 bits.
|
|
Packit Service |
310c69 |
return (numEntries * (numPayloadBits + minBits + 1) + numEntries / 2);
|
|
Packit Service |
310c69 |
}
|