/*
* Copyright (c) 2020 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/journalPoint.h#2 $
*/
#ifndef JOURNAL_POINT_H
#define JOURNAL_POINT_H
#include "numeric.h"
#include "types.h"
typedef uint16_t JournalEntryCount;
/**
* The absolute position of an entry in a recovery journal or slab journal.
**/
typedef struct {
SequenceNumber sequenceNumber;
JournalEntryCount entryCount;
} JournalPoint;
/**
* A packed, platform-independent encoding of a JournalPoint.
**/
typedef struct {
/**
* The packed representation is the little-endian 64-bit representation of
* the low-order 48 bits of the sequence number, shifted up 16 bits, or'ed
* with the 16-bit entry count.
*
* Very long-term, the top 16 bits of the sequence number may not always be
* zero, as this encoding assumes--see BZ 1523240.
**/
byte encodedPoint[8];
} __attribute__((packed)) PackedJournalPoint;
/**
* Move the given journal point forward by one entry.
*
* @param point the journal point to adjust
* @param entriesPerBlock the number of entries in one full block
**/
static inline void advanceJournalPoint(JournalPoint *point,
JournalEntryCount entriesPerBlock)
{
point->entryCount++;
if (point->entryCount == entriesPerBlock) {
point->sequenceNumber++;
point->entryCount = 0;
}
}
/**
* Check whether a journal point is valid.
*
* @param point the journal point
*
* @return true
if the journal point is valid
**/
static inline bool isValidJournalPoint(const JournalPoint *point)
{
return ((point != NULL) && (point->sequenceNumber > 0));
}
/**
* Check whether the first point precedes the second point.
*
* @param first the first journal point
* @param second the second journal point
*
* @return true
if the first point precedes the second point.
**/
static inline bool beforeJournalPoint(const JournalPoint *first,
const JournalPoint *second)
{
return ((first->sequenceNumber < second->sequenceNumber)
|| ((first->sequenceNumber == second->sequenceNumber)
&& (first->entryCount < second->entryCount)));
}
/**
* Check whether the first point is the same as the second point.
*
* @param first the first journal point
* @param second the second journal point
*
* @return true
if both points reference the same logical
* position of an entry the journal
**/
static inline bool areEquivalentJournalPoints(const JournalPoint *first,
const JournalPoint *second)
{
return ((first->sequenceNumber == second->sequenceNumber)
&& (first->entryCount == second->entryCount));
}
/**
* Encode the journal location represented by a JournalPoint into a
* PackedJournalPoint.
*
* @param unpacked The unpacked input point
* @param packed The packed output point
**/
static inline void packJournalPoint(const JournalPoint *unpacked,
PackedJournalPoint *packed)
{
uint64_t native = ((unpacked->sequenceNumber << 16) | unpacked->entryCount);
storeUInt64LE(packed->encodedPoint, native);
}
/**
* Decode the journal location represented by a PackedJournalPoint into a
* JournalPoint.
*
* @param packed The packed input point
* @param unpacked The unpacked output point
**/
static inline void unpackJournalPoint(const PackedJournalPoint *packed,
JournalPoint *unpacked)
{
uint64_t native = getUInt64LE(packed->encodedPoint);
unpacked->sequenceNumber = (native >> 16);
unpacked->entryCount = (native & 0xffff);
}
#endif // JOURNAL_POINT_H