/* * 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/uds-releases/jasper/src/uds/openChapterZone.h#1 $ */ #ifndef OPEN_CHAPTER_ZONE_H #define OPEN_CHAPTER_ZONE_H 1 #include "common.h" #include "geometry.h" #include "typeDefs.h" /** * OpenChapterZone is the mutable, in-memory representation of one zone's * section of an Albireo index chapter. * *
In addition to providing the same access to records as an on-disk * chapter, the open chapter zone must allow records to be added or * modified. It must provide a way to generate the on-disk representation * without excessive work. It does that by accumulating records in the order * they are added (maintaining temporal locality), and referencing them (as * record numbers) from hash slots selected from the name. If the metadata for * a name changes, the record field is just modified in place. * *
Storage for the records (names and metadata) is allocated when the zone * is created. It keeps no references to the data passed to it, and performs * no additional allocation when adding records. Opening a new chapter simply * marks it as being empty. * *
Records are stored in a flat array. To allow a value of zero in a * hash slot to indicate that the slot is empty, records are numbered starting * at one (1-based). Since C arrays are 0-based, the records array contains * enough space for N+1 records, and the record that starts at array index * zero is never used or referenced. * *
The array of hash slots is actually two arrays, superimposed: an
* array of record numbers, indexed by hash value, and an array of deleted
* flags, indexed by record number. This overlay is possible because the
* number of hash slots always exceeds the number of records, and is done
* simply to save on memory.
**/
enum {
OPEN_CHAPTER_RECORD_NUMBER_BITS = 23,
OPEN_CHAPTER_MAX_RECORD_NUMBER = (1 << OPEN_CHAPTER_RECORD_NUMBER_BITS) - 1
};
typedef struct {
/** If non-zero, the record number addressed by this hash slot */
unsigned int recordNumber : OPEN_CHAPTER_RECORD_NUMBER_BITS;
/** If true, the record at the index of this hash slot was deleted */
bool recordDeleted : 1;
} __attribute__((packed)) Slot;
typedef struct openChapterZone {
/** Maximum number of records that can be stored */
unsigned int capacity;
/** Number of records stored */
unsigned int size;
/** Number of deleted records */
unsigned int deleted;
/** Record data, stored as (name, metadata), 1-based */
UdsChunkRecord *records;
/** The number of slots in the chapter zone hash table. */
unsigned int slotCount;
/** Hash table, referencing virtual record numbers */
Slot slots[];
} OpenChapterZone;
/**
* Allocate an open chapter zone.
*
* @param geometry the geometry of the volume
* @param zoneCount the total number of open chapter zones
* @param openChapterPtr a pointer to hold the new open chapter
*
* @return UDS_SUCCESS or an error code
**/
int makeOpenChapter(const Geometry *geometry,
unsigned int zoneCount,
OpenChapterZone **openChapterPtr)
__attribute__((warn_unused_result));
/**
* Return the number of records in the open chapter zone that have not been
* deleted.
*
* @return the number of non-deleted records
**/
size_t openChapterSize(const OpenChapterZone *openChapter)
__attribute__((warn_unused_result));
/**
* Open a chapter by marking it empty.
*
* @param openChapter The chapter to open
**/
void resetOpenChapter(OpenChapterZone *openChapter);
/**
* Search the open chapter for a chunk name.
*
* @param openChapter The chapter to search
* @param name The name of the desired chunk
* @param metadata The holder for the metadata associated with the
* chunk, if found (or NULL)
* @param found A pointer which will be set to true if the chunk
* name was found
**/
void searchOpenChapter(OpenChapterZone *openChapter,
const UdsChunkName *name,
UdsChunkData *metadata,
bool *found);
/**
* Put a record into the open chapter.
*
* @param openChapter The chapter into which to put the record
* @param name The name of the record
* @param metadata The record data
* @param remaining Pointer to an integer set to the number of additional
* records that can be added to this chapter
*
* @return UDS_SUCCESS or an error code
**/
int putOpenChapter(OpenChapterZone *openChapter,
const UdsChunkName *name,
const UdsChunkData *metadata,
unsigned int *remaining)
__attribute__((warn_unused_result));
/**
* Remove a record from the open chapter.
*
* @param openChapter The chapter from which to remove the record
* @param name The name of the record
* @param removed Pointer to bool set to true
if the
* record was found
**/
void removeFromOpenChapter(OpenChapterZone *openChapter,
const UdsChunkName *name,
bool *removed);
/**
* Clean up an open chapter and its memory.
*
* @param openChapter the chapter to destroy
**/
void freeOpenChapter(OpenChapterZone *openChapter);
#endif /* OPEN_CHAPTER_ZONE_H */