/* * 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/indexComponent.h#5 $ */ #ifndef INDEX_COMPONENT_H #define INDEX_COMPONENT_H 1 #include "common.h" #include "bufferedReader.h" #include "bufferedWriter.h" #include "compiler.h" #include "regionIdentifiers.h" typedef enum completionStatus { CS_NOT_COMPLETED, // operation has not completed CS_JUST_COMPLETED, // operation just completed CS_COMPLETED_PREVIOUSLY // operation completed previously } CompletionStatus; typedef struct readPortal { struct indexComponent *component; BufferedReader **readers; unsigned int zones; } ReadPortal; /** * Prototype for functions which can load an index component from its * saved state. * * @param portal A component portal which can be used to load the * specified component. * @return UDS_SUCCESS or an error code **/ typedef int (*Loader)(ReadPortal *portal); /** * Prototype for functions which can save an index component. * * @param component The index component. * @param writer A buffered writer. * @param zone The zone number. * * @return UDS_SUCCESS or an error code **/ typedef int (*Saver)(struct indexComponent *component, BufferedWriter *writer, unsigned int zone); /** * Command code used by IncrementalWriter function protocol. **/ typedef enum incrementalWriterCommand { IWC_START, //< start an incremental save IWC_CONTINUE, //< continue an incremental save IWC_FINISH, //< force finish of incremental save IWC_ABORT, //< abort incremental save IWC_IDLE = -1,//< not a command, used internally to signify not in progress IWC_DONE = -2 //< not a command, used internally to signify async completion } IncrementalWriterCommand; typedef struct writeZone { struct indexComponent *component; IncrementalWriterCommand phase; BufferedWriter *writer; unsigned int zone; } WriteZone; /** * @param [in] component The index component. * @param [in] writer A buffered writer. * @param [in] zone The zone number (0 for non-multi-zone). * @param [in] command The incremental writer command. * @param [out] completed If non-NULL, set to whether save is done. * * @return UDS_SUCCESS or an error code **/ typedef int (*IncrementalWriter)(struct indexComponent *component, BufferedWriter *writer, unsigned int zone, IncrementalWriterCommand command, bool *completed); /** * The structure describing how to load or save an index component. * At least one of saver or incremental must be specified. **/ typedef struct indexComponentInfo { RegionKind kind; // Region kind const char *name; // The name of the component (for logging) bool saveOnly; // Used for saves but not checkpoints bool chapterSync; // Saved by the chapter writer bool multiZone; // Does this component have multiple zones? bool ioStorage; // Do we do I/O directly to storage? Loader loader; // The function load this component Saver saver; // The function to store this component IncrementalWriter incremental; // The function for incremental writing } IndexComponentInfo; /** * The structure representing a savable (and loadable) part of an index. **/ typedef struct indexComponent { const IndexComponentInfo *info; // IndexComponentInfo specification void *componentData; // The object to load or save void *context; // The context used to load or save struct indexState *state; // The index state unsigned int numZones; // Number of zones in write portal WriteZone **writeZones; // State for writing component } IndexComponent; /** * Make an index component * * @param state The index state in which this component instance * shall reside. * @param info The component info specification for this component. * @param zoneCount How many active zones are in use. * @param data Component-specific data. * @param context Component-specific context. * @param componentPtr Where to store the resulting component. * * @return UDS_SUCCESS or an error code **/ int makeIndexComponent(struct indexState *state, const IndexComponentInfo *info, unsigned int zoneCount, void *data, void *context, IndexComponent **componentPtr) __attribute__((warn_unused_result)); /** * Destroy and index component. * * @param componentPtr A pointer to the component to be freed. **/ void freeIndexComponent(IndexComponent **componentPtr); /** * Return the index component name for this component. **/ static INLINE const char *indexComponentName(IndexComponent *component) { return component->info->name; } /** * Return the index component data for this component. **/ static INLINE void *indexComponentData(IndexComponent *component) { return component->componentData; } /** * Return the index component context for this component. **/ static INLINE void *indexComponentContext(IndexComponent *component) { return component->context; } /** * Determine whether this component may be skipped for a checkpoint. * * @param component the component, * * @return whether the component may be skipped **/ static INLINE bool skipIndexComponentOnCheckpoint(IndexComponent *component) { return component->info->saveOnly; } /** * Determine whether actual saving during a checkpoint should be * invoked by the chapter writer thread. **/ static INLINE bool deferIndexComponentCheckpointToChapterWriter(IndexComponent *component) { return component->info->chapterSync; } /** * Determine whether a replay is required if component is missing. * * @param component the component * * @return whether the component is final (that is, contains shutdown state) **/ static INLINE bool missingIndexComponentRequiresReplay(IndexComponent *component) { return component->info->saveOnly; } /** * Read a component's state. * * @param component The component to read. * * @return UDS_SUCCESS, an error code from reading, or UDS_INVALID_ARGUMENT * if the component is NULL. **/ int readIndexComponent(IndexComponent *component) __attribute__((warn_unused_result)); /** * Write a state file. * * @param component The component to write * * @return UDS_SUCCESS, an error code from writing, or UDS_INVALID_ARGUMENT * if the component is NULL. **/ int writeIndexComponent(IndexComponent *component) __attribute__((warn_unused_result)); /** * Start an incremental save for this component (all zones). * * @param [in] component The index component. * * @return UDS_SUCCESS or an error code. **/ int startIndexComponentIncrementalSave(IndexComponent *component) __attribute__((warn_unused_result)); /** * Perform an incremental save for a component in a particular zone. * * @param [in] component The index component. * @param [in] zone The zone number. * @param [out] completed Pointer to hold completion status result. * * @return UDS_SUCCESS or an error code. * * @note If an incremental save is not supported, a regular * save will be performed if this is the first call in zone 0. **/ int performIndexComponentZoneSave(IndexComponent *component, unsigned int zone, CompletionStatus *completed) __attribute__((warn_unused_result)); /** * Perform an incremental save for a non-multizone component synchronized * with the chapter writer. * * @param component The index component. **/ int performIndexComponentChapterWriterSave(IndexComponent *component) __attribute__((warn_unused_result)); /** * Force the completion of an incremental save currently in progress in * a particular zone. * * @param [in] component The index component. * @param [in] zone The zone number. * @param [out] completed Pointer to hold completion status result. * * @return UDS_SUCCESS or an error code. **/ int finishIndexComponentZoneSave(IndexComponent *component, unsigned int zone, CompletionStatus *completed) __attribute__((warn_unused_result)); /** * Force the completion of an incremental save in all zones and complete * the overal save. * * @param [in] component The index component. * * @return UDS_SUCCESS or an error code. * * @note If all zones call finishIndexComponentZoneSave first, only * the common non-index-related completion code is required, * which protects access to the index data structures from the * invoking thread. **/ int finishIndexComponentIncrementalSave(IndexComponent *component) __attribute__((warn_unused_result)); /** * Abort the incremental save currently in progress in a particular zone. * * @param [in] component The index component. * @param [in] zone The zone number. * @param [out] completed Pointer to hold completion status result. * * @return UDS_SUCCESS or an error code. * * @note "Completed" in this case means completed or aborted. * Once any zone calls this function the entire save is * useless unless every zone indicates CS_COMPLETED_PREVIOUSLY. **/ int abortIndexComponentZoneSave(IndexComponent *component, unsigned int zone, CompletionStatus *completed) __attribute__((warn_unused_result)); /** * Abort an incremental save currently in progress * * @param [in] component The index component. * * @return UDS_SUCCESS or an error code. * * @note If all zones call abortIndexComponentZoneSave first, only * the common non-index-related completion code is required, * which protects access to the index data structures from the * invoking thread. **/ int abortIndexComponentIncrementalSave(IndexComponent *component) __attribute__((warn_unused_result)); /** * Remove or invalidate component state. * * @param component The component whose file is to be removed. If NULL * no action is taken. **/ __attribute__((warn_unused_result)) int discardIndexComponent(IndexComponent *component); /** * Get a buffered reader for the specified component part. * * @param [in] portal The component portal. * @param [in] part The component ordinal number. * @param [out] readerPtr Where to put the buffered reader. * * @return UDS_SUCCESS or an error code. * * @note the reader is managed by the component portal **/ __attribute__((warn_unused_result)) int getBufferedReaderForPortal(ReadPortal *portal, unsigned int part, BufferedReader **readerPtr); #endif /* INDEX_COMPONENT_H */